From 5283413055a84279ee4e594dc4b887dd0fab5370 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 9 Mar 2026 20:00:48 +0000 Subject: [PATCH 01/48] update codeql documentation --- .../codeql-changelog/codeql-cli-2.19.1.rst | 2 +- .../codeql-changelog/codeql-cli-2.21.3.rst | 2 +- .../codeql-changelog/codeql-cli-2.22.3.rst | 2 +- .../codeql-changelog/codeql-cli-2.23.1.rst | 4 +- .../codeql-changelog/codeql-cli-2.24.3.rst | 121 ++++++++++++++++++ .../codeql-changelog/index.rst | 1 + 6 files changed, 127 insertions(+), 5 deletions(-) create mode 100644 docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.3.rst diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst index f2948d0db67..39d4d36537c 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst @@ -129,7 +129,7 @@ Java/Kotlin """"""""""" * The Java extractor and QL libraries now support Java 23. -* Kotlin versions up to 2.1.0\ *x* are now supported. +* Kotlin versions up to 2.1.0*x* are now supported. Python """""" diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst index 71a8e3a6824..fffe94c04b8 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst @@ -144,7 +144,7 @@ New Features Java/Kotlin """"""""""" -* Kotlin versions up to 2.2.0\ *x* are now supported. Support for the Kotlin 1.5.x series is dropped (so the minimum Kotlin version is now 1.6.0). +* Kotlin versions up to 2.2.0*x* are now supported. Support for the Kotlin 1.5.x series is dropped (so the minimum Kotlin version is now 1.6.0). Swift """"" diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst index 4f1d34ff2dd..8e5a18a0c74 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst @@ -98,4 +98,4 @@ C/C++ Java/Kotlin """"""""""" -* Kotlin versions up to 2.2.2\ *x* are now supported. +* Kotlin versions up to 2.2.2*x* are now supported. diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst index ff22a3f647c..27f1eee84ed 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst @@ -88,7 +88,7 @@ JavaScript/TypeScript * Data flow is now tracked through the :code:`Promise.try` and :code:`Array.prototype.with` functions. * Query :code:`js/index-out-of-bounds` no longer produces a false-positive when a strictly-less-than check overrides a previous less-than-or-equal test. * The query :code:`js/remote-property-injection` now detects property injection vulnerabilities through object enumeration patterns such as :code:`Object.keys()`. -* The query "Permissive CORS configuration" (:code:`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite. Thank you to @maikypedia who `submitted the original experimental query `__! +* The query "Permissive CORS configuration" (:code:`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite. Thank you to @maikypedia who `submitted the original experimental query `__\ ! Python """""" @@ -126,7 +126,7 @@ Golang """""" * The second argument of the :code:`CreateTemp` function, from the :code:`os` package, is no longer a path-injection sink due to proper sanitization by Go. -* The query "Uncontrolled data used in path expression" (:code:`go/path-injection`) now detects sanitizing a path by adding :code:`os.PathSeparator` or ``\`` to the beginning. +* The query "Uncontrolled data used in path expression" (:code:`go/path-injection`) now detects sanitizing a path by adding :code:`os.PathSeparator` or :code:`\` to the beginning. Java/Kotlin """"""""""" diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.3.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.3.rst new file mode 100644 index 00000000000..7c4f99e10d2 --- /dev/null +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.3.rst @@ -0,0 +1,121 @@ +.. _codeql-cli-2.24.3: + +========================== +CodeQL 2.24.3 (2026-03-05) +========================== + +.. contents:: Contents + :depth: 2 + :local: + :backlinks: none + +This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog `__, `relevant GitHub Changelog updates `__, `changes in the CodeQL extension for Visual Studio Code `__, and the `CodeQL Action changelog `__. + +Security Coverage +----------------- + +CodeQL 2.24.3 runs a total of 491 security queries when configured with the Default suite (covering 166 CWE). The Extended suite enables an additional 135 queries (covering 35 more CWE). + +CodeQL CLI +---------- + +Bug Fixes +~~~~~~~~~ + +* Fixed a race condition that could cause flaky failures in overlay CodeQL tests. Test extraction now skips :code:`*.testproj` directories by name, preventing interference from concurrently cleaned-up test databases. +* Fixed spurious "OOPS" warnings that could appear in help output for commands using mutually exclusive option groups, such as :code:`codeql query run`. + +Query Packs +----------- + +Minor Analysis Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Java/Kotlin +""""""""""" + +* The Java extractor and QL libraries now support Java 26. +* Java analysis now selects the Java version to use informed by Maven POM files across all project modules. It also tries to use Java 17 or higher for all Maven projects if possible, for improved build compatibility. + +Rust +"""" + +* The macro resolution metric has been removed from :code:`rust/diagnostic/database-quality`. This metric was found to be an unreliable indicator of database quality in many cases, leading to false alarms on the tool status page. + +Language Libraries +------------------ + +Bug Fixes +~~~~~~~~~ + +C/C++ +""""" + +* The :code:`allowInterproceduralFlow` predicate of must-flow data flow configurations now correctly handles direct recursion. + +C# +"" + +* Fixed an issue where the body of a partial member could be extracted twice. When both a *defining* and an *implementing* declaration exist, only the *implementing* declaration is now extracted. + +Breaking Changes +~~~~~~~~~~~~~~~~ + +C/C++ +""""" + +* CodeQL version 2.24.2 accidentally introduced a syntactical breaking change to :code:`BarrierGuard<...>::getAnIndirectBarrierNode` and :code:`InstructionBarrierGuard<...>::getAnIndirectBarrierNode`. These breaking changes have now been reverted so that the original code compiles again. +* :code:`MustFlow`, the inter-procedural must-flow data flow analysis library, has been re-worked to use parameterized modules. Like in the case of data flow and taint tracking, instead of extending the :code:`MustFlowConfiguration` class, the user should now implement a module with the :code:`MustFlow::ConfigSig` signature, and instantiate the :code:`MustFlow::Global` parameterized module with the implemented module. + +Python +"""""" + +* The :code:`Metrics` library no longer contains code that depends on the points-to analysis. The removed functionality has instead been moved to the :code:`LegacyPointsTo` module, to classes like :code:`ModuleMetricsWithPointsTo` etc. If you depend on any of these classes, you must now remember to import :code:`LegacyPointsTo`, and use the appropriate types in order to use the points-to-based functionality. + +Major Analysis Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Python +"""""" + +* The CodeQL Python libraries have been updated to be compatible with overlay evaluation. This should result in a significant speedup on analyses for which a base database already exists. Note that it may be necessary to add :code:`overlay[local?] module;` to user-managed libraries that extend classes that are now marked as :code:`overlay[local]`. + +Minor Analysis Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +C/C++ +""""" + +* Refactored the "Year field changed using an arithmetic operation without checking for leap year" query (:code:`cpp/leap-year/unchecked-after-arithmetic-year-modification`) to address large numbers of false positive results. + +C# +"" + +* C# 14: Added support for partial events. +* C# 14: Added support for the :code:`field` keyword in properties. + +Java/Kotlin +""""""""""" + +* Some modelling which previously only worked for Java EE packages beginning with "javax" will now also work for Java EE packages beginning with "jakarta" as well. This may lead to some alert changes. + +JavaScript/TypeScript +""""""""""""""""""""" + +* Added support for React components wrapped by :code:`observer` from :code:`mobx-react` and :code:`mobx-react-lite`. + +Python +"""""" + +* Added new full SSRF sanitization barrier from the new AntiSSRF library. +* When a guard such as :code:`isSafe(x)` is defined, we now also automatically handle :code:`isSafe(x) == true` and :code:`isSafe(x) != false`. + +Ruby +"""" + +* We now track taint flow through :code:`Shellwords.escape` and :code:`Shellwords.shellescape` for all queries except command injection, for which they are sanitizers. + +Rust +"""" + +* Added support for neutral models (:code:`extensible: neutralModel`) to control where generated source, sink and flow summary models apply. diff --git a/docs/codeql/codeql-overview/codeql-changelog/index.rst b/docs/codeql/codeql-overview/codeql-changelog/index.rst index 21671f1c969..c128fe96410 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/index.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/index.rst @@ -11,6 +11,7 @@ A list of queries for each suite and language `is available here Date: Mon, 9 Mar 2026 15:32:42 -0500 Subject: [PATCH 02/48] Fix formatting issues in codeql-cli-2.23.1.rst --- .../codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst index 27f1eee84ed..ff22a3f647c 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst @@ -88,7 +88,7 @@ JavaScript/TypeScript * Data flow is now tracked through the :code:`Promise.try` and :code:`Array.prototype.with` functions. * Query :code:`js/index-out-of-bounds` no longer produces a false-positive when a strictly-less-than check overrides a previous less-than-or-equal test. * The query :code:`js/remote-property-injection` now detects property injection vulnerabilities through object enumeration patterns such as :code:`Object.keys()`. -* The query "Permissive CORS configuration" (:code:`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite. Thank you to @maikypedia who `submitted the original experimental query `__\ ! +* The query "Permissive CORS configuration" (:code:`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite. Thank you to @maikypedia who `submitted the original experimental query `__! Python """""" @@ -126,7 +126,7 @@ Golang """""" * The second argument of the :code:`CreateTemp` function, from the :code:`os` package, is no longer a path-injection sink due to proper sanitization by Go. -* The query "Uncontrolled data used in path expression" (:code:`go/path-injection`) now detects sanitizing a path by adding :code:`os.PathSeparator` or :code:`\` to the beginning. +* The query "Uncontrolled data used in path expression" (:code:`go/path-injection`) now detects sanitizing a path by adding :code:`os.PathSeparator` or ``\`` to the beginning. Java/Kotlin """"""""""" From 5921dacf528820a4e462b1037755d87401fe85fd Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Mon, 9 Mar 2026 15:33:08 -0500 Subject: [PATCH 03/48] Fix formatting of Kotlin version support note --- .../codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst index 8e5a18a0c74..4f1d34ff2dd 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst @@ -98,4 +98,4 @@ C/C++ Java/Kotlin """"""""""" -* Kotlin versions up to 2.2.2*x* are now supported. +* Kotlin versions up to 2.2.2\ *x* are now supported. From 216bc7669424bb67fa206b8fbca8353ec3ee0b78 Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Mon, 9 Mar 2026 15:34:07 -0500 Subject: [PATCH 04/48] Fix formatting in Kotlin version support note --- .../codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst index fffe94c04b8..71a8e3a6824 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst @@ -144,7 +144,7 @@ New Features Java/Kotlin """"""""""" -* Kotlin versions up to 2.2.0*x* are now supported. Support for the Kotlin 1.5.x series is dropped (so the minimum Kotlin version is now 1.6.0). +* Kotlin versions up to 2.2.0\ *x* are now supported. Support for the Kotlin 1.5.x series is dropped (so the minimum Kotlin version is now 1.6.0). Swift """"" From f5545516dbb873153b7bb2496d44ec7e6bcd3343 Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Mon, 9 Mar 2026 15:34:27 -0500 Subject: [PATCH 05/48] Fix formatting in codeql-cli-2.19.1.rst --- .../codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst index 39d4d36537c..f2948d0db67 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst @@ -129,7 +129,7 @@ Java/Kotlin """"""""""" * The Java extractor and QL libraries now support Java 23. -* Kotlin versions up to 2.1.0*x* are now supported. +* Kotlin versions up to 2.1.0\ *x* are now supported. Python """""" From eea61ea821c2f966d61b03421b1ec3bd2bc161ca Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Mon, 9 Mar 2026 16:55:09 -0500 Subject: [PATCH 06/48] Revert "Update changelog documentation site for codeql-cli-2.24.3" --- .../codeql-changelog/codeql-cli-2.24.3.rst | 121 ------------------ .../codeql-changelog/index.rst | 1 - 2 files changed, 122 deletions(-) delete mode 100644 docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.3.rst diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.3.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.3.rst deleted file mode 100644 index 7c4f99e10d2..00000000000 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.3.rst +++ /dev/null @@ -1,121 +0,0 @@ -.. _codeql-cli-2.24.3: - -========================== -CodeQL 2.24.3 (2026-03-05) -========================== - -.. contents:: Contents - :depth: 2 - :local: - :backlinks: none - -This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog `__, `relevant GitHub Changelog updates `__, `changes in the CodeQL extension for Visual Studio Code `__, and the `CodeQL Action changelog `__. - -Security Coverage ------------------ - -CodeQL 2.24.3 runs a total of 491 security queries when configured with the Default suite (covering 166 CWE). The Extended suite enables an additional 135 queries (covering 35 more CWE). - -CodeQL CLI ----------- - -Bug Fixes -~~~~~~~~~ - -* Fixed a race condition that could cause flaky failures in overlay CodeQL tests. Test extraction now skips :code:`*.testproj` directories by name, preventing interference from concurrently cleaned-up test databases. -* Fixed spurious "OOPS" warnings that could appear in help output for commands using mutually exclusive option groups, such as :code:`codeql query run`. - -Query Packs ------------ - -Minor Analysis Improvements -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Java/Kotlin -""""""""""" - -* The Java extractor and QL libraries now support Java 26. -* Java analysis now selects the Java version to use informed by Maven POM files across all project modules. It also tries to use Java 17 or higher for all Maven projects if possible, for improved build compatibility. - -Rust -"""" - -* The macro resolution metric has been removed from :code:`rust/diagnostic/database-quality`. This metric was found to be an unreliable indicator of database quality in many cases, leading to false alarms on the tool status page. - -Language Libraries ------------------- - -Bug Fixes -~~~~~~~~~ - -C/C++ -""""" - -* The :code:`allowInterproceduralFlow` predicate of must-flow data flow configurations now correctly handles direct recursion. - -C# -"" - -* Fixed an issue where the body of a partial member could be extracted twice. When both a *defining* and an *implementing* declaration exist, only the *implementing* declaration is now extracted. - -Breaking Changes -~~~~~~~~~~~~~~~~ - -C/C++ -""""" - -* CodeQL version 2.24.2 accidentally introduced a syntactical breaking change to :code:`BarrierGuard<...>::getAnIndirectBarrierNode` and :code:`InstructionBarrierGuard<...>::getAnIndirectBarrierNode`. These breaking changes have now been reverted so that the original code compiles again. -* :code:`MustFlow`, the inter-procedural must-flow data flow analysis library, has been re-worked to use parameterized modules. Like in the case of data flow and taint tracking, instead of extending the :code:`MustFlowConfiguration` class, the user should now implement a module with the :code:`MustFlow::ConfigSig` signature, and instantiate the :code:`MustFlow::Global` parameterized module with the implemented module. - -Python -"""""" - -* The :code:`Metrics` library no longer contains code that depends on the points-to analysis. The removed functionality has instead been moved to the :code:`LegacyPointsTo` module, to classes like :code:`ModuleMetricsWithPointsTo` etc. If you depend on any of these classes, you must now remember to import :code:`LegacyPointsTo`, and use the appropriate types in order to use the points-to-based functionality. - -Major Analysis Improvements -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Python -"""""" - -* The CodeQL Python libraries have been updated to be compatible with overlay evaluation. This should result in a significant speedup on analyses for which a base database already exists. Note that it may be necessary to add :code:`overlay[local?] module;` to user-managed libraries that extend classes that are now marked as :code:`overlay[local]`. - -Minor Analysis Improvements -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -C/C++ -""""" - -* Refactored the "Year field changed using an arithmetic operation without checking for leap year" query (:code:`cpp/leap-year/unchecked-after-arithmetic-year-modification`) to address large numbers of false positive results. - -C# -"" - -* C# 14: Added support for partial events. -* C# 14: Added support for the :code:`field` keyword in properties. - -Java/Kotlin -""""""""""" - -* Some modelling which previously only worked for Java EE packages beginning with "javax" will now also work for Java EE packages beginning with "jakarta" as well. This may lead to some alert changes. - -JavaScript/TypeScript -""""""""""""""""""""" - -* Added support for React components wrapped by :code:`observer` from :code:`mobx-react` and :code:`mobx-react-lite`. - -Python -"""""" - -* Added new full SSRF sanitization barrier from the new AntiSSRF library. -* When a guard such as :code:`isSafe(x)` is defined, we now also automatically handle :code:`isSafe(x) == true` and :code:`isSafe(x) != false`. - -Ruby -"""" - -* We now track taint flow through :code:`Shellwords.escape` and :code:`Shellwords.shellescape` for all queries except command injection, for which they are sanitizers. - -Rust -"""" - -* Added support for neutral models (:code:`extensible: neutralModel`) to control where generated source, sink and flow summary models apply. diff --git a/docs/codeql/codeql-overview/codeql-changelog/index.rst b/docs/codeql/codeql-overview/codeql-changelog/index.rst index c128fe96410..21671f1c969 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/index.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/index.rst @@ -11,7 +11,6 @@ A list of queries for each suite and language `is available here Date: Mon, 9 Mar 2026 22:17:15 +0000 Subject: [PATCH 07/48] update codeql documentation --- .../codeql-changelog/codeql-cli-2.19.1.rst | 2 +- .../codeql-changelog/codeql-cli-2.21.3.rst | 2 +- .../codeql-changelog/codeql-cli-2.22.3.rst | 2 +- .../codeql-changelog/codeql-cli-2.23.1.rst | 4 +- .../codeql-changelog/codeql-cli-2.24.3.rst | 121 ++++++++++++++++++ .../codeql-changelog/index.rst | 1 + 6 files changed, 127 insertions(+), 5 deletions(-) create mode 100644 docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.3.rst diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst index f2948d0db67..39d4d36537c 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst @@ -129,7 +129,7 @@ Java/Kotlin """"""""""" * The Java extractor and QL libraries now support Java 23. -* Kotlin versions up to 2.1.0\ *x* are now supported. +* Kotlin versions up to 2.1.0*x* are now supported. Python """""" diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst index 71a8e3a6824..fffe94c04b8 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst @@ -144,7 +144,7 @@ New Features Java/Kotlin """"""""""" -* Kotlin versions up to 2.2.0\ *x* are now supported. Support for the Kotlin 1.5.x series is dropped (so the minimum Kotlin version is now 1.6.0). +* Kotlin versions up to 2.2.0*x* are now supported. Support for the Kotlin 1.5.x series is dropped (so the minimum Kotlin version is now 1.6.0). Swift """"" diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst index 4f1d34ff2dd..8e5a18a0c74 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst @@ -98,4 +98,4 @@ C/C++ Java/Kotlin """"""""""" -* Kotlin versions up to 2.2.2\ *x* are now supported. +* Kotlin versions up to 2.2.2*x* are now supported. diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst index ff22a3f647c..27f1eee84ed 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst @@ -88,7 +88,7 @@ JavaScript/TypeScript * Data flow is now tracked through the :code:`Promise.try` and :code:`Array.prototype.with` functions. * Query :code:`js/index-out-of-bounds` no longer produces a false-positive when a strictly-less-than check overrides a previous less-than-or-equal test. * The query :code:`js/remote-property-injection` now detects property injection vulnerabilities through object enumeration patterns such as :code:`Object.keys()`. -* The query "Permissive CORS configuration" (:code:`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite. Thank you to @maikypedia who `submitted the original experimental query `__! +* The query "Permissive CORS configuration" (:code:`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite. Thank you to @maikypedia who `submitted the original experimental query `__\ ! Python """""" @@ -126,7 +126,7 @@ Golang """""" * The second argument of the :code:`CreateTemp` function, from the :code:`os` package, is no longer a path-injection sink due to proper sanitization by Go. -* The query "Uncontrolled data used in path expression" (:code:`go/path-injection`) now detects sanitizing a path by adding :code:`os.PathSeparator` or ``\`` to the beginning. +* The query "Uncontrolled data used in path expression" (:code:`go/path-injection`) now detects sanitizing a path by adding :code:`os.PathSeparator` or :code:`\` to the beginning. Java/Kotlin """"""""""" diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.3.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.3.rst new file mode 100644 index 00000000000..7c4f99e10d2 --- /dev/null +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.3.rst @@ -0,0 +1,121 @@ +.. _codeql-cli-2.24.3: + +========================== +CodeQL 2.24.3 (2026-03-05) +========================== + +.. contents:: Contents + :depth: 2 + :local: + :backlinks: none + +This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog `__, `relevant GitHub Changelog updates `__, `changes in the CodeQL extension for Visual Studio Code `__, and the `CodeQL Action changelog `__. + +Security Coverage +----------------- + +CodeQL 2.24.3 runs a total of 491 security queries when configured with the Default suite (covering 166 CWE). The Extended suite enables an additional 135 queries (covering 35 more CWE). + +CodeQL CLI +---------- + +Bug Fixes +~~~~~~~~~ + +* Fixed a race condition that could cause flaky failures in overlay CodeQL tests. Test extraction now skips :code:`*.testproj` directories by name, preventing interference from concurrently cleaned-up test databases. +* Fixed spurious "OOPS" warnings that could appear in help output for commands using mutually exclusive option groups, such as :code:`codeql query run`. + +Query Packs +----------- + +Minor Analysis Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Java/Kotlin +""""""""""" + +* The Java extractor and QL libraries now support Java 26. +* Java analysis now selects the Java version to use informed by Maven POM files across all project modules. It also tries to use Java 17 or higher for all Maven projects if possible, for improved build compatibility. + +Rust +"""" + +* The macro resolution metric has been removed from :code:`rust/diagnostic/database-quality`. This metric was found to be an unreliable indicator of database quality in many cases, leading to false alarms on the tool status page. + +Language Libraries +------------------ + +Bug Fixes +~~~~~~~~~ + +C/C++ +""""" + +* The :code:`allowInterproceduralFlow` predicate of must-flow data flow configurations now correctly handles direct recursion. + +C# +"" + +* Fixed an issue where the body of a partial member could be extracted twice. When both a *defining* and an *implementing* declaration exist, only the *implementing* declaration is now extracted. + +Breaking Changes +~~~~~~~~~~~~~~~~ + +C/C++ +""""" + +* CodeQL version 2.24.2 accidentally introduced a syntactical breaking change to :code:`BarrierGuard<...>::getAnIndirectBarrierNode` and :code:`InstructionBarrierGuard<...>::getAnIndirectBarrierNode`. These breaking changes have now been reverted so that the original code compiles again. +* :code:`MustFlow`, the inter-procedural must-flow data flow analysis library, has been re-worked to use parameterized modules. Like in the case of data flow and taint tracking, instead of extending the :code:`MustFlowConfiguration` class, the user should now implement a module with the :code:`MustFlow::ConfigSig` signature, and instantiate the :code:`MustFlow::Global` parameterized module with the implemented module. + +Python +"""""" + +* The :code:`Metrics` library no longer contains code that depends on the points-to analysis. The removed functionality has instead been moved to the :code:`LegacyPointsTo` module, to classes like :code:`ModuleMetricsWithPointsTo` etc. If you depend on any of these classes, you must now remember to import :code:`LegacyPointsTo`, and use the appropriate types in order to use the points-to-based functionality. + +Major Analysis Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Python +"""""" + +* The CodeQL Python libraries have been updated to be compatible with overlay evaluation. This should result in a significant speedup on analyses for which a base database already exists. Note that it may be necessary to add :code:`overlay[local?] module;` to user-managed libraries that extend classes that are now marked as :code:`overlay[local]`. + +Minor Analysis Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +C/C++ +""""" + +* Refactored the "Year field changed using an arithmetic operation without checking for leap year" query (:code:`cpp/leap-year/unchecked-after-arithmetic-year-modification`) to address large numbers of false positive results. + +C# +"" + +* C# 14: Added support for partial events. +* C# 14: Added support for the :code:`field` keyword in properties. + +Java/Kotlin +""""""""""" + +* Some modelling which previously only worked for Java EE packages beginning with "javax" will now also work for Java EE packages beginning with "jakarta" as well. This may lead to some alert changes. + +JavaScript/TypeScript +""""""""""""""""""""" + +* Added support for React components wrapped by :code:`observer` from :code:`mobx-react` and :code:`mobx-react-lite`. + +Python +"""""" + +* Added new full SSRF sanitization barrier from the new AntiSSRF library. +* When a guard such as :code:`isSafe(x)` is defined, we now also automatically handle :code:`isSafe(x) == true` and :code:`isSafe(x) != false`. + +Ruby +"""" + +* We now track taint flow through :code:`Shellwords.escape` and :code:`Shellwords.shellescape` for all queries except command injection, for which they are sanitizers. + +Rust +"""" + +* Added support for neutral models (:code:`extensible: neutralModel`) to control where generated source, sink and flow summary models apply. diff --git a/docs/codeql/codeql-overview/codeql-changelog/index.rst b/docs/codeql/codeql-overview/codeql-changelog/index.rst index 21671f1c969..c128fe96410 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/index.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/index.rst @@ -11,6 +11,7 @@ A list of queries for each suite and language `is available here Date: Mon, 9 Mar 2026 17:19:18 -0500 Subject: [PATCH 08/48] Fix formatting for Kotlin version support note --- .../codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst index 39d4d36537c..f2948d0db67 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst @@ -129,7 +129,7 @@ Java/Kotlin """"""""""" * The Java extractor and QL libraries now support Java 23. -* Kotlin versions up to 2.1.0*x* are now supported. +* Kotlin versions up to 2.1.0\ *x* are now supported. Python """""" From f52195e96d688c7712c276488bf823150148b179 Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Mon, 9 Mar 2026 17:19:36 -0500 Subject: [PATCH 09/48] Fix formatting in Kotlin version support note --- .../codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst index fffe94c04b8..71a8e3a6824 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst @@ -144,7 +144,7 @@ New Features Java/Kotlin """"""""""" -* Kotlin versions up to 2.2.0*x* are now supported. Support for the Kotlin 1.5.x series is dropped (so the minimum Kotlin version is now 1.6.0). +* Kotlin versions up to 2.2.0\ *x* are now supported. Support for the Kotlin 1.5.x series is dropped (so the minimum Kotlin version is now 1.6.0). Swift """"" From 87ec22db655d970f7f4094f111985d498c3d5a4a Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Mon, 9 Mar 2026 17:19:56 -0500 Subject: [PATCH 10/48] Fix formatting of Kotlin version support note --- .../codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst index 8e5a18a0c74..4f1d34ff2dd 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst @@ -98,4 +98,4 @@ C/C++ Java/Kotlin """"""""""" -* Kotlin versions up to 2.2.2*x* are now supported. +* Kotlin versions up to 2.2.2\ *x* are now supported. From b7a5b08d61605438f419049971bb5514cc9eddab Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Mon, 9 Mar 2026 17:20:34 -0500 Subject: [PATCH 11/48] Fix formatting issues in codeql-cli-2.23.1.rst --- .../codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst index 27f1eee84ed..ff22a3f647c 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst @@ -88,7 +88,7 @@ JavaScript/TypeScript * Data flow is now tracked through the :code:`Promise.try` and :code:`Array.prototype.with` functions. * Query :code:`js/index-out-of-bounds` no longer produces a false-positive when a strictly-less-than check overrides a previous less-than-or-equal test. * The query :code:`js/remote-property-injection` now detects property injection vulnerabilities through object enumeration patterns such as :code:`Object.keys()`. -* The query "Permissive CORS configuration" (:code:`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite. Thank you to @maikypedia who `submitted the original experimental query `__\ ! +* The query "Permissive CORS configuration" (:code:`js/cors-permissive-configuration`) has been promoted from experimental and is now part of the default security suite. Thank you to @maikypedia who `submitted the original experimental query `__! Python """""" @@ -126,7 +126,7 @@ Golang """""" * The second argument of the :code:`CreateTemp` function, from the :code:`os` package, is no longer a path-injection sink due to proper sanitization by Go. -* The query "Uncontrolled data used in path expression" (:code:`go/path-injection`) now detects sanitizing a path by adding :code:`os.PathSeparator` or :code:`\` to the beginning. +* The query "Uncontrolled data used in path expression" (:code:`go/path-injection`) now detects sanitizing a path by adding :code:`os.PathSeparator` or ``\`` to the beginning. Java/Kotlin """"""""""" From 6c792e69b341de543d31598c63acbc8fa4cba429 Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Wed, 11 Mar 2026 13:53:24 -0700 Subject: [PATCH 12/48] Expose the indirection index --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll index fe954c640d1..d1eccf8c1cc 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll @@ -767,10 +767,11 @@ module Public { */ class UninitializedNode extends Node { LocalVariable v; + int indirectionIndex; UninitializedNode() { exists(SsaImpl::Definition def, SsaImpl::SourceVariable sv | - def.getIndirectionIndex() = 0 and + def.getIndirectionIndex() = indirectionIndex and def.getValue().asInstruction() instanceof UninitializedInstruction and SsaImpl::defToNode(this, def, sv) and v = sv.getBaseVariable().(SsaImpl::BaseIRVariable).getIRVariable().getAst() @@ -779,6 +780,9 @@ module Public { /** Gets the uninitialized local variable corresponding to this node. */ LocalVariable getLocalVariable() { result = v } + + /** Gets the level of indirection to get to this node. */ + int getIndirectionIndex() { result = indirectionIndex } } /** From 8c03136c252e22cc062b63f132d89235b3354633 Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Fri, 13 Mar 2026 10:11:40 -0700 Subject: [PATCH 13/48] Revert "Expose the indirection index" This reverts commit 6c792e69b341de543d31598c63acbc8fa4cba429. --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll index d1eccf8c1cc..fe954c640d1 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll @@ -767,11 +767,10 @@ module Public { */ class UninitializedNode extends Node { LocalVariable v; - int indirectionIndex; UninitializedNode() { exists(SsaImpl::Definition def, SsaImpl::SourceVariable sv | - def.getIndirectionIndex() = indirectionIndex and + def.getIndirectionIndex() = 0 and def.getValue().asInstruction() instanceof UninitializedInstruction and SsaImpl::defToNode(this, def, sv) and v = sv.getBaseVariable().(SsaImpl::BaseIRVariable).getIRVariable().getAst() @@ -780,9 +779,6 @@ module Public { /** Gets the uninitialized local variable corresponding to this node. */ LocalVariable getLocalVariable() { result = v } - - /** Gets the level of indirection to get to this node. */ - int getIndirectionIndex() { result = indirectionIndex } } /** From d3066af2e2ca786bca7cc16c65613f07720c9ffc Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Fri, 13 Mar 2026 11:39:57 -0700 Subject: [PATCH 14/48] Create `IndirectUninitializedNode` and add a bridge from it to `LocalVariable` This way the changes do not alter the meaning of `UninitializedNode`. In the meantime, the code still provides a specialized `Node` type `IndirectUninitializedNode` to access the nodes behind levels of indirection. --- .../ir/dataflow/internal/DataFlowNodes.qll | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll index fe954c640d1..6b201a7aa8b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll @@ -617,6 +617,25 @@ module Public { */ LocalVariable asUninitialized() { result = this.(UninitializedNode).getLocalVariable() } + /** + * Gets the uninitialized local variable corresponding to this node behind + * the given levels of indirection, if any. + */ + LocalVariable asIndirectUninitialized(int indirectionIndex) { + exists(IndirectUninitializedNode indirectUninitializedNode | + this = indirectUninitializedNode and + indirectUninitializedNode.getIndirectionIndex() = indirectionIndex + | + result = indirectUninitializedNode.getLocalVariable() + ) + } + + /** + * Gets the uninitialized local variable corresponding to this node behind + * any levels of indirection, if any. + */ + LocalVariable asIndirectUninitialized() { result = this.asIndirectUninitialized(_) } + /** * Gets the positional parameter corresponding to the node that represents * the value of the parameter after `index` number of loads, if any. For @@ -781,6 +800,34 @@ module Public { LocalVariable getLocalVariable() { result = v } } + /** + * The value of an uninitialized local variable behind one or more levels of + * indirection, viewed as a node in a data flow graph. + * + * NOTE: For the direct value of the uninitialized local variable, see + * `UninitializedNode`. + */ + class IndirectUninitializedNode extends Node { + LocalVariable v; + int indirectionIndex; + + IndirectUninitializedNode() { + exists(SsaImpl::Definition def, SsaImpl::SourceVariable sv | + def.getIndirectionIndex() = indirectionIndex and + indirectionIndex > 0 and // With `indirectionIndex` = 0, this class becomes the same as `UninitializedNode`. + def.getValue().asInstruction() instanceof UninitializedInstruction and + SsaImpl::defToNode(this, def, sv) and + v = sv.getBaseVariable().(SsaImpl::BaseIRVariable).getIRVariable().getAst() + ) + } + + /** Gets the uninitialized local variable corresponding to this node. */ + LocalVariable getLocalVariable() { result = v } + + /** Gets the level of indirection to get to this node. */ + int getIndirectionIndex() { result = indirectionIndex } + } + /** * The value of a parameter at function entry, viewed as a node in a data * flow graph. This includes both explicit parameters such as `x` in `f(x)` From 3f9ad144737a814b69766e1d218b073a06759eec Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Mon, 16 Mar 2026 14:11:34 -0700 Subject: [PATCH 15/48] Factor out common code into an abstract private class --- .../ir/dataflow/internal/DataFlowNodes.qll | 37 +++++++------------ 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll index 6b201a7aa8b..51cc7430f62 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll @@ -780,16 +780,13 @@ module Public { final override Type getType() { result = this.getPreUpdateNode().getType() } } - /** - * The value of an uninitialized local variable, viewed as a node in a data - * flow graph. - */ - class UninitializedNode extends Node { + abstract private class AbstractUninitializedNode extends Node { LocalVariable v; + int indirectionIndex; - UninitializedNode() { + AbstractUninitializedNode() { exists(SsaImpl::Definition def, SsaImpl::SourceVariable sv | - def.getIndirectionIndex() = 0 and + def.getIndirectionIndex() = indirectionIndex and def.getValue().asInstruction() instanceof UninitializedInstruction and SsaImpl::defToNode(this, def, sv) and v = sv.getBaseVariable().(SsaImpl::BaseIRVariable).getIRVariable().getAst() @@ -800,6 +797,14 @@ module Public { LocalVariable getLocalVariable() { result = v } } + /** + * The value of an uninitialized local variable, viewed as a node in a data + * flow graph. + */ + class UninitializedNode extends AbstractUninitializedNode { + UninitializedNode() { indirectionIndex = 0 } + } + /** * The value of an uninitialized local variable behind one or more levels of * indirection, viewed as a node in a data flow graph. @@ -807,22 +812,8 @@ module Public { * NOTE: For the direct value of the uninitialized local variable, see * `UninitializedNode`. */ - class IndirectUninitializedNode extends Node { - LocalVariable v; - int indirectionIndex; - - IndirectUninitializedNode() { - exists(SsaImpl::Definition def, SsaImpl::SourceVariable sv | - def.getIndirectionIndex() = indirectionIndex and - indirectionIndex > 0 and // With `indirectionIndex` = 0, this class becomes the same as `UninitializedNode`. - def.getValue().asInstruction() instanceof UninitializedInstruction and - SsaImpl::defToNode(this, def, sv) and - v = sv.getBaseVariable().(SsaImpl::BaseIRVariable).getIRVariable().getAst() - ) - } - - /** Gets the uninitialized local variable corresponding to this node. */ - LocalVariable getLocalVariable() { result = v } + class IndirectUninitializedNode extends AbstractUninitializedNode { + IndirectUninitializedNode() { indirectionIndex > 0 } /** Gets the level of indirection to get to this node. */ int getIndirectionIndex() { result = indirectionIndex } From 750f1ae8e9b34ec6475daea1cd010dc5a684d391 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 19 Mar 2026 10:18:42 +0100 Subject: [PATCH 16/48] Ruby: Use empty DB stats --- ruby/ql/lib/ruby.dbscheme.stats | 21832 +----------------------------- 1 file changed, 2 insertions(+), 21830 deletions(-) diff --git a/ruby/ql/lib/ruby.dbscheme.stats b/ruby/ql/lib/ruby.dbscheme.stats index 468bd72c780..9995467e33e 100644 --- a/ruby/ql/lib/ruby.dbscheme.stats +++ b/ruby/ql/lib/ruby.dbscheme.stats @@ -1,21832 +1,4 @@ - - @diagnostic_debug - 0 - - - @diagnostic_error - 0 - - - @diagnostic_info - 0 - - - @diagnostic_warning - 188 - - - @erb_comment_directive - 26 - - - @erb_directive - 1108 - - - @erb_graphql_directive - 0 - - - @erb_output_directive - 3270 - - - @erb_reserved_word - 8756 - - - @erb_template - 1508 - - - @erb_token_code - 4378 - - - @erb_token_comment - 26 - - - @erb_token_content - 4555 - - - @file - 18724 - - - @folder - 5165 - - - @location_default - 9223392 - - - @ruby_alias - 1289 - - - @ruby_alternative_pattern - 9 - - - @ruby_argument_list - 706474 - - - @ruby_array - 249320 - - - @ruby_array_pattern - 179 - - - @ruby_as_pattern - 156 - - - @ruby_assignment - 141202 - - - @ruby_bare_string - 13136 - - - @ruby_bare_symbol - 8435 - - - @ruby_begin - 2610 - - - @ruby_begin_block - 10 - - - @ruby_binary_ampersand - 630 - - - @ruby_binary_ampersandampersand - 8142 - - - @ruby_binary_and - 1189 - - - @ruby_binary_bangequal - 1434 - - - @ruby_binary_bangtilde - 176 - - - @ruby_binary_caret - 153 - - - @ruby_binary_equalequal - 33761 - - - @ruby_binary_equalequalequal - 689 - - - @ruby_binary_equaltilde - 1823 - - - @ruby_binary_langle - 1101 - - - @ruby_binary_langleequal - 431 - - - @ruby_binary_langleequalrangle - 764 - - - @ruby_binary_langlelangle - 10779 - - - @ruby_binary_minus - 2747 - - - @ruby_binary_or - 647 - - - @ruby_binary_percent - 986 - - - @ruby_binary_pipe - 1058 - - - @ruby_binary_pipepipe - 7336 - - - @ruby_binary_plus - 6593 - - - @ruby_binary_rangle - 2114 - - - @ruby_binary_rangleequal - 597 - - - @ruby_binary_ranglerangle - 259 - - - @ruby_binary_slash - 1169 - - - @ruby_binary_star - 3490 - - - @ruby_binary_starstar - 1227 - - - @ruby_block - 104143 - - - @ruby_block_argument - 6547 - - - @ruby_block_body - 103820 - - - @ruby_block_parameter - 2543 - - - @ruby_block_parameters - 25884 - - - @ruby_body_statement - 213896 - - - @ruby_break - 3414 - - - @ruby_call - 1027501 - - - @ruby_case__ - 1319 - - - @ruby_case_match - 232 - - - @ruby_chained_string - 884 - - - @ruby_class - 17441 - - - @ruby_complex - 72 - - - @ruby_conditional - 2896 - - - @ruby_delimited_symbol - 1247 - - - @ruby_destructured_left_assignment - 108 - - - @ruby_destructured_parameter - 208 - - - @ruby_do - 1675 - - - @ruby_do_block - 145534 - - - @ruby_element_reference - 82606 - - - @ruby_else - 7681 - - - @ruby_elsif - 1583 - - - @ruby_end_block - 13 - - - @ruby_ensure - 4106 - - - @ruby_exception_variable - 935 - - - @ruby_exceptions - 1904 - - - @ruby_expression_reference_pattern - 3 - - - @ruby_find_pattern - 18 - - - @ruby_for - 136 - - - @ruby_hash - 41915 - - - @ruby_hash_pattern - 73 - - - @ruby_hash_splat_argument - 1989 - - - @ruby_hash_splat_parameter - 1574 - - - @ruby_heredoc_body - 6934 - - - @ruby_if - 16164 - - - @ruby_if_guard - 9 - - - @ruby_if_modifier - 14541 - - - @ruby_in - 136 - - - @ruby_in_clause - 381 - - - @ruby_interpolation - 38493 - - - @ruby_keyword_parameter - 4763 - - - @ruby_keyword_pattern - 77 - - - @ruby_lambda - 8187 - - - @ruby_lambda_parameters - 1811 - - - @ruby_left_assignment_list - 3100 - - - @ruby_match_pattern - 31 - - - @ruby_method - 103532 - - - @ruby_method_parameters - 31208 - - - @ruby_module - 22962 - - - @ruby_next - 2020 - - - @ruby_operator_assignment_ampersandampersandequal - 118 - - - @ruby_operator_assignment_ampersandequal - 17 - - - @ruby_operator_assignment_caretequal - 6 - - - @ruby_operator_assignment_langlelangleequal - 19 - - - @ruby_operator_assignment_minusequal - 305 - - - @ruby_operator_assignment_percentequal - 26 - - - @ruby_operator_assignment_pipeequal - 164 - - - @ruby_operator_assignment_pipepipeequal - 4272 - - - @ruby_operator_assignment_plusequal - 1732 - - - @ruby_operator_assignment_ranglerangleequal - 11 - - - @ruby_operator_assignment_slashequal - 13 - - - @ruby_operator_assignment_starequal - 42 - - - @ruby_operator_assignment_starstarequal - 6 - - - @ruby_optional_parameter - 6556 - - - @ruby_pair - 254198 - - - @ruby_parenthesized_pattern - 8 - - - @ruby_parenthesized_statements - 11296 - - - @ruby_pattern - 4745 - - - @ruby_program - 18697 - - - @ruby_range_dotdot - 3690 - - - @ruby_range_dotdotdot - 1376 - - - @ruby_rational - 166 - - - @ruby_redo - 34 - - - @ruby_regex - 13680 - - - @ruby_rescue - 2299 - - - @ruby_rescue_modifier - 458 - - - @ruby_reserved_word - 3894800 - - - @ruby_rest_assignment - 414 - - - @ruby_retry - 58 - - - @ruby_return - 7979 - - - @ruby_right_assignment_list - 1280 - - - @ruby_scope_resolution - 87113 - - - @ruby_setter - 656 - - - @ruby_singleton_class - 677 - - - @ruby_singleton_method - 6325 - - - @ruby_splat_argument - 3606 - - - @ruby_splat_parameter - 3014 - - - @ruby_string__ - 490602 - - - @ruby_string_array - 4287 - - - @ruby_subshell - 359 - - - @ruby_superclass - 13806 - - - @ruby_symbol_array - 2240 - - - @ruby_test_pattern - 5 - - - @ruby_then - 22229 - - - @ruby_token_character - 440 - - - @ruby_token_class_variable - 887 - - - @ruby_token_comment - 194426 - - - @ruby_token_constant - 302373 - - - @ruby_token_empty_statement - 58 - - - @ruby_token_encoding - 1 - - - @ruby_token_escape_sequence - 80835 - - - @ruby_token_false - 17355 - - - @ruby_token_file - 1 - - - @ruby_token_float - 8689 - - - @ruby_token_forward_argument - 194 - - - @ruby_token_forward_parameter - 287 - - - @ruby_token_global_variable - 7165 - - - @ruby_token_hash_key_symbol - 246826 - - - @ruby_token_hash_splat_nil - 14 - - - @ruby_token_heredoc_beginning - 6933 - - - @ruby_token_heredoc_content - 12986 - - - @ruby_token_heredoc_end - 6934 - - - @ruby_token_identifier - 1590836 - - - @ruby_token_instance_variable - 89852 - - - @ruby_token_integer - 310358 - - - @ruby_token_line - 1 - - - @ruby_token_nil - 19333 - - - @ruby_token_operator - 878 - - - @ruby_token_self - 14094 - - - @ruby_token_simple_symbol - 267609 - - - @ruby_token_string_content - 510164 - - - @ruby_token_super - 5329 - - - @ruby_token_true - 25065 - - - @ruby_token_uninterpreted - 11 - - - @ruby_unary_bang - 5909 - - - @ruby_unary_definedquestion - 1369 - - - @ruby_unary_minus - 9830 - - - @ruby_unary_not - 172 - - - @ruby_unary_plus - 1394 - - - @ruby_unary_tilde - 97 - - - @ruby_undef - 182 - - - @ruby_unless - 2723 - - - @ruby_unless_guard - 4 - - - @ruby_unless_modifier - 3416 - - - @ruby_until - 126 - - - @ruby_until_modifier - 238 - - - @ruby_variable_reference_pattern - 5 - - - @ruby_when - 3882 - - - @ruby_while - 1413 - - - @ruby_while_modifier - 198 - - - @ruby_yield - 2450 - - - @yaml_alias_node - 0 - - - @yaml_error - 0 - - - @yaml_mapping_node - 0 - - - @yaml_scalar_node - 0 - - - @yaml_sequence_node - 0 - - - - containerparent - 23863 - - - parent - 5165 - - - child - 23863 - - - - - parent - child - - - 12 - - - 1 - 2 - 2394 - - - 2 - 3 - 968 - - - 3 - 4 - 417 - - - 4 - 5 - 295 - - - 5 - 7 - 443 - - - 7 - 14 - 403 - - - 14 - 126 - 242 - - - - - - - child - parent - - - 12 - - - 1 - 2 - 23863 - - - - - - - - - diagnostics - 188 - - - id - 188 - - - severity - 13 - - - error_tag - 13 - - - error_message - 53 - - - full_error_message - 161 - - - location - 174 - - - - - id - severity - - - 12 - - - 1 - 2 - 188 - - - - - - - id - error_tag - - - 12 - - - 1 - 2 - 188 - - - - - - - id - error_message - - - 12 - - - 1 - 2 - 188 - - - - - - - id - full_error_message - - - 12 - - - 1 - 2 - 188 - - - - - - - id - location - - - 12 - - - 1 - 2 - 188 - - - - - - - severity - id - - - 12 - - - 14 - 15 - 13 - - - - - - - severity - error_tag - - - 12 - - - 1 - 2 - 13 - - - - - - - severity - error_message - - - 12 - - - 4 - 5 - 13 - - - - - - - severity - full_error_message - - - 12 - - - 12 - 13 - 13 - - - - - - - severity - location - - - 12 - - - 13 - 14 - 13 - - - - - - - error_tag - id - - - 12 - - - 14 - 15 - 13 - - - - - - - error_tag - severity - - - 12 - - - 1 - 2 - 13 - - - - - - - error_tag - error_message - - - 12 - - - 4 - 5 - 13 - - - - - - - error_tag - full_error_message - - - 12 - - - 12 - 13 - 13 - - - - - - - error_tag - location - - - 12 - - - 13 - 14 - 13 - - - - - - - error_message - id - - - 12 - - - 1 - 2 - 26 - - - 2 - 3 - 13 - - - 10 - 11 - 13 - - - - - - - error_message - severity - - - 12 - - - 1 - 2 - 53 - - - - - - - error_message - error_tag - - - 12 - - - 1 - 2 - 53 - - - - - - - error_message - full_error_message - - - 12 - - - 1 - 2 - 26 - - - 2 - 3 - 13 - - - 8 - 9 - 13 - - - - - - - error_message - location - - - 12 - - - 1 - 2 - 26 - - - 2 - 3 - 13 - - - 10 - 11 - 13 - - - - - - - full_error_message - id - - - 12 - - - 1 - 2 - 134 - - - 2 - 3 - 26 - - - - - - - full_error_message - severity - - - 12 - - - 1 - 2 - 161 - - - - - - - full_error_message - error_tag - - - 12 - - - 1 - 2 - 161 - - - - - - - full_error_message - error_message - - - 12 - - - 1 - 2 - 161 - - - - - - - full_error_message - location - - - 12 - - - 1 - 2 - 134 - - - 2 - 3 - 26 - - - - - - - location - id - - - 12 - - - 1 - 2 - 161 - - - 2 - 3 - 13 - - - - - - - location - severity - - - 12 - - - 1 - 2 - 174 - - - - - - - location - error_tag - - - 12 - - - 1 - 2 - 174 - - - - - - - location - error_message - - - 12 - - - 1 - 2 - 161 - - - 2 - 3 - 13 - - - - - - - location - full_error_message - - - 12 - - - 1 - 2 - 161 - - - 2 - 3 - 13 - - - - - - - - - erb_ast_node_location - 22409 - - - node - 22409 - - - loc - 22407 - - - - - node - loc - - - 12 - - - 1 - 2 - 22409 - - - - - - - loc - node - - - 12 - - - 1 - 2 - 22404 - - - 2 - 3 - 2 - - - - - - - - - erb_ast_node_parent - 22069 - - - node - 22069 - - - parent - 4718 - - - parent_index - 564 - - - - - node - parent - - - 12 - - - 1 - 2 - 22069 - - - - - - - node - parent_index - - - 12 - - - 1 - 2 - 22069 - - - - - - - parent - node - - - 12 - - - 1 - 3 - 9 - - - 3 - 4 - 4494 - - - 4 - 240 - 215 - - - - - - - parent - parent_index - - - 12 - - - 1 - 3 - 9 - - - 3 - 4 - 4494 - - - 4 - 240 - 215 - - - - - - - parent_index - node - - - 12 - - - 1 - 2 - 25 - - - 2 - 3 - 33 - - - 3 - 4 - 33 - - - 4 - 5 - 122 - - - 5 - 6 - 96 - - - 6 - 8 - 40 - - - 8 - 13 - 42 - - - 13 - 20 - 44 - - - 21 - 31 - 42 - - - 35 - 55 - 44 - - - 55 - 1998 - 37 - - - - - - - parent_index - parent - - - 12 - - - 1 - 2 - 25 - - - 2 - 3 - 33 - - - 3 - 4 - 33 - - - 4 - 5 - 122 - - - 5 - 6 - 96 - - - 6 - 8 - 40 - - - 8 - 13 - 42 - - - 13 - 20 - 44 - - - 21 - 31 - 42 - - - 35 - 55 - 44 - - - 55 - 1998 - 37 - - - - - - - - - erb_comment_directive_child - 26 - - - erb_comment_directive - 26 - - - child - 26 - - - - - erb_comment_directive - child - - - 12 - - - 1 - 2 - 26 - - - - - - - child - erb_comment_directive - - - 12 - - - 1 - 2 - 26 - - - - - - - - - erb_comment_directive_def - 26 - - - id - 26 - - - - - - erb_directive_child - 1108 - - - erb_directive - 1108 - - - child - 1108 - - - - - erb_directive - child - - - 12 - - - 1 - 2 - 1108 - - - - - - - child - erb_directive - - - 12 - - - 1 - 2 - 1108 - - - - - - - - - erb_directive_def - 1108 - - - id - 1108 - - - - - - erb_graphql_directive_child - 0 - - - erb_graphql_directive - 0 - - - child - 0 - - - - - erb_graphql_directive - child - - - 12 - - - 1 - 2 - 2 - - - - - - - child - erb_graphql_directive - - - 12 - - - 1 - 2 - 2 - - - - - - - - - erb_graphql_directive_def - 0 - - - id - 0 - - - - - - erb_output_directive_child - 3270 - - - erb_output_directive - 3270 - - - child - 3270 - - - - - erb_output_directive - child - - - 12 - - - 1 - 2 - 3270 - - - - - - - child - erb_output_directive - - - 12 - - - 1 - 2 - 3270 - - - - - - - - - erb_output_directive_def - 3270 - - - id - 3270 - - - - - - erb_template_child - 8934 - - - erb_template - 340 - - - index - 564 - - - child - 8934 - - - - - erb_template - index - - - 12 - - - 1 - 3 - 9 - - - 3 - 4 - 115 - - - 4 - 7 - 21 - - - 7 - 10 - 25 - - - 10 - 14 - 28 - - - 14 - 24 - 25 - - - 24 - 33 - 25 - - - 33 - 44 - 25 - - - 45 - 64 - 25 - - - 67 - 149 - 25 - - - 200 - 240 - 9 - - - - - - - erb_template - child - - - 12 - - - 1 - 3 - 9 - - - 3 - 4 - 115 - - - 4 - 7 - 21 - - - 7 - 10 - 25 - - - 10 - 14 - 28 - - - 14 - 24 - 25 - - - 24 - 33 - 25 - - - 33 - 44 - 25 - - - 45 - 64 - 25 - - - 67 - 149 - 25 - - - 200 - 240 - 9 - - - - - - - index - erb_template - - - 12 - - - 1 - 2 - 25 - - - 2 - 3 - 33 - - - 3 - 4 - 33 - - - 4 - 5 - 122 - - - 5 - 6 - 96 - - - 6 - 8 - 40 - - - 8 - 13 - 42 - - - 13 - 20 - 44 - - - 21 - 31 - 42 - - - 35 - 55 - 44 - - - 55 - 145 - 37 - - - - - - - index - child - - - 12 - - - 1 - 2 - 25 - - - 2 - 3 - 33 - - - 3 - 4 - 33 - - - 4 - 5 - 122 - - - 5 - 6 - 96 - - - 6 - 8 - 40 - - - 8 - 13 - 42 - - - 13 - 20 - 44 - - - 21 - 31 - 42 - - - 35 - 55 - 44 - - - 55 - 145 - 37 - - - - - - - child - erb_template - - - 12 - - - 1 - 2 - 8934 - - - - - - - child - index - - - 12 - - - 1 - 2 - 8934 - - - - - - - - - erb_template_def - 1508 - - - id - 1508 - - - - - - erb_tokeninfo - 17690 - - - id - 17690 - - - kind - 7 - - - value - 4822 - - - - - id - kind - - - 12 - - - 1 - 2 - 17690 - - - - - - - id - value - - - 12 - - - 1 - 2 - 17690 - - - - - - - kind - id - - - 12 - - - 1853 - 1854 - 2 - - - 1928 - 1929 - 2 - - - 3706 - 3707 - 2 - - - - - - - kind - value - - - 12 - - - 5 - 6 - 2 - - - 984 - 985 - 2 - - - 1052 - 1053 - 2 - - - - - - - value - id - - - 12 - - - 1 - 2 - 3879 - - - 2 - 3 - 600 - - - 3 - 1786 - 342 - - - - - - - value - kind - - - 12 - - - 1 - 2 - 4822 - - - - - - - - - files - 18724 - - - id - 18724 - - - name - 18724 - - - - - id - name - - - 12 - - - 1 - 2 - 18724 - - - - - - - name - id - - - 12 - - - 1 - 2 - 18724 - - - - - - - - - folders - 5165 - - - id - 5165 - - - name - 5165 - - - - - id - name - - - 12 - - - 1 - 2 - 5165 - - - - - - - name - id - - - 12 - - - 1 - 2 - 5165 - - - - - - - - - locations_default - 9223392 - - - id - 9223392 - - - file - 18724 - - - beginLine - 31826 - - - beginColumn - 5300 - - - endLine - 31826 - - - endColumn - 5407 - - - - - id - file - - - 12 - - - 1 - 2 - 9223392 - - - - - - - id - beginLine - - - 12 - - - 1 - 2 - 9223392 - - - - - - - id - beginColumn - - - 12 - - - 1 - 2 - 9223392 - - - - - - - id - endLine - - - 12 - - - 1 - 2 - 9223392 - - - - - - - id - endColumn - - - 12 - - - 1 - 2 - 9223392 - - - - - - - file - id - - - 12 - - - 1 - 32 - 1479 - - - 32 - 47 - 1412 - - - 47 - 71 - 1452 - - - 71 - 94 - 1439 - - - 94 - 119 - 1412 - - - 119 - 161 - 1412 - - - 161 - 209 - 1466 - - - 209 - 260 - 1439 - - - 260 - 333 - 1412 - - - 336 - 445 - 1425 - - - 445 - 679 - 1412 - - - 684 - 1221 - 1412 - - - 1228 - 5812 - 1412 - - - 7145 - 22841 - 134 - - - - - - - file - beginLine - - - 12 - - - 1 - 7 - 1398 - - - 7 - 10 - 1641 - - - 10 - 13 - 1479 - - - 13 - 16 - 1668 - - - 16 - 20 - 1600 - - - 20 - 25 - 1587 - - - 25 - 31 - 1573 - - - 31 - 38 - 1506 - - - 38 - 49 - 1506 - - - 49 - 69 - 1425 - - - 69 - 117 - 1425 - - - 119 - 275 - 1412 - - - 276 - 2339 - 497 - - - - - - - file - beginColumn - - - 12 - - - 1 - 16 - 1533 - - - 16 - 24 - 1493 - - - 24 - 31 - 1412 - - - 31 - 40 - 1573 - - - 40 - 46 - 1452 - - - 46 - 52 - 1533 - - - 52 - 60 - 1587 - - - 60 - 68 - 1721 - - - 68 - 76 - 1533 - - - 76 - 85 - 1452 - - - 85 - 98 - 1412 - - - 98 - 122 - 1412 - - - 122 - 357 - 605 - - - - - - - file - endLine - - - 12 - - - 1 - 7 - 1398 - - - 7 - 10 - 1600 - - - 10 - 13 - 1506 - - - 13 - 16 - 1641 - - - 16 - 20 - 1614 - - - 20 - 25 - 1600 - - - 25 - 31 - 1587 - - - 31 - 38 - 1506 - - - 38 - 49 - 1506 - - - 49 - 69 - 1425 - - - 69 - 117 - 1425 - - - 119 - 275 - 1412 - - - 276 - 2339 - 497 - - - - - - - file - endColumn - - - 12 - - - 1 - 19 - 1412 - - - 19 - 27 - 1587 - - - 27 - 35 - 1425 - - - 35 - 44 - 1452 - - - 44 - 50 - 1600 - - - 50 - 57 - 1533 - - - 57 - 64 - 1439 - - - 64 - 71 - 1412 - - - 71 - 78 - 1533 - - - 78 - 87 - 1520 - - - 87 - 99 - 1493 - - - 99 - 118 - 1425 - - - 118 - 367 - 887 - - - - - - - beginLine - id - - - 12 - - - 1 - 2 - 1600 - - - 2 - 5 - 1627 - - - 5 - 6 - 3484 - - - 6 - 10 - 2676 - - - 10 - 17 - 2878 - - - 17 - 24 - 2421 - - - 24 - 43 - 2448 - - - 43 - 78 - 2394 - - - 78 - 117 - 2394 - - - 117 - 168 - 2407 - - - 169 - 262 - 2421 - - - 262 - 703 - 2394 - - - 708 - 5999 - 2394 - - - 6159 - 10971 - 282 - - - - - - - beginLine - file - - - 12 - - - 1 - 2 - 10304 - - - 2 - 3 - 5609 - - - 3 - 7 - 2838 - - - 7 - 10 - 2663 - - - 10 - 15 - 2407 - - - 15 - 23 - 2394 - - - 23 - 58 - 2407 - - - 58 - 287 - 2394 - - - 296 - 1392 - 807 - - - - - - - beginLine - beginColumn - - - 12 - - - 1 - 2 - 1600 - - - 2 - 3 - 1520 - - - 3 - 4 - 2394 - - - 4 - 6 - 2650 - - - 6 - 8 - 1775 - - - 8 - 13 - 2811 - - - 13 - 18 - 2448 - - - 18 - 29 - 2582 - - - 29 - 44 - 2475 - - - 44 - 56 - 2582 - - - 56 - 69 - 2475 - - - 69 - 86 - 2461 - - - 86 - 113 - 2407 - - - 113 - 205 - 1641 - - - - - - - beginLine - endLine - - - 12 - - - 1 - 2 - 11299 - - - 2 - 3 - 6591 - - - 3 - 4 - 2380 - - - 4 - 5 - 1815 - - - 5 - 7 - 2623 - - - 7 - 10 - 2367 - - - 10 - 17 - 2461 - - - 17 - 240 - 2286 - - - - - - - beginLine - endColumn - - - 12 - - - 1 - 2 - 1600 - - - 2 - 4 - 1627 - - - 4 - 5 - 3537 - - - 5 - 7 - 2152 - - - 7 - 11 - 2744 - - - 11 - 15 - 2461 - - - 15 - 24 - 2394 - - - 24 - 39 - 2421 - - - 39 - 52 - 2448 - - - 52 - 65 - 2542 - - - 65 - 80 - 2555 - - - 80 - 102 - 2434 - - - 102 - 136 - 2421 - - - 136 - 209 - 484 - - - - - - - beginColumn - id - - - 12 - - - 1 - 2 - 484 - - - 2 - 3 - 605 - - - 3 - 4 - 255 - - - 4 - 5 - 269 - - - 5 - 6 - 336 - - - 6 - 9 - 457 - - - 9 - 16 - 430 - - - 16 - 43 - 403 - - - 46 - 182 - 403 - - - 184 - 794 - 403 - - - 811 - 3014 - 403 - - - 3015 - 8230 - 403 - - - 8347 - 25670 - 403 - - - 28494 - 38951 - 40 - - - - - - - beginColumn - file - - - 12 - - - 1 - 2 - 1466 - - - 2 - 3 - 605 - - - 3 - 4 - 484 - - - 4 - 9 - 417 - - - 9 - 37 - 403 - - - 37 - 118 - 403 - - - 124 - 381 - 403 - - - 381 - 728 - 403 - - - 754 - 985 - 403 - - - 996 - 1392 - 309 - - - - - - - beginColumn - beginLine - - - 12 - - - 1 - 2 - 551 - - - 2 - 3 - 712 - - - 3 - 4 - 322 - - - 4 - 5 - 363 - - - 5 - 7 - 363 - - - 7 - 13 - 457 - - - 13 - 35 - 403 - - - 35 - 103 - 403 - - - 109 - 281 - 403 - - - 286 - 583 - 403 - - - 591 - 927 - 403 - - - 935 - 1163 - 403 - - - 1198 - 1405 - 107 - - - - - - - beginColumn - endLine - - - 12 - - - 1 - 2 - 551 - - - 2 - 3 - 712 - - - 3 - 4 - 322 - - - 4 - 5 - 363 - - - 5 - 7 - 363 - - - 7 - 13 - 457 - - - 13 - 35 - 403 - - - 35 - 105 - 403 - - - 108 - 282 - 403 - - - 287 - 596 - 403 - - - 596 - 945 - 403 - - - 956 - 1202 - 403 - - - 1223 - 1412 - 107 - - - - - - - beginColumn - endColumn - - - 12 - - - 1 - 2 - 1318 - - - 2 - 3 - 712 - - - 3 - 4 - 524 - - - 4 - 6 - 443 - - - 6 - 15 - 403 - - - 15 - 37 - 403 - - - 37 - 66 - 403 - - - 66 - 98 - 403 - - - 100 - 127 - 403 - - - 128 - 180 - 282 - - - - - - - endLine - id - - - 12 - - - 1 - 3 - 322 - - - 3 - 4 - 3510 - - - 4 - 6 - 2528 - - - 6 - 9 - 2394 - - - 9 - 13 - 2488 - - - 13 - 20 - 2407 - - - 20 - 33 - 2461 - - - 33 - 64 - 2421 - - - 64 - 103 - 2421 - - - 103 - 143 - 2448 - - - 143 - 220 - 2394 - - - 220 - 446 - 2394 - - - 446 - 1691 - 2394 - - - 1717 - 10278 - 1237 - - - - - - - endLine - file - - - 12 - - - 1 - 2 - 10304 - - - 2 - 3 - 5609 - - - 3 - 7 - 2838 - - - 7 - 10 - 2663 - - - 10 - 15 - 2407 - - - 15 - 23 - 2394 - - - 23 - 58 - 2407 - - - 58 - 287 - 2394 - - - 296 - 1376 - 807 - - - - - - - endLine - beginLine - - - 12 - - - 1 - 2 - 11420 - - - 2 - 3 - 5959 - - - 3 - 4 - 2636 - - - 4 - 5 - 1654 - - - 5 - 7 - 2650 - - - 7 - 10 - 2407 - - - 10 - 17 - 2394 - - - 17 - 34 - 2434 - - - 34 - 43 - 269 - - - - - - - endLine - beginColumn - - - 12 - - - 1 - 3 - 1614 - - - 3 - 4 - 3497 - - - 4 - 6 - 2824 - - - 6 - 8 - 1694 - - - 8 - 12 - 2502 - - - 12 - 17 - 2771 - - - 17 - 28 - 2421 - - - 28 - 42 - 2448 - - - 42 - 55 - 2650 - - - 55 - 67 - 2407 - - - 67 - 82 - 2434 - - - 82 - 108 - 2461 - - - 108 - 204 - 2098 - - - - - - - endLine - endColumn - - - 12 - - - 1 - 2 - 1587 - - - 2 - 3 - 1520 - - - 3 - 4 - 2421 - - - 4 - 6 - 2650 - - - 6 - 8 - 1748 - - - 8 - 13 - 2851 - - - 13 - 18 - 2448 - - - 18 - 30 - 2488 - - - 30 - 45 - 2448 - - - 45 - 58 - 2542 - - - 58 - 71 - 2421 - - - 71 - 86 - 2407 - - - 86 - 113 - 2394 - - - 113 - 209 - 1896 - - - - - - - endColumn - id - - - 12 - - - 1 - 2 - 417 - - - 2 - 3 - 484 - - - 3 - 5 - 457 - - - 5 - 6 - 174 - - - 6 - 8 - 470 - - - 8 - 12 - 417 - - - 12 - 24 - 417 - - - 24 - 72 - 417 - - - 76 - 277 - 417 - - - 278 - 1206 - 417 - - - 1227 - 3859 - 417 - - - 3977 - 8618 - 417 - - - 9094 - 11251 - 417 - - - 11548 - 19740 - 67 - - - - - - - endColumn - file - - - 12 - - - 1 - 2 - 1479 - - - 2 - 3 - 578 - - - 3 - 4 - 538 - - - 4 - 8 - 417 - - - 8 - 29 - 417 - - - 35 - 115 - 417 - - - 115 - 399 - 417 - - - 427 - 798 - 417 - - - 805 - 1038 - 417 - - - 1039 - 1359 - 309 - - - - - - - endColumn - beginLine - - - 12 - - - 1 - 2 - 591 - - - 2 - 3 - 645 - - - 3 - 4 - 336 - - - 4 - 6 - 470 - - - 6 - 9 - 470 - - - 9 - 17 - 443 - - - 17 - 47 - 417 - - - 51 - 153 - 417 - - - 153 - 387 - 417 - - - 390 - 717 - 417 - - - 730 - 1059 - 417 - - - 1062 - 1404 - 363 - - - - - - - endColumn - beginColumn - - - 12 - - - 1 - 2 - 928 - - - 2 - 3 - 390 - - - 3 - 4 - 497 - - - 4 - 5 - 363 - - - 5 - 7 - 363 - - - 7 - 14 - 443 - - - 15 - 33 - 470 - - - 33 - 49 - 417 - - - 49 - 64 - 430 - - - 65 - 81 - 417 - - - 81 - 96 - 457 - - - 97 - 109 - 228 - - - - - - - endColumn - endLine - - - 12 - - - 1 - 2 - 591 - - - 2 - 3 - 659 - - - 3 - 4 - 336 - - - 4 - 6 - 457 - - - 6 - 9 - 470 - - - 9 - 16 - 417 - - - 16 - 43 - 430 - - - 45 - 151 - 430 - - - 161 - 379 - 417 - - - 384 - 712 - 417 - - - 729 - 1046 - 417 - - - 1049 - 1397 - 363 - - - - - - - - - ruby_alias_def - 1289 - - - id - 1289 - - - alias - 1289 - - - name - 1289 - - - - - id - alias - - - 12 - - - 1 - 2 - 1289 - - - - - - - id - name - - - 12 - - - 1 - 2 - 1289 - - - - - - - alias - id - - - 12 - - - 1 - 2 - 1289 - - - - - - - alias - name - - - 12 - - - 1 - 2 - 1289 - - - - - - - name - id - - - 12 - - - 1 - 2 - 1289 - - - - - - - name - alias - - - 12 - - - 1 - 2 - 1289 - - - - - - - - - ruby_alternative_pattern_alternatives - 23 - - - ruby_alternative_pattern - 9 - - - index - 4 - - - alternatives - 23 - - - - - ruby_alternative_pattern - index - - - 12 - - - 2 - 3 - 6 - - - 3 - 4 - 1 - - - 4 - 5 - 2 - - - - - - - ruby_alternative_pattern - alternatives - - - 12 - - - 2 - 3 - 6 - - - 3 - 4 - 1 - - - 4 - 5 - 2 - - - - - - - index - ruby_alternative_pattern - - - 12 - - - 2 - 3 - 1 - - - 3 - 4 - 1 - - - 9 - 10 - 2 - - - - - - - index - alternatives - - - 12 - - - 2 - 3 - 1 - - - 3 - 4 - 1 - - - 9 - 10 - 2 - - - - - - - alternatives - ruby_alternative_pattern - - - 12 - - - 1 - 2 - 23 - - - - - - - alternatives - index - - - 12 - - - 1 - 2 - 23 - - - - - - - - - ruby_alternative_pattern_def - 9 - - - id - 9 - - - - - - ruby_argument_list_child - 879410 - - - ruby_argument_list - 706205 - - - index - 443 - - - child - 879410 - - - - - ruby_argument_list - index - - - 12 - - - 1 - 2 - 596855 - - - 2 - 3 - 68483 - - - 3 - 34 - 40866 - - - - - - - ruby_argument_list - child - - - 12 - - - 1 - 2 - 596855 - - - 2 - 3 - 68483 - - - 3 - 34 - 40866 - - - - - - - index - ruby_argument_list - - - 12 - - - 1 - 2 - 147 - - - 2 - 3 - 40 - - - 3 - 7 - 40 - - - 7 - 11 - 40 - - - 11 - 21 - 40 - - - 23 - 45 - 40 - - - 56 - 385 - 40 - - - 963 - 8130 - 40 - - - 52499 - 52500 - 13 - - - - - - - index - child - - - 12 - - - 1 - 2 - 147 - - - 2 - 3 - 40 - - - 3 - 7 - 40 - - - 7 - 11 - 40 - - - 11 - 21 - 40 - - - 23 - 45 - 40 - - - 56 - 385 - 40 - - - 963 - 8130 - 40 - - - 52499 - 52500 - 13 - - - - - - - child - ruby_argument_list - - - 12 - - - 1 - 2 - 879410 - - - - - - - child - index - - - 12 - - - 1 - 2 - 879410 - - - - - - - - - ruby_argument_list_def - 706474 - - - id - 706474 - - - - - - ruby_array_child - 708919 - - - ruby_array - 240456 - - - index - 63360 - - - child - 708919 - - - - - ruby_array - index - - - 12 - - - 1 - 2 - 12708 - - - 2 - 3 - 213730 - - - 3 - 63361 - 14018 - - - - - - - ruby_array - child - - - 12 - - - 1 - 2 - 12708 - - - 2 - 3 - 213730 - - - 3 - 63361 - 14018 - - - - - - - index - ruby_array - - - 12 - - - 1 - 2 - 40208 - - - 2 - 6 - 4769 - - - 6 - 7 - 9559 - - - 7 - 8 - 598 - - - 8 - 9 - 6932 - - - 11 - 240457 - 1294 - - - - - - - index - child - - - 12 - - - 1 - 2 - 40208 - - - 2 - 6 - 4769 - - - 6 - 7 - 9559 - - - 7 - 8 - 598 - - - 8 - 9 - 6932 - - - 11 - 240457 - 1294 - - - - - - - child - ruby_array - - - 12 - - - 1 - 2 - 708919 - - - - - - - child - index - - - 12 - - - 1 - 2 - 708919 - - - - - - - - - ruby_array_def - 249320 - - - id - 249320 - - - - - - ruby_array_pattern_child - 336 - - - ruby_array_pattern - 168 - - - index - 18 - - - child - 336 - - - - - ruby_array_pattern - index - - - 12 - - - 1 - 2 - 51 - - - 2 - 3 - 97 - - - 3 - 4 - 14 - - - 4 - 19 - 6 - - - - - - - ruby_array_pattern - child - - - 12 - - - 1 - 2 - 51 - - - 2 - 3 - 97 - - - 3 - 4 - 14 - - - 4 - 19 - 6 - - - - - - - index - ruby_array_pattern - - - 12 - - - 1 - 2 - 7 - - - 2 - 3 - 5 - - - 4 - 5 - 2 - - - 6 - 7 - 1 - - - 20 - 21 - 1 - - - 117 - 118 - 1 - - - 168 - 169 - 1 - - - - - - - index - child - - - 12 - - - 1 - 2 - 7 - - - 2 - 3 - 5 - - - 4 - 5 - 2 - - - 6 - 7 - 1 - - - 20 - 21 - 1 - - - 117 - 118 - 1 - - - 168 - 169 - 1 - - - - - - - child - ruby_array_pattern - - - 12 - - - 1 - 2 - 336 - - - - - - - child - index - - - 12 - - - 1 - 2 - 336 - - - - - - - - - ruby_array_pattern_class - 51 - - - ruby_array_pattern - 51 - - - class - 51 - - - - - ruby_array_pattern - class - - - 12 - - - 1 - 2 - 51 - - - - - - - class - ruby_array_pattern - - - 12 - - - 1 - 2 - 51 - - - - - - - - - ruby_array_pattern_def - 179 - - - id - 179 - - - - - - ruby_as_pattern_def - 156 - - - id - 156 - - - name - 156 - - - value - 156 - - - - - id - name - - - 12 - - - 1 - 2 - 156 - - - - - - - id - value - - - 12 - - - 1 - 2 - 156 - - - - - - - name - id - - - 12 - - - 1 - 2 - 156 - - - - - - - name - value - - - 12 - - - 1 - 2 - 156 - - - - - - - value - id - - - 12 - - - 1 - 2 - 156 - - - - - - - value - name - - - 12 - - - 1 - 2 - 156 - - - - - - - - - ruby_assignment_def - 141202 - - - id - 141202 - - - left - 141202 - - - right - 141202 - - - - - id - left - - - 12 - - - 1 - 2 - 141202 - - - - - - - id - right - - - 12 - - - 1 - 2 - 141202 - - - - - - - left - id - - - 12 - - - 1 - 2 - 141202 - - - - - - - left - right - - - 12 - - - 1 - 2 - 141202 - - - - - - - right - id - - - 12 - - - 1 - 2 - 141202 - - - - - - - right - left - - - 12 - - - 1 - 2 - 141202 - - - - - - - - - ruby_ast_node_location - 9723503 - - - node - 9723503 - - - loc - 9209550 - - - - - node - loc - - - 12 - - - 1 - 2 - 9723503 - - - - - - - loc - node - - - 12 - - - 1 - 2 - 8697279 - - - 2 - 4 - 512270 - - - - - - - - - ruby_ast_node_parent - 9674605 - - - node - 9674605 - - - parent - 3381025 - - - parent_index - 2892 - - - - - node - parent - - - 12 - - - 1 - 2 - 9674605 - - - - - - - node - parent_index - - - 12 - - - 1 - 2 - 9674605 - - - - - - - parent - node - - - 12 - - - 1 - 2 - 533793 - - - 2 - 3 - 465418 - - - 3 - 4 - 1832321 - - - 4 - 5 - 359620 - - - 5 - 216 - 189871 - - - - - - - parent - parent_index - - - 12 - - - 1 - 2 - 533793 - - - 2 - 3 - 465418 - - - 3 - 4 - 1832321 - - - 4 - 5 - 359620 - - - 5 - 216 - 189871 - - - - - - - parent_index - node - - - 12 - - - 1 - 2 - 470 - - - 2 - 3 - 242 - - - 3 - 4 - 363 - - - 4 - 6 - 161 - - - 6 - 7 - 484 - - - 7 - 17 - 255 - - - 17 - 29 - 228 - - - 33 - 71 - 228 - - - 72 - 298 - 228 - - - 358 - 251345 - 228 - - - - - - - parent_index - parent - - - 12 - - - 1 - 2 - 470 - - - 2 - 3 - 242 - - - 3 - 4 - 363 - - - 4 - 6 - 161 - - - 6 - 7 - 484 - - - 7 - 17 - 255 - - - 17 - 29 - 228 - - - 33 - 71 - 228 - - - 72 - 298 - 228 - - - 358 - 251345 - 228 - - - - - - - - - ruby_bare_string_child - 16784 - - - ruby_bare_string - 13136 - - - index - 2309 - - - child - 16784 - - - - - ruby_bare_string - index - - - 12 - - - 1 - 2 - 12728 - - - 2 - 2310 - 408 - - - - - - - ruby_bare_string - child - - - 12 - - - 1 - 2 - 12728 - - - 2 - 2310 - 408 - - - - - - - index - ruby_bare_string - - - 12 - - - 1 - 2 - 1942 - - - 2 - 3 - 72 - - - 3 - 4 - 276 - - - 4 - 13137 - 19 - - - - - - - index - child - - - 12 - - - 1 - 2 - 1942 - - - 2 - 3 - 72 - - - 3 - 4 - 276 - - - 4 - 13137 - 19 - - - - - - - child - ruby_bare_string - - - 12 - - - 1 - 2 - 16784 - - - - - - - child - index - - - 12 - - - 1 - 2 - 16784 - - - - - - - - - ruby_bare_string_def - 13136 - - - id - 13136 - - - - - - ruby_bare_symbol_child - 8435 - - - ruby_bare_symbol - 8435 - - - index - 2 - - - child - 8435 - - - - - ruby_bare_symbol - index - - - 12 - - - 1 - 2 - 8435 - - - - - - - ruby_bare_symbol - child - - - 12 - - - 1 - 2 - 8435 - - - - - - - index - ruby_bare_symbol - - - 12 - - - 3570 - 3571 - 2 - - - - - - - index - child - - - 12 - - - 3570 - 3571 - 2 - - - - - - - child - ruby_bare_symbol - - - 12 - - - 1 - 2 - 8435 - - - - - - - child - index - - - 12 - - - 1 - 2 - 8435 - - - - - - - - - ruby_bare_symbol_def - 8435 - - - id - 8435 - - - - - - ruby_begin_block_child - 39 - - - ruby_begin_block - 10 - - - index - 7 - - - child - 39 - - - - - ruby_begin_block - index - - - 12 - - - 1 - 2 - 3 - - - 2 - 3 - 1 - - - 3 - 4 - 2 - - - 7 - 8 - 4 - - - - - - - ruby_begin_block - child - - - 12 - - - 1 - 2 - 3 - - - 2 - 3 - 1 - - - 3 - 4 - 2 - - - 7 - 8 - 4 - - - - - - - index - ruby_begin_block - - - 12 - - - 4 - 5 - 4 - - - 6 - 7 - 1 - - - 7 - 8 - 1 - - - 10 - 11 - 1 - - - - - - - index - child - - - 12 - - - 4 - 5 - 4 - - - 6 - 7 - 1 - - - 7 - 8 - 1 - - - 10 - 11 - 1 - - - - - - - child - ruby_begin_block - - - 12 - - - 1 - 2 - 39 - - - - - - - child - index - - - 12 - - - 1 - 2 - 39 - - - - - - - - - ruby_begin_block_def - 10 - - - id - 10 - - - - - - ruby_begin_child - 7606 - - - ruby_begin - 2610 - - - index - 39 - - - child - 7606 - - - - - ruby_begin - index - - - 12 - - - 1 - 2 - 161 - - - 2 - 3 - 1414 - - - 3 - 4 - 537 - - - 4 - 5 - 200 - - - 5 - 8 - 221 - - - 8 - 40 - 77 - - - - - - - ruby_begin - child - - - 12 - - - 1 - 2 - 161 - - - 2 - 3 - 1414 - - - 3 - 4 - 537 - - - 4 - 5 - 200 - - - 5 - 8 - 221 - - - 8 - 40 - 77 - - - - - - - index - ruby_begin - - - 12 - - - 1 - 2 - 2 - - - 2 - 3 - 3 - - - 3 - 4 - 12 - - - 4 - 8 - 2 - - - 9 - 12 - 3 - - - 15 - 17 - 3 - - - 23 - 33 - 3 - - - 37 - 59 - 3 - - - 77 - 166 - 3 - - - 298 - 1036 - 3 - - - 2449 - 2611 - 2 - - - - - - - index - child - - - 12 - - - 1 - 2 - 2 - - - 2 - 3 - 3 - - - 3 - 4 - 12 - - - 4 - 8 - 2 - - - 9 - 12 - 3 - - - 15 - 17 - 3 - - - 23 - 33 - 3 - - - 37 - 59 - 3 - - - 77 - 166 - 3 - - - 298 - 1036 - 3 - - - 2449 - 2611 - 2 - - - - - - - child - ruby_begin - - - 12 - - - 1 - 2 - 7606 - - - - - - - child - index - - - 12 - - - 1 - 2 - 7606 - - - - - - - - - ruby_begin_def - 2610 - - - id - 2610 - - - - - - ruby_binary_def - 73665 - - - id - 73665 - - - left - 73665 - - - operator - 25 - - - right - 73665 - - - - - id - left - - - 12 - - - 1 - 2 - 73665 - - - - - - - id - operator - - - 12 - - - 1 - 2 - 73665 - - - - - - - id - right - - - 12 - - - 1 - 2 - 73665 - - - - - - - left - id - - - 12 - - - 1 - 2 - 73665 - - - - - - - left - operator - - - 12 - - - 1 - 2 - 73665 - - - - - - - left - right - - - 12 - - - 1 - 2 - 73665 - - - - - - - operator - id - - - 12 - - - 153 - 177 - 2 - - - 259 - 432 - 2 - - - 597 - 631 - 2 - - - 647 - 690 - 2 - - - 764 - 987 - 2 - - - 1026 - 1033 - 2 - - - 1058 - 1073 - 2 - - - 1169 - 1190 - 2 - - - 1227 - 1824 - 2 - - - 2079 - 2661 - 2 - - - 2747 - 3491 - 2 - - - 6593 - 7408 - 2 - - - 33761 - 33762 - 1 - - - - - - - operator - left - - - 12 - - - 153 - 177 - 2 - - - 259 - 432 - 2 - - - 597 - 631 - 2 - - - 647 - 690 - 2 - - - 764 - 987 - 2 - - - 1026 - 1033 - 2 - - - 1058 - 1073 - 2 - - - 1169 - 1190 - 2 - - - 1227 - 1824 - 2 - - - 2079 - 2661 - 2 - - - 2747 - 3491 - 2 - - - 6593 - 7408 - 2 - - - 33761 - 33762 - 1 - - - - - - - operator - right - - - 12 - - - 153 - 177 - 2 - - - 259 - 432 - 2 - - - 597 - 631 - 2 - - - 647 - 690 - 2 - - - 764 - 987 - 2 - - - 1026 - 1033 - 2 - - - 1058 - 1073 - 2 - - - 1169 - 1190 - 2 - - - 1227 - 1824 - 2 - - - 2079 - 2661 - 2 - - - 2747 - 3491 - 2 - - - 6593 - 7408 - 2 - - - 33761 - 33762 - 1 - - - - - - - right - id - - - 12 - - - 1 - 2 - 73665 - - - - - - - right - left - - - 12 - - - 1 - 2 - 73665 - - - - - - - right - operator - - - 12 - - - 1 - 2 - 73665 - - - - - - - - - ruby_block_argument_child - 6541 - - - ruby_block_argument - 6541 - - - child - 6541 - - - - - ruby_block_argument - child - - - 12 - - - 1 - 2 - 6541 - - - - - - - child - ruby_block_argument - - - 12 - - - 1 - 2 - 6541 - - - - - - - - - ruby_block_argument_def - 6547 - - - id - 6547 - - - - - - ruby_block_body - 103820 - - - ruby_block - 103820 - - - body - 103820 - - - - - ruby_block - body - - - 12 - - - 1 - 2 - 103820 - - - - - - - body - ruby_block - - - 12 - - - 1 - 2 - 103820 - - - - - - - - - ruby_block_body_child - 103995 - - - ruby_block_body - 103820 - - - index - 53 - - - child - 103995 - - - - - ruby_block_body - index - - - 12 - - - 1 - 2 - 103699 - - - 2 - 5 - 121 - - - - - - - ruby_block_body - child - - - 12 - - - 1 - 2 - 103699 - - - 2 - 5 - 121 - - - - - - - index - ruby_block_body - - - 12 - - - 2 - 3 - 26 - - - 9 - 10 - 13 - - - 7718 - 7719 - 13 - - - - - - - index - child - - - 12 - - - 2 - 3 - 26 - - - 9 - 10 - 13 - - - 7718 - 7719 - 13 - - - - - - - child - ruby_block_body - - - 12 - - - 1 - 2 - 103995 - - - - - - - child - index - - - 12 - - - 1 - 2 - 103995 - - - - - - - - - ruby_block_body_def - 103820 - - - id - 103820 - - - - - - ruby_block_def - 104143 - - - id - 104143 - - - - - - ruby_block_parameter_def - 2543 - - - id - 2543 - - - - - - ruby_block_parameter_name - 2537 - - - ruby_block_parameter - 2537 - - - name - 2537 - - - - - ruby_block_parameter - name - - - 12 - - - 1 - 2 - 2537 - - - - - - - name - ruby_block_parameter - - - 12 - - - 1 - 2 - 2537 - - - - - - - - - ruby_block_parameters - 10767 - - - ruby_block - 10767 - - - parameters - 10767 - - - - - ruby_block - parameters - - - 12 - - - 1 - 2 - 10767 - - - - - - - parameters - ruby_block - - - 12 - - - 1 - 2 - 10767 - - - - - - - - - ruby_block_parameters_child - 30131 - - - ruby_block_parameters - 25884 - - - index - 14 - - - child - 30131 - - - - - ruby_block_parameters - index - - - 12 - - - 1 - 2 - 22189 - - - 2 - 3 - 3329 - - - 3 - 6 - 365 - - - - - - - ruby_block_parameters - child - - - 12 - - - 1 - 2 - 22189 - - - 2 - 3 - 3329 - - - 3 - 6 - 365 - - - - - - - index - ruby_block_parameters - - - 12 - - - 27 - 28 - 2 - - - 35 - 36 - 2 - - - 122 - 123 - 2 - - - 1232 - 1233 - 2 - - - 8630 - 8631 - 2 - - - - - - - index - child - - - 12 - - - 27 - 28 - 2 - - - 35 - 36 - 2 - - - 122 - 123 - 2 - - - 1232 - 1233 - 2 - - - 8630 - 8631 - 2 - - - - - - - child - ruby_block_parameters - - - 12 - - - 1 - 2 - 30131 - - - - - - - child - index - - - 12 - - - 1 - 2 - 30131 - - - - - - - - - ruby_block_parameters_def - 25884 - - - id - 25884 - - - - - - ruby_block_parameters_locals - 16 - - - ruby_block_parameters - 12 - - - index - 2 - - - locals - 16 - - - - - ruby_block_parameters - index - - - 12 - - - 1 - 2 - 8 - - - 2 - 3 - 4 - - - - - - - ruby_block_parameters - locals - - - 12 - - - 1 - 2 - 8 - - - 2 - 3 - 4 - - - - - - - index - ruby_block_parameters - - - 12 - - - 4 - 5 - 1 - - - 12 - 13 - 1 - - - - - - - index - locals - - - 12 - - - 4 - 5 - 1 - - - 12 - 13 - 1 - - - - - - - locals - ruby_block_parameters - - - 12 - - - 1 - 2 - 16 - - - - - - - locals - index - - - 12 - - - 1 - 2 - 16 - - - - - - - - - ruby_body_statement_child - 641142 - - - ruby_body_statement - 206879 - - - index - 1187 - - - child - 641142 - - - - - ruby_body_statement - index - - - 12 - - - 1 - 2 - 95107 - - - 2 - 3 - 37693 - - - 3 - 4 - 24510 - - - 4 - 5 - 15881 - - - 5 - 7 - 16388 - - - 7 - 23 - 15560 - - - 23 - 397 - 1736 - - - - - - - ruby_body_statement - child - - - 12 - - - 1 - 2 - 95107 - - - 2 - 3 - 37693 - - - 3 - 4 - 24510 - - - 4 - 5 - 15881 - - - 5 - 7 - 16388 - - - 7 - 23 - 15560 - - - 23 - 397 - 1736 - - - - - - - index - ruby_body_statement - - - 12 - - - 1 - 2 - 140 - - - 2 - 3 - 122 - - - 3 - 4 - 77 - - - 4 - 5 - 62 - - - 5 - 7 - 98 - - - 8 - 10 - 86 - - - 10 - 12 - 89 - - - 12 - 26 - 95 - - - 26 - 42 - 92 - - - 42 - 77 - 89 - - - 80 - 179 - 89 - - - 184 - 1016 - 89 - - - 1134 - 68975 - 47 - - - - - - - index - child - - - 12 - - - 1 - 2 - 140 - - - 2 - 3 - 122 - - - 3 - 4 - 77 - - - 4 - 5 - 62 - - - 5 - 7 - 98 - - - 8 - 10 - 86 - - - 10 - 12 - 89 - - - 12 - 26 - 95 - - - 26 - 42 - 92 - - - 42 - 77 - 89 - - - 80 - 179 - 89 - - - 184 - 1016 - 89 - - - 1134 - 68975 - 47 - - - - - - - child - ruby_body_statement - - - 12 - - - 1 - 2 - 641142 - - - - - - - child - index - - - 12 - - - 1 - 2 - 641142 - - - - - - - - - ruby_body_statement_def - 213896 - - - id - 213896 - - - - - - ruby_break_child - 394 - - - ruby_break - 394 - - - child - 394 - - - - - ruby_break - child - - - 12 - - - 1 - 2 - 394 - - - - - - - child - ruby_break - - - 12 - - - 1 - 2 - 394 - - - - - - - - - ruby_break_def - 3414 - - - id - 3414 - - - - - - ruby_call_arguments - 703178 - - - ruby_call - 703178 - - - arguments - 703178 - - - - - ruby_call - arguments - - - 12 - - - 1 - 2 - 703178 - - - - - - - arguments - ruby_call - - - 12 - - - 1 - 2 - 703178 - - - - - - - - - ruby_call_block - 246208 - - - ruby_call - 246208 - - - block - 246208 - - - - - ruby_call - block - - - 12 - - - 1 - 2 - 246208 - - - - - - - block - ruby_call - - - 12 - - - 1 - 2 - 246208 - - - - - - - - - ruby_call_def - 1027501 - - - id - 1027501 - - - - - - ruby_call_method - 1027501 - - - ruby_call - 1027501 - - - method - 1027501 - - - - - ruby_call - method - - - 12 - - - 1 - 2 - 1027501 - - - - - - - method - ruby_call - - - 12 - - - 1 - 2 - 1027501 - - - - - - - - - ruby_call_operator - 571632 - - - ruby_call - 571632 - - - operator - 571632 - - - - - ruby_call - operator - - - 12 - - - 1 - 2 - 571632 - - - - - - - operator - ruby_call - - - 12 - - - 1 - 2 - 571632 - - - - - - - - - ruby_call_receiver - 571632 - - - ruby_call - 571632 - - - receiver - 571632 - - - - - ruby_call - receiver - - - 12 - - - 1 - 2 - 571632 - - - - - - - receiver - ruby_call - - - 12 - - - 1 - 2 - 571632 - - - - - - - - - ruby_case_child - 4685 - - - ruby_case__ - 1267 - - - index - 86 - - - child - 4685 - - - - - ruby_case__ - index - - - 12 - - - 1 - 2 - 69 - - - 2 - 3 - 405 - - - 3 - 4 - 399 - - - 4 - 5 - 166 - - - 5 - 6 - 89 - - - 6 - 12 - 100 - - - 12 - 87 - 39 - - - - - - - ruby_case__ - child - - - 12 - - - 1 - 2 - 69 - - - 2 - 3 - 405 - - - 3 - 4 - 399 - - - 4 - 5 - 166 - - - 5 - 6 - 89 - - - 6 - 12 - 100 - - - 12 - 87 - 39 - - - - - - - index - ruby_case__ - - - 12 - - - 1 - 2 - 42 - - - 2 - 3 - 12 - - - 3 - 6 - 6 - - - 6 - 9 - 7 - - - 9 - 31 - 7 - - - 39 - 140 - 7 - - - 228 - 1268 - 5 - - - - - - - index - child - - - 12 - - - 1 - 2 - 42 - - - 2 - 3 - 12 - - - 3 - 6 - 6 - - - 6 - 9 - 7 - - - 9 - 31 - 7 - - - 39 - 140 - 7 - - - 228 - 1268 - 5 - - - - - - - child - ruby_case__ - - - 12 - - - 1 - 2 - 4685 - - - - - - - child - index - - - 12 - - - 1 - 2 - 4685 - - - - - - - - - ruby_case_def - 1319 - - - id - 1319 - - - - - - ruby_case_match_clauses - 381 - - - ruby_case_match - 232 - - - index - 12 - - - clauses - 381 - - - - - ruby_case_match - index - - - 12 - - - 1 - 2 - 160 - - - 2 - 3 - 40 - - - 3 - 4 - 17 - - - 4 - 13 - 15 - - - - - - - ruby_case_match - clauses - - - 12 - - - 1 - 2 - 160 - - - 2 - 3 - 40 - - - 3 - 4 - 17 - - - 4 - 13 - 15 - - - - - - - index - ruby_case_match - - - 12 - - - 1 - 2 - 2 - - - 2 - 3 - 3 - - - 5 - 6 - 1 - - - 8 - 9 - 1 - - - 9 - 10 - 1 - - - 15 - 16 - 1 - - - 32 - 33 - 1 - - - 72 - 73 - 1 - - - 232 - 233 - 1 - - - - - - - index - clauses - - - 12 - - - 1 - 2 - 2 - - - 2 - 3 - 3 - - - 5 - 6 - 1 - - - 8 - 9 - 1 - - - 9 - 10 - 1 - - - 15 - 16 - 1 - - - 32 - 33 - 1 - - - 72 - 73 - 1 - - - 232 - 233 - 1 - - - - - - - clauses - ruby_case_match - - - 12 - - - 1 - 2 - 381 - - - - - - - clauses - index - - - 12 - - - 1 - 2 - 381 - - - - - - - - - ruby_case_match_def - 232 - - - id - 232 - - - value - 232 - - - - - id - value - - - 12 - - - 1 - 2 - 232 - - - - - - - value - id - - - 12 - - - 1 - 2 - 232 - - - - - - - - - ruby_case_match_else - 45 - - - ruby_case_match - 45 - - - else - 45 - - - - - ruby_case_match - else - - - 12 - - - 1 - 2 - 45 - - - - - - - else - ruby_case_match - - - 12 - - - 1 - 2 - 45 - - - - - - - - - ruby_case_value - 1277 - - - ruby_case__ - 1277 - - - value - 1277 - - - - - ruby_case__ - value - - - 12 - - - 1 - 2 - 1277 - - - - - - - value - ruby_case__ - - - 12 - - - 1 - 2 - 1277 - - - - - - - - - ruby_chained_string_child - 3320 - - - ruby_chained_string - 884 - - - index - 35 - - - child - 3320 - - - - - ruby_chained_string - index - - - 12 - - - 2 - 3 - 296 - - - 3 - 4 - 215 - - - 4 - 5 - 128 - - - 5 - 6 - 116 - - - 6 - 8 - 65 - - - 8 - 13 - 59 - - - - - - - ruby_chained_string - child - - - 12 - - - 2 - 3 - 296 - - - 3 - 4 - 215 - - - 4 - 5 - 128 - - - 5 - 6 - 116 - - - 6 - 8 - 65 - - - 8 - 13 - 59 - - - - - - - index - ruby_chained_string - - - 12 - - - 2 - 3 - 2 - - - 4 - 5 - 2 - - - 7 - 8 - 2 - - - 8 - 9 - 2 - - - 20 - 21 - 2 - - - 33 - 34 - 2 - - - 42 - 43 - 2 - - - 81 - 82 - 2 - - - 124 - 125 - 2 - - - 196 - 197 - 2 - - - 295 - 296 - 5 - - - - - - - index - child - - - 12 - - - 2 - 3 - 2 - - - 4 - 5 - 2 - - - 7 - 8 - 2 - - - 8 - 9 - 2 - - - 20 - 21 - 2 - - - 33 - 34 - 2 - - - 42 - 43 - 2 - - - 81 - 82 - 2 - - - 124 - 125 - 2 - - - 196 - 197 - 2 - - - 295 - 296 - 5 - - - - - - - child - ruby_chained_string - - - 12 - - - 1 - 2 - 3320 - - - - - - - child - index - - - 12 - - - 1 - 2 - 3320 - - - - - - - - - ruby_chained_string_def - 884 - - - id - 884 - - - - - - ruby_class_body - 15734 - - - ruby_class - 15734 - - - body - 15734 - - - - - ruby_class - body - - - 12 - - - 1 - 2 - 15734 - - - - - - - body - ruby_class - - - 12 - - - 1 - 2 - 15734 - - - - - - - - - ruby_class_def - 17441 - - - id - 17441 - - - name - 17441 - - - - - id - name - - - 12 - - - 1 - 2 - 17441 - - - - - - - name - id - - - 12 - - - 1 - 2 - 17441 - - - - - - - - - ruby_class_superclass - 13806 - - - ruby_class - 13806 - - - superclass - 13806 - - - - - ruby_class - superclass - - - 12 - - - 1 - 2 - 13806 - - - - - - - superclass - ruby_class - - - 12 - - - 1 - 2 - 13806 - - - - - - - - - ruby_complex_def - 72 - - - id - 72 - - - child - 72 - - - - - id - child - - - 12 - - - 1 - 2 - 72 - - - - - - - child - id - - - 12 - - - 1 - 2 - 72 - - - - - - - - - ruby_conditional_def - 2896 - - - id - 2896 - - - alternative - 2896 - - - condition - 2896 - - - consequence - 2896 - - - - - id - alternative - - - 12 - - - 1 - 2 - 2896 - - - - - - - id - condition - - - 12 - - - 1 - 2 - 2896 - - - - - - - id - consequence - - - 12 - - - 1 - 2 - 2896 - - - - - - - alternative - id - - - 12 - - - 1 - 2 - 2896 - - - - - - - alternative - condition - - - 12 - - - 1 - 2 - 2896 - - - - - - - alternative - consequence - - - 12 - - - 1 - 2 - 2896 - - - - - - - condition - id - - - 12 - - - 1 - 2 - 2896 - - - - - - - condition - alternative - - - 12 - - - 1 - 2 - 2896 - - - - - - - condition - consequence - - - 12 - - - 1 - 2 - 2896 - - - - - - - consequence - id - - - 12 - - - 1 - 2 - 2896 - - - - - - - consequence - alternative - - - 12 - - - 1 - 2 - 2896 - - - - - - - consequence - condition - - - 12 - - - 1 - 2 - 2896 - - - - - - - - - ruby_delimited_symbol_child - 1742 - - - ruby_delimited_symbol - 1247 - - - index - 23 - - - child - 1742 - - - - - ruby_delimited_symbol - index - - - 12 - - - 1 - 2 - 920 - - - 2 - 3 - 254 - - - 3 - 9 - 71 - - - - - - - ruby_delimited_symbol - child - - - 12 - - - 1 - 2 - 920 - - - 2 - 3 - 254 - - - 3 - 9 - 71 - - - - - - - index - ruby_delimited_symbol - - - 12 - - - 1 - 2 - 2 - - - 3 - 4 - 2 - - - 6 - 7 - 2 - - - 9 - 10 - 2 - - - 13 - 14 - 2 - - - 24 - 25 - 2 - - - 109 - 110 - 2 - - - 416 - 417 - 2 - - - - - - - index - child - - - 12 - - - 1 - 2 - 2 - - - 3 - 4 - 2 - - - 6 - 7 - 2 - - - 9 - 10 - 2 - - - 13 - 14 - 2 - - - 24 - 25 - 2 - - - 109 - 110 - 2 - - - 416 - 417 - 2 - - - - - - - child - ruby_delimited_symbol - - - 12 - - - 1 - 2 - 1742 - - - - - - - child - index - - - 12 - - - 1 - 2 - 1742 - - - - - - - - - ruby_delimited_symbol_def - 1247 - - - id - 1247 - - - - - - ruby_destructured_left_assignment_child - 226 - - - ruby_destructured_left_assignment - 108 - - - index - 4 - - - child - 226 - - - - - ruby_destructured_left_assignment - index - - - 12 - - - 1 - 2 - 12 - - - 2 - 3 - 79 - - - 3 - 4 - 12 - - - 4 - 5 - 5 - - - - - - - ruby_destructured_left_assignment - child - - - 12 - - - 1 - 2 - 12 - - - 2 - 3 - 79 - - - 3 - 4 - 12 - - - 4 - 5 - 5 - - - - - - - index - ruby_destructured_left_assignment - - - 12 - - - 5 - 6 - 1 - - - 17 - 18 - 1 - - - 96 - 97 - 1 - - - 108 - 109 - 1 - - - - - - - index - child - - - 12 - - - 5 - 6 - 1 - - - 17 - 18 - 1 - - - 96 - 97 - 1 - - - 108 - 109 - 1 - - - - - - - child - ruby_destructured_left_assignment - - - 12 - - - 1 - 2 - 226 - - - - - - - child - index - - - 12 - - - 1 - 2 - 226 - - - - - - - - - ruby_destructured_left_assignment_def - 108 - - - id - 108 - - - - - - ruby_destructured_parameter_child - 463 - - - ruby_destructured_parameter - 208 - - - index - 11 - - - child - 463 - - - - - ruby_destructured_parameter - index - - - 12 - - - 1 - 2 - 16 - - - 2 - 3 - 162 - - - 3 - 4 - 19 - - - 4 - 12 - 11 - - - - - - - ruby_destructured_parameter - child - - - 12 - - - 1 - 2 - 16 - - - 2 - 3 - 162 - - - 3 - 4 - 19 - - - 4 - 12 - 11 - - - - - - - index - ruby_destructured_parameter - - - 12 - - - 2 - 3 - 1 - - - 3 - 4 - 5 - - - 5 - 6 - 1 - - - 11 - 12 - 1 - - - 30 - 31 - 1 - - - 192 - 193 - 1 - - - 208 - 209 - 1 - - - - - - - index - child - - - 12 - - - 2 - 3 - 1 - - - 3 - 4 - 5 - - - 5 - 6 - 1 - - - 11 - 12 - 1 - - - 30 - 31 - 1 - - - 192 - 193 - 1 - - - 208 - 209 - 1 - - - - - - - child - ruby_destructured_parameter - - - 12 - - - 1 - 2 - 463 - - - - - - - child - index - - - 12 - - - 1 - 2 - 463 - - - - - - - - - ruby_destructured_parameter_def - 208 - - - id - 208 - - - - - - ruby_do_block_body - 145373 - - - ruby_do_block - 145373 - - - body - 145373 - - - - - ruby_do_block - body - - - 12 - - - 1 - 2 - 145373 - - - - - - - body - ruby_do_block - - - 12 - - - 1 - 2 - 145373 - - - - - - - - - ruby_do_block_def - 145534 - - - id - 145534 - - - - - - ruby_do_block_parameters - 16724 - - - ruby_do_block - 16724 - - - parameters - 16724 - - - - - ruby_do_block - parameters - - - 12 - - - 1 - 2 - 16724 - - - - - - - parameters - ruby_do_block - - - 12 - - - 1 - 2 - 16724 - - - - - - - - - ruby_do_child - 9352 - - - ruby_do - 1651 - - - index - 211 - - - child - 9352 - - - - - ruby_do - index - - - 12 - - - 1 - 2 - 347 - - - 2 - 3 - 300 - - - 3 - 4 - 204 - - - 4 - 6 - 149 - - - 6 - 7 - 25 - - - 7 - 8 - 137 - - - 8 - 9 - 209 - - - 9 - 14 - 116 - - - 14 - 18 - 125 - - - 18 - 212 - 39 - - - - - - - ruby_do - child - - - 12 - - - 1 - 2 - 347 - - - 2 - 3 - 300 - - - 3 - 4 - 204 - - - 4 - 6 - 149 - - - 6 - 7 - 25 - - - 7 - 8 - 137 - - - 8 - 9 - 209 - - - 9 - 14 - 116 - - - 14 - 18 - 125 - - - 18 - 212 - 39 - - - - - - - index - ruby_do - - - 12 - - - 1 - 2 - 105 - - - 2 - 3 - 26 - - - 3 - 4 - 31 - - - 4 - 6 - 18 - - - 6 - 63 - 16 - - - 116 - 1652 - 15 - - - - - - - index - child - - - 12 - - - 1 - 2 - 105 - - - 2 - 3 - 26 - - - 3 - 4 - 31 - - - 4 - 6 - 18 - - - 6 - 63 - 16 - - - 116 - 1652 - 15 - - - - - - - child - ruby_do - - - 12 - - - 1 - 2 - 9352 - - - - - - - child - index - - - 12 - - - 1 - 2 - 9352 - - - - - - - - - ruby_do_def - 1675 - - - id - 1675 - - - - - - ruby_element_reference_child - 82748 - - - ruby_element_reference - 82601 - - - index - 4 - - - child - 82748 - - - - - ruby_element_reference - index - - - 12 - - - 1 - 2 - 82455 - - - 2 - 3 - 146 - - - - - - - ruby_element_reference - child - - - 12 - - - 1 - 2 - 82455 - - - 2 - 3 - 146 - - - - - - - index - ruby_element_reference - - - 12 - - - 62 - 63 - 2 - - - 34958 - 34959 - 2 - - - - - - - index - child - - - 12 - - - 62 - 63 - 2 - - - 34958 - 34959 - 2 - - - - - - - child - ruby_element_reference - - - 12 - - - 1 - 2 - 82748 - - - - - - - child - index - - - 12 - - - 1 - 2 - 82748 - - - - - - - - - ruby_element_reference_def - 82606 - - - id - 82606 - - - object - 82606 - - - - - id - object - - - 12 - - - 1 - 2 - 82606 - - - - - - - object - id - - - 12 - - - 1 - 2 - 82606 - - - - - - - - - ruby_else_child - 9730 - - - ruby_else - 7669 - - - index - 32 - - - child - 9730 - - - - - ruby_else - index - - - 12 - - - 1 - 2 - 6454 - - - 2 - 3 - 758 - - - 3 - 12 - 455 - - - - - - - ruby_else - child - - - 12 - - - 1 - 2 - 6454 - - - 2 - 3 - 758 - - - 3 - 12 - 455 - - - - - - - index - ruby_else - - - 12 - - - 1 - 2 - 2 - - - 4 - 5 - 2 - - - 5 - 6 - 2 - - - 6 - 7 - 2 - - - 9 - 10 - 2 - - - 15 - 16 - 2 - - - 26 - 27 - 2 - - - 64 - 65 - 2 - - - 152 - 153 - 2 - - - 405 - 406 - 2 - - - 2557 - 2558 - 2 - - - - - - - index - child - - - 12 - - - 1 - 2 - 2 - - - 4 - 5 - 2 - - - 5 - 6 - 2 - - - 6 - 7 - 2 - - - 9 - 10 - 2 - - - 15 - 16 - 2 - - - 26 - 27 - 2 - - - 64 - 65 - 2 - - - 152 - 153 - 2 - - - 405 - 406 - 2 - - - 2557 - 2558 - 2 - - - - - - - child - ruby_else - - - 12 - - - 1 - 2 - 9730 - - - - - - - child - index - - - 12 - - - 1 - 2 - 9730 - - - - - - - - - ruby_else_def - 7681 - - - id - 7681 - - - - - - ruby_elsif_alternative - 1058 - - - ruby_elsif - 1058 - - - alternative - 1058 - - - - - ruby_elsif - alternative - - - 12 - - - 1 - 2 - 1058 - - - - - - - alternative - ruby_elsif - - - 12 - - - 1 - 2 - 1058 - - - - - - - - - ruby_elsif_consequence - 1571 - - - ruby_elsif - 1571 - - - consequence - 1571 - - - - - ruby_elsif - consequence - - - 12 - - - 1 - 2 - 1571 - - - - - - - consequence - ruby_elsif - - - 12 - - - 1 - 2 - 1571 - - - - - - - - - ruby_elsif_def - 1583 - - - id - 1583 - - - condition - 1583 - - - - - id - condition - - - 12 - - - 1 - 2 - 1583 - - - - - - - condition - id - - - 12 - - - 1 - 2 - 1583 - - - - - - - - - ruby_end_block_child - 27 - - - ruby_end_block - 13 - - - index - 10 - - - child - 27 - - - - - ruby_end_block - index - - - 12 - - - 1 - 2 - 8 - - - 2 - 3 - 3 - - - 3 - 4 - 1 - - - 10 - 11 - 1 - - - - - - - ruby_end_block - child - - - 12 - - - 1 - 2 - 8 - - - 2 - 3 - 3 - - - 3 - 4 - 1 - - - 10 - 11 - 1 - - - - - - - index - ruby_end_block - - - 12 - - - 1 - 2 - 7 - - - 2 - 3 - 1 - - - 5 - 6 - 1 - - - 13 - 14 - 1 - - - - - - - index - child - - - 12 - - - 1 - 2 - 7 - - - 2 - 3 - 1 - - - 5 - 6 - 1 - - - 13 - 14 - 1 - - - - - - - child - ruby_end_block - - - 12 - - - 1 - 2 - 27 - - - - - - - child - index - - - 12 - - - 1 - 2 - 27 - - - - - - - - - ruby_end_block_def - 13 - - - id - 13 - - - - - - ruby_ensure_child - 5236 - - - ruby_ensure - 4106 - - - index - 47 - - - child - 5236 - - - - - ruby_ensure - index - - - 12 - - - 1 - 2 - 3323 - - - 2 - 3 - 554 - - - 3 - 17 - 227 - - - - - - - ruby_ensure - child - - - 12 - - - 1 - 2 - 3323 - - - 2 - 3 - 554 - - - 3 - 17 - 227 - - - - - - - index - ruby_ensure - - - 12 - - - 1 - 2 - 23 - - - 3 - 4 - 5 - - - 4 - 5 - 2 - - - 5 - 6 - 2 - - - 17 - 18 - 2 - - - 76 - 77 - 2 - - - 261 - 262 - 2 - - - 1369 - 1370 - 2 - - - - - - - index - child - - - 12 - - - 1 - 2 - 23 - - - 3 - 4 - 5 - - - 4 - 5 - 2 - - - 5 - 6 - 2 - - - 17 - 18 - 2 - - - 76 - 77 - 2 - - - 261 - 262 - 2 - - - 1369 - 1370 - 2 - - - - - - - child - ruby_ensure - - - 12 - - - 1 - 2 - 5236 - - - - - - - child - index - - - 12 - - - 1 - 2 - 5236 - - - - - - - - - ruby_ensure_def - 4106 - - - id - 4106 - - - - - - ruby_exception_variable_def - 935 - - - id - 935 - - - child - 935 - - - - - id - child - - - 12 - - - 1 - 2 - 935 - - - - - - - child - id - - - 12 - - - 1 - 2 - 935 - - - - - - - - - ruby_exceptions_child - 2128 - - - ruby_exceptions - 1904 - - - index - 11 - - - child - 2128 - - - - - ruby_exceptions - index - - - 12 - - - 1 - 2 - 1748 - - - 2 - 5 - 153 - - - 5 - 6 - 2 - - - - - - - ruby_exceptions - child - - - 12 - - - 1 - 2 - 1748 - - - 2 - 5 - 153 - - - 5 - 6 - 2 - - - - - - - index - ruby_exceptions - - - 12 - - - 1 - 2 - 2 - - - 6 - 7 - 2 - - - 22 - 23 - 2 - - - 66 - 67 - 2 - - - 806 - 807 - 2 - - - - - - - index - child - - - 12 - - - 1 - 2 - 2 - - - 6 - 7 - 2 - - - 22 - 23 - 2 - - - 66 - 67 - 2 - - - 806 - 807 - 2 - - - - - - - child - ruby_exceptions - - - 12 - - - 1 - 2 - 2128 - - - - - - - child - index - - - 12 - - - 1 - 2 - 2128 - - - - - - - - - ruby_exceptions_def - 1904 - - - id - 1904 - - - - - - ruby_expression_reference_pattern_def - 3 - - - id - 3 - - - value - 3 - - - - - id - value - - - 12 - - - 1 - 2 - 3 - - - - - - - value - id - - - 12 - - - 1 - 2 - 3 - - - - - - - - - ruby_find_pattern_child - 56 - - - ruby_find_pattern - 18 - - - index - 4 - - - child - 56 - - - - - ruby_find_pattern - index - - - 12 - - - 3 - 4 - 16 - - - 4 - 5 - 2 - - - - - - - ruby_find_pattern - child - - - 12 - - - 3 - 4 - 16 - - - 4 - 5 - 2 - - - - - - - index - ruby_find_pattern - - - 12 - - - 2 - 3 - 1 - - - 18 - 19 - 3 - - - - - - - index - child - - - 12 - - - 2 - 3 - 1 - - - 18 - 19 - 3 - - - - - - - child - ruby_find_pattern - - - 12 - - - 1 - 2 - 56 - - - - - - - child - index - - - 12 - - - 1 - 2 - 56 - - - - - - - - - ruby_find_pattern_class - 5 - - - ruby_find_pattern - 5 - - - class - 5 - - - - - ruby_find_pattern - class - - - 12 - - - 1 - 2 - 5 - - - - - - - class - ruby_find_pattern - - - 12 - - - 1 - 2 - 5 - - - - - - - - - ruby_find_pattern_def - 18 - - - id - 18 - - - - - - ruby_for_def - 136 - - - id - 136 - - - body - 136 - - - pattern - 136 - - - value - 136 - - - - - id - body - - - 12 - - - 1 - 2 - 136 - - - - - - - id - pattern - - - 12 - - - 1 - 2 - 136 - - - - - - - id - value - - - 12 - - - 1 - 2 - 136 - - - - - - - body - id - - - 12 - - - 1 - 2 - 136 - - - - - - - body - pattern - - - 12 - - - 1 - 2 - 136 - - - - - - - body - value - - - 12 - - - 1 - 2 - 136 - - - - - - - pattern - id - - - 12 - - - 1 - 2 - 136 - - - - - - - pattern - body - - - 12 - - - 1 - 2 - 136 - - - - - - - pattern - value - - - 12 - - - 1 - 2 - 136 - - - - - - - value - id - - - 12 - - - 1 - 2 - 136 - - - - - - - value - body - - - 12 - - - 1 - 2 - 136 - - - - - - - value - pattern - - - 12 - - - 1 - 2 - 136 - - - - - - - - - ruby_hash_child - 96207 - - - ruby_hash - 37893 - - - index - 1439 - - - child - 96207 - - - - - ruby_hash - index - - - 12 - - - 1 - 2 - 15577 - - - 2 - 3 - 10573 - - - 3 - 4 - 4318 - - - 4 - 5 - 4385 - - - 5 - 20 - 2878 - - - 20 - 108 - 161 - - - - - - - ruby_hash - child - - - 12 - - - 1 - 2 - 15577 - - - 2 - 3 - 10573 - - - 3 - 4 - 4318 - - - 4 - 5 - 4385 - - - 5 - 20 - 2878 - - - 20 - 108 - 161 - - - - - - - index - ruby_hash - - - 12 - - - 1 - 2 - 363 - - - 2 - 3 - 255 - - - 3 - 4 - 336 - - - 5 - 6 - 107 - - - 7 - 13 - 121 - - - 16 - 55 - 121 - - - 59 - 1660 - 121 - - - 2817 - 2818 - 13 - - - - - - - index - child - - - 12 - - - 1 - 2 - 363 - - - 2 - 3 - 255 - - - 3 - 4 - 336 - - - 5 - 6 - 107 - - - 7 - 13 - 121 - - - 16 - 55 - 121 - - - 59 - 1660 - 121 - - - 2817 - 2818 - 13 - - - - - - - child - ruby_hash - - - 12 - - - 1 - 2 - 96207 - - - - - - - child - index - - - 12 - - - 1 - 2 - 96207 - - - - - - - - - ruby_hash_def - 41915 - - - id - 41915 - - - - - - ruby_hash_pattern_child - 94 - - - ruby_hash_pattern - 68 - - - index - 4 - - - child - 94 - - - - - ruby_hash_pattern - index - - - 12 - - - 1 - 2 - 50 - - - 2 - 3 - 12 - - - 3 - 5 - 6 - - - - - - - ruby_hash_pattern - child - - - 12 - - - 1 - 2 - 50 - - - 2 - 3 - 12 - - - 3 - 5 - 6 - - - - - - - index - ruby_hash_pattern - - - 12 - - - 2 - 3 - 1 - - - 6 - 7 - 1 - - - 18 - 19 - 1 - - - 68 - 69 - 1 - - - - - - - index - child - - - 12 - - - 2 - 3 - 1 - - - 6 - 7 - 1 - - - 18 - 19 - 1 - - - 68 - 69 - 1 - - - - - - - child - ruby_hash_pattern - - - 12 - - - 1 - 2 - 94 - - - - - - - child - index - - - 12 - - - 1 - 2 - 94 - - - - - - - - - ruby_hash_pattern_class - 32 - - - ruby_hash_pattern - 32 - - - class - 32 - - - - - ruby_hash_pattern - class - - - 12 - - - 1 - 2 - 32 - - - - - - - class - ruby_hash_pattern - - - 12 - - - 1 - 2 - 32 - - - - - - - - - ruby_hash_pattern_def - 73 - - - id - 73 - - - - - - ruby_hash_splat_argument_child - 1988 - - - ruby_hash_splat_argument - 1988 - - - child - 1988 - - - - - ruby_hash_splat_argument - child - - - 12 - - - 1 - 2 - 1988 - - - - - - - child - ruby_hash_splat_argument - - - 12 - - - 1 - 2 - 1988 - - - - - - - - - ruby_hash_splat_argument_def - 1989 - - - id - 1989 - - - - - - ruby_hash_splat_parameter_def - 1574 - - - id - 1574 - - - - - - ruby_hash_splat_parameter_name - 1352 - - - ruby_hash_splat_parameter - 1352 - - - name - 1352 - - - - - ruby_hash_splat_parameter - name - - - 12 - - - 1 - 2 - 1352 - - - - - - - name - ruby_hash_splat_parameter - - - 12 - - - 1 - 2 - 1352 - - - - - - - - - ruby_heredoc_body_child - 26244 - - - ruby_heredoc_body - 5817 - - - index - 512 - - - child - 26244 - - - - - ruby_heredoc_body - index - - - 12 - - - 2 - 3 - 3504 - - - 4 - 5 - 701 - - - 5 - 6 - 2 - - - 6 - 7 - 675 - - - 7 - 9 - 328 - - - 10 - 17 - 467 - - - 17 - 218 - 137 - - - - - - - ruby_heredoc_body - child - - - 12 - - - 2 - 3 - 3504 - - - 4 - 5 - 701 - - - 5 - 6 - 2 - - - 6 - 7 - 675 - - - 7 - 9 - 328 - - - 10 - 17 - 467 - - - 17 - 218 - 137 - - - - - - - index - ruby_heredoc_body - - - 12 - - - 1 - 2 - 302 - - - 2 - 3 - 40 - - - 3 - 5 - 47 - - - 5 - 13 - 40 - - - 13 - 43 - 40 - - - 56 - 2463 - 42 - - - - - - - index - child - - - 12 - - - 1 - 2 - 302 - - - 2 - 3 - 40 - - - 3 - 5 - 47 - - - 5 - 13 - 40 - - - 13 - 43 - 40 - - - 56 - 2463 - 42 - - - - - - - child - ruby_heredoc_body - - - 12 - - - 1 - 2 - 26244 - - - - - - - child - index - - - 12 - - - 1 - 2 - 26244 - - - - - - - - - ruby_heredoc_body_def - 6934 - - - id - 6934 - - - - - - ruby_if_alternative - 7192 - - - ruby_if - 7192 - - - alternative - 7192 - - - - - ruby_if - alternative - - - 12 - - - 1 - 2 - 7192 - - - - - - - alternative - ruby_if - - - 12 - - - 1 - 2 - 7192 - - - - - - - - - ruby_if_consequence - 16117 - - - ruby_if - 16117 - - - consequence - 16117 - - - - - ruby_if - consequence - - - 12 - - - 1 - 2 - 16117 - - - - - - - consequence - ruby_if - - - 12 - - - 1 - 2 - 16117 - - - - - - - - - ruby_if_def - 16164 - - - id - 16164 - - - condition - 16164 - - - - - id - condition - - - 12 - - - 1 - 2 - 16164 - - - - - - - condition - id - - - 12 - - - 1 - 2 - 16164 - - - - - - - - - ruby_if_guard_def - 9 - - - id - 9 - - - condition - 9 - - - - - id - condition - - - 12 - - - 1 - 2 - 9 - - - - - - - condition - id - - - 12 - - - 1 - 2 - 9 - - - - - - - - - ruby_if_modifier_def - 14541 - - - id - 14541 - - - body - 14541 - - - condition - 14541 - - - - - id - body - - - 12 - - - 1 - 2 - 14541 - - - - - - - id - condition - - - 12 - - - 1 - 2 - 14541 - - - - - - - body - id - - - 12 - - - 1 - 2 - 14541 - - - - - - - body - condition - - - 12 - - - 1 - 2 - 14541 - - - - - - - condition - id - - - 12 - - - 1 - 2 - 14541 - - - - - - - condition - body - - - 12 - - - 1 - 2 - 14541 - - - - - - - - - ruby_in_clause_body - 341 - - - ruby_in_clause - 341 - - - body - 341 - - - - - ruby_in_clause - body - - - 12 - - - 1 - 2 - 341 - - - - - - - body - ruby_in_clause - - - 12 - - - 1 - 2 - 341 - - - - - - - - - ruby_in_clause_def - 381 - - - id - 381 - - - pattern - 381 - - - - - id - pattern - - - 12 - - - 1 - 2 - 381 - - - - - - - pattern - id - - - 12 - - - 1 - 2 - 381 - - - - - - - - - ruby_in_clause_guard - 13 - - - ruby_in_clause - 13 - - - guard - 13 - - - - - ruby_in_clause - guard - - - 12 - - - 1 - 2 - 13 - - - - - - - guard - ruby_in_clause - - - 12 - - - 1 - 2 - 13 - - - - - - - - - ruby_in_def - 136 - - - id - 136 - - - child - 136 - - - - - id - child - - - 12 - - - 1 - 2 - 136 - - - - - - - child - id - - - 12 - - - 1 - 2 - 136 - - - - - - - - - ruby_interpolation_child - 38493 - - - ruby_interpolation - 38493 - - - index - 2 - - - child - 38493 - - - - - ruby_interpolation - index - - - 12 - - - 1 - 2 - 38493 - - - - - - - ruby_interpolation - child - - - 12 - - - 1 - 2 - 38493 - - - - - - - index - ruby_interpolation - - - 12 - - - 16291 - 16292 - 2 - - - - - - - index - child - - - 12 - - - 16291 - 16292 - 2 - - - - - - - child - ruby_interpolation - - - 12 - - - 1 - 2 - 38493 - - - - - - - child - index - - - 12 - - - 1 - 2 - 38493 - - - - - - - - - ruby_interpolation_def - 38493 - - - id - 38493 - - - - - - ruby_keyword_parameter_def - 4763 - - - id - 4763 - - - name - 4763 - - - - - id - name - - - 12 - - - 1 - 2 - 4763 - - - - - - - name - id - - - 12 - - - 1 - 2 - 4763 - - - - - - - - - ruby_keyword_parameter_value - 3293 - - - ruby_keyword_parameter - 3293 - - - value - 3293 - - - - - ruby_keyword_parameter - value - - - 12 - - - 1 - 2 - 3293 - - - - - - - value - ruby_keyword_parameter - - - 12 - - - 1 - 2 - 3293 - - - - - - - - - ruby_keyword_pattern_def - 77 - - - id - 77 - - - key__ - 77 - - - - - id - key__ - - - 12 - - - 1 - 2 - 77 - - - - - - - key__ - id - - - 12 - - - 1 - 2 - 77 - - - - - - - - - ruby_keyword_pattern_value - 56 - - - ruby_keyword_pattern - 56 - - - value - 56 - - - - - ruby_keyword_pattern - value - - - 12 - - - 1 - 2 - 56 - - - - - - - value - ruby_keyword_pattern - - - 12 - - - 1 - 2 - 56 - - - - - - - - - ruby_lambda_def - 8187 - - - id - 8187 - - - body - 8187 - - - - - id - body - - - 12 - - - 1 - 2 - 8187 - - - - - - - body - id - - - 12 - - - 1 - 2 - 8187 - - - - - - - - - ruby_lambda_parameters - 1811 - - - ruby_lambda - 1811 - - - parameters - 1811 - - - - - ruby_lambda - parameters - - - 12 - - - 1 - 2 - 1811 - - - - - - - parameters - ruby_lambda - - - 12 - - - 1 - 2 - 1811 - - - - - - - - - ruby_lambda_parameters_child - 2197 - - - ruby_lambda_parameters - 1801 - - - index - 8 - - - child - 2197 - - - - - ruby_lambda_parameters - index - - - 12 - - - 1 - 2 - 1545 - - - 2 - 3 - 164 - - - 3 - 9 - 92 - - - - - - - ruby_lambda_parameters - child - - - 12 - - - 1 - 2 - 1545 - - - 2 - 3 - 164 - - - 3 - 9 - 92 - - - - - - - index - ruby_lambda_parameters - - - 12 - - - 1 - 2 - 1 - - - 3 - 4 - 1 - - - 4 - 5 - 1 - - - 11 - 12 - 1 - - - 29 - 30 - 1 - - - 92 - 93 - 1 - - - 256 - 257 - 1 - - - 1801 - 1802 - 1 - - - - - - - index - child - - - 12 - - - 1 - 2 - 1 - - - 3 - 4 - 1 - - - 4 - 5 - 1 - - - 11 - 12 - 1 - - - 29 - 30 - 1 - - - 92 - 93 - 1 - - - 256 - 257 - 1 - - - 1801 - 1802 - 1 - - - - - - - child - ruby_lambda_parameters - - - 12 - - - 1 - 2 - 2197 - - - - - - - child - index - - - 12 - - - 1 - 2 - 2197 - - - - - - - - - ruby_lambda_parameters_def - 1811 - - - id - 1811 - - - - - - ruby_left_assignment_list_child - 6934 - - - ruby_left_assignment_list - 3100 - - - index - 15 - - - child - 6934 - - - - - ruby_left_assignment_list - index - - - 12 - - - 1 - 2 - 382 - - - 2 - 3 - 2002 - - - 3 - 4 - 531 - - - 4 - 16 - 185 - - - - - - - ruby_left_assignment_list - child - - - 12 - - - 1 - 2 - 382 - - - 2 - 3 - 2002 - - - 3 - 4 - 531 - - - 4 - 16 - 185 - - - - - - - index - ruby_left_assignment_list - - - 12 - - - 3 - 4 - 1 - - - 6 - 7 - 2 - - - 10 - 11 - 3 - - - 15 - 16 - 1 - - - 20 - 21 - 1 - - - 22 - 23 - 1 - - - 41 - 42 - 1 - - - 72 - 73 - 1 - - - 185 - 186 - 1 - - - 716 - 717 - 1 - - - 2718 - 2719 - 1 - - - 3100 - 3101 - 1 - - - - - - - index - child - - - 12 - - - 3 - 4 - 1 - - - 6 - 7 - 2 - - - 10 - 11 - 3 - - - 15 - 16 - 1 - - - 20 - 21 - 1 - - - 22 - 23 - 1 - - - 41 - 42 - 1 - - - 72 - 73 - 1 - - - 185 - 186 - 1 - - - 716 - 717 - 1 - - - 2718 - 2719 - 1 - - - 3100 - 3101 - 1 - - - - - - - child - ruby_left_assignment_list - - - 12 - - - 1 - 2 - 6934 - - - - - - - child - index - - - 12 - - - 1 - 2 - 6934 - - - - - - - - - ruby_left_assignment_list_def - 3100 - - - id - 3100 - - - - - - ruby_match_pattern_def - 31 - - - id - 31 - - - pattern - 31 - - - value - 31 - - - - - id - pattern - - - 12 - - - 1 - 2 - 31 - - - - - - - id - value - - - 12 - - - 1 - 2 - 31 - - - - - - - pattern - id - - - 12 - - - 1 - 2 - 31 - - - - - - - pattern - value - - - 12 - - - 1 - 2 - 31 - - - - - - - value - id - - - 12 - - - 1 - 2 - 31 - - - - - - - value - pattern - - - 12 - - - 1 - 2 - 31 - - - - - - - - - ruby_method_body - 102401 - - - ruby_method - 102401 - - - body - 102401 - - - - - ruby_method - body - - - 12 - - - 1 - 2 - 102401 - - - - - - - body - ruby_method - - - 12 - - - 1 - 2 - 102401 - - - - - - - - - ruby_method_def - 103532 - - - id - 103532 - - - name - 103532 - - - - - id - name - - - 12 - - - 1 - 2 - 103532 - - - - - - - name - id - - - 12 - - - 1 - 2 - 103532 - - - - - - - - - ruby_method_parameters - 29519 - - - ruby_method - 29519 - - - parameters - 29519 - - - - - ruby_method - parameters - - - 12 - - - 1 - 2 - 29519 - - - - - - - parameters - ruby_method - - - 12 - - - 1 - 2 - 29519 - - - - - - - - - ruby_method_parameters_child - 51112 - - - ruby_method_parameters - 31001 - - - index - 41 - - - child - 51112 - - - - - ruby_method_parameters - index - - - 12 - - - 1 - 2 - 18836 - - - 2 - 3 - 7543 - - - 3 - 4 - 2840 - - - 4 - 15 - 1781 - - - - - - - ruby_method_parameters - child - - - 12 - - - 1 - 2 - 18836 - - - 2 - 3 - 7543 - - - 3 - 4 - 2840 - - - 4 - 15 - 1781 - - - - - - - index - ruby_method_parameters - - - 12 - - - 1 - 2 - 8 - - - 4 - 5 - 2 - - - 7 - 8 - 2 - - - 13 - 14 - 2 - - - 37 - 38 - 2 - - - 59 - 60 - 2 - - - 129 - 130 - 2 - - - 262 - 263 - 2 - - - 594 - 595 - 2 - - - 1541 - 1542 - 2 - - - 4056 - 4057 - 2 - - - 10336 - 10337 - 2 - - - - - - - index - child - - - 12 - - - 1 - 2 - 8 - - - 4 - 5 - 2 - - - 7 - 8 - 2 - - - 13 - 14 - 2 - - - 37 - 38 - 2 - - - 59 - 60 - 2 - - - 129 - 130 - 2 - - - 262 - 263 - 2 - - - 594 - 595 - 2 - - - 1541 - 1542 - 2 - - - 4056 - 4057 - 2 - - - 10336 - 10337 - 2 - - - - - - - child - ruby_method_parameters - - - 12 - - - 1 - 2 - 51112 - - - - - - - child - index - - - 12 - - - 1 - 2 - 51112 - - - - - - - - - ruby_method_parameters_def - 31208 - - - id - 31208 - - - - - - ruby_module_body - 22881 - - - ruby_module - 22881 - - - body - 22881 - - - - - ruby_module - body - - - 12 - - - 1 - 2 - 22881 - - - - - - - body - ruby_module - - - 12 - - - 1 - 2 - 22881 - - - - - - - - - ruby_module_def - 22962 - - - id - 22962 - - - name - 22962 - - - - - id - name - - - 12 - - - 1 - 2 - 22962 - - - - - - - name - id - - - 12 - - - 1 - 2 - 22962 - - - - - - - - - ruby_next_child - 256 - - - ruby_next - 256 - - - child - 256 - - - - - ruby_next - child - - - 12 - - - 1 - 2 - 256 - - - - - - - child - ruby_next - - - 12 - - - 1 - 2 - 256 - - - - - - - - - ruby_next_def - 2020 - - - id - 2020 - - - - - - ruby_operator_assignment_def - 6160 - - - id - 6160 - - - left - 6160 - - - operator - 16 - - - right - 6160 - - - - - id - left - - - 12 - - - 1 - 2 - 6160 - - - - - - - id - operator - - - 12 - - - 1 - 2 - 6160 - - - - - - - id - right - - - 12 - - - 1 - 2 - 6160 - - - - - - - left - id - - - 12 - - - 1 - 2 - 6160 - - - - - - - left - operator - - - 12 - - - 1 - 2 - 6160 - - - - - - - left - right - - - 12 - - - 1 - 2 - 6160 - - - - - - - operator - id - - - 12 - - - 3 - 4 - 2 - - - 4 - 5 - 2 - - - 10 - 11 - 2 - - - 11 - 12 - 2 - - - 64 - 65 - 2 - - - 707 - 708 - 2 - - - 1808 - 1809 - 2 - - - - - - - operator - left - - - 12 - - - 3 - 4 - 2 - - - 4 - 5 - 2 - - - 10 - 11 - 2 - - - 11 - 12 - 2 - - - 64 - 65 - 2 - - - 707 - 708 - 2 - - - 1808 - 1809 - 2 - - - - - - - operator - right - - - 12 - - - 3 - 4 - 2 - - - 4 - 5 - 2 - - - 10 - 11 - 2 - - - 11 - 12 - 2 - - - 64 - 65 - 2 - - - 707 - 708 - 2 - - - 1808 - 1809 - 2 - - - - - - - right - id - - - 12 - - - 1 - 2 - 6160 - - - - - - - right - left - - - 12 - - - 1 - 2 - 6160 - - - - - - - right - operator - - - 12 - - - 1 - 2 - 6160 - - - - - - - - - ruby_optional_parameter_def - 6556 - - - id - 6556 - - - name - 6556 - - - value - 6556 - - - - - id - name - - - 12 - - - 1 - 2 - 6556 - - - - - - - id - value - - - 12 - - - 1 - 2 - 6556 - - - - - - - name - id - - - 12 - - - 1 - 2 - 6556 - - - - - - - name - value - - - 12 - - - 1 - 2 - 6556 - - - - - - - value - id - - - 12 - - - 1 - 2 - 6556 - - - - - - - value - name - - - 12 - - - 1 - 2 - 6556 - - - - - - - - - ruby_pair_def - 254198 - - - id - 254198 - - - key__ - 254198 - - - - - id - key__ - - - 12 - - - 1 - 2 - 254198 - - - - - - - key__ - id - - - 12 - - - 1 - 2 - 254198 - - - - - - - - - ruby_pair_value - 254198 - - - ruby_pair - 254198 - - - value - 254198 - - - - - ruby_pair - value - - - 12 - - - 1 - 2 - 254198 - - - - - - - value - ruby_pair - - - 12 - - - 1 - 2 - 254198 - - - - - - - - - ruby_parenthesized_pattern_def - 8 - - - id - 8 - - - child - 8 - - - - - id - child - - - 12 - - - 1 - 2 - 8 - - - - - - - child - id - - - 12 - - - 1 - 2 - 8 - - - - - - - - - ruby_parenthesized_statements_child - 11347 - - - ruby_parenthesized_statements - 11258 - - - index - 4 - - - child - 11347 - - - - - ruby_parenthesized_statements - index - - - 12 - - - 1 - 2 - 11179 - - - 2 - 5 - 79 - - - - - - - ruby_parenthesized_statements - child - - - 12 - - - 1 - 2 - 11179 - - - 2 - 5 - 79 - - - - - - - index - ruby_parenthesized_statements - - - 12 - - - 1 - 2 - 1 - - - 9 - 10 - 1 - - - 79 - 80 - 1 - - - 11258 - 11259 - 1 - - - - - - - index - child - - - 12 - - - 1 - 2 - 1 - - - 9 - 10 - 1 - - - 79 - 80 - 1 - - - 11258 - 11259 - 1 - - - - - - - child - ruby_parenthesized_statements - - - 12 - - - 1 - 2 - 11347 - - - - - - - child - index - - - 12 - - - 1 - 2 - 11347 - - - - - - - - - ruby_parenthesized_statements_def - 11296 - - - id - 11296 - - - - - - ruby_pattern_def - 4745 - - - id - 4745 - - - child - 4745 - - - - - id - child - - - 12 - - - 1 - 2 - 4745 - - - - - - - child - id - - - 12 - - - 1 - 2 - 4745 - - - - - - - - - ruby_program_child - 33893 - - - ruby_program - 10674 - - - index - 239 - - - child - 33893 - - - - - ruby_program - index - - - 12 - - - 1 - 2 - 3956 - - - 2 - 3 - 2531 - - - 3 - 4 - 1772 - - - 4 - 5 - 794 - - - 5 - 8 - 902 - - - 8 - 81 - 716 - - - - - - - ruby_program - child - - - 12 - - - 1 - 2 - 3956 - - - 2 - 3 - 2531 - - - 3 - 4 - 1772 - - - 4 - 5 - 794 - - - 5 - 8 - 902 - - - 8 - 81 - 716 - - - - - - - index - ruby_program - - - 12 - - - 1 - 2 - 50 - - - 2 - 3 - 29 - - - 3 - 7 - 17 - - - 8 - 11 - 17 - - - 11 - 15 - 17 - - - 16 - 23 - 17 - - - 26 - 36 - 17 - - - 38 - 60 - 17 - - - 67 - 129 - 17 - - - 145 - 397 - 17 - - - 540 - 3560 - 14 - - - - - - - index - child - - - 12 - - - 1 - 2 - 50 - - - 2 - 3 - 29 - - - 3 - 7 - 17 - - - 8 - 11 - 17 - - - 11 - 15 - 17 - - - 16 - 23 - 17 - - - 26 - 36 - 17 - - - 38 - 60 - 17 - - - 67 - 129 - 17 - - - 145 - 397 - 17 - - - 540 - 3560 - 14 - - - - - - - child - ruby_program - - - 12 - - - 1 - 2 - 33893 - - - - - - - child - index - - - 12 - - - 1 - 2 - 33893 - - - - - - - - - ruby_program_def - 18697 - - - id - 18697 - - - - - - ruby_range_begin - 4748 - - - ruby_range - 4748 - - - begin - 4748 - - - - - ruby_range - begin - - - 12 - - - 1 - 2 - 4748 - - - - - - - begin - ruby_range - - - 12 - - - 1 - 2 - 4748 - - - - - - - - - ruby_range_def - 5066 - - - id - 5066 - - - operator - 2 - - - - - id - operator - - - 12 - - - 1 - 2 - 5066 - - - - - - - operator - id - - - 12 - - - 1376 - 1377 - 1 - - - 3690 - 3691 - 1 - - - - - - - - - ruby_range_end - 4818 - - - ruby_range - 4818 - - - end - 4818 - - - - - ruby_range - end - - - 12 - - - 1 - 2 - 4818 - - - - - - - end - ruby_range - - - 12 - - - 1 - 2 - 4818 - - - - - - - - - ruby_rational_def - 166 - - - id - 166 - - - child - 166 - - - - - id - child - - - 12 - - - 1 - 2 - 166 - - - - - - - child - id - - - 12 - - - 1 - 2 - 166 - - - - - - - - - ruby_redo_child - 0 - - - ruby_redo - 0 - - - child - 0 - - - - - ruby_redo - child - - - 12 - - - 1 - 2 - 2 - - - - - - - child - ruby_redo - - - 12 - - - 1 - 2 - 2 - - - - - - - - - ruby_redo_def - 34 - - - id - 34 - - - - - - ruby_regex_child - 45368 - - - ruby_regex - 13665 - - - index - 146 - - - child - 45368 - - - - - ruby_regex - index - - - 12 - - - 1 - 2 - 7006 - - - 2 - 3 - 800 - - - 3 - 4 - 1868 - - - 4 - 5 - 500 - - - 5 - 6 - 1124 - - - 6 - 8 - 1031 - - - 8 - 16 - 1094 - - - 16 - 50 - 236 - - - - - - - ruby_regex - child - - - 12 - - - 1 - 2 - 7006 - - - 2 - 3 - 800 - - - 3 - 4 - 1868 - - - 4 - 5 - 500 - - - 5 - 6 - 1124 - - - 6 - 8 - 1031 - - - 8 - 16 - 1094 - - - 16 - 50 - 236 - - - - - - - index - ruby_regex - - - 12 - - - 1 - 2 - 17 - - - 4 - 5 - 11 - - - 6 - 7 - 2 - - - 7 - 8 - 11 - - - 8 - 15 - 11 - - - 15 - 18 - 8 - - - 18 - 21 - 11 - - - 21 - 31 - 11 - - - 32 - 80 - 11 - - - 103 - 184 - 11 - - - 249 - 445 - 11 - - - 696 - 1331 - 11 - - - 1953 - 4557 - 8 - - - - - - - index - child - - - 12 - - - 1 - 2 - 17 - - - 4 - 5 - 11 - - - 6 - 7 - 2 - - - 7 - 8 - 11 - - - 8 - 15 - 11 - - - 15 - 18 - 8 - - - 18 - 21 - 11 - - - 21 - 31 - 11 - - - 32 - 80 - 11 - - - 103 - 184 - 11 - - - 249 - 445 - 11 - - - 696 - 1331 - 11 - - - 1953 - 4557 - 8 - - - - - - - child - ruby_regex - - - 12 - - - 1 - 2 - 45368 - - - - - - - child - index - - - 12 - - - 1 - 2 - 45368 - - - - - - - - - ruby_regex_def - 13680 - - - id - 13680 - - - - - - ruby_rescue_body - 2050 - - - ruby_rescue - 2050 - - - body - 2050 - - - - - ruby_rescue - body - - - 12 - - - 1 - 2 - 2050 - - - - - - - body - ruby_rescue - - - 12 - - - 1 - 2 - 2050 - - - - - - - - - ruby_rescue_def - 2299 - - - id - 2299 - - - - - - ruby_rescue_exceptions - 1904 - - - ruby_rescue - 1904 - - - exceptions - 1904 - - - - - ruby_rescue - exceptions - - - 12 - - - 1 - 2 - 1904 - - - - - - - exceptions - ruby_rescue - - - 12 - - - 1 - 2 - 1904 - - - - - - - - - ruby_rescue_modifier_def - 458 - - - id - 458 - - - body - 458 - - - handler - 458 - - - - - id - body - - - 12 - - - 1 - 2 - 458 - - - - - - - id - handler - - - 12 - - - 1 - 2 - 458 - - - - - - - body - id - - - 12 - - - 1 - 2 - 458 - - - - - - - body - handler - - - 12 - - - 1 - 2 - 458 - - - - - - - handler - id - - - 12 - - - 1 - 2 - 458 - - - - - - - handler - body - - - 12 - - - 1 - 2 - 458 - - - - - - - - - ruby_rescue_variable - 935 - - - ruby_rescue - 935 - - - variable - 935 - - - - - ruby_rescue - variable - - - 12 - - - 1 - 2 - 935 - - - - - - - variable - ruby_rescue - - - 12 - - - 1 - 2 - 935 - - - - - - - - - ruby_rest_assignment_child - 392 - - - ruby_rest_assignment - 392 - - - child - 392 - - - - - ruby_rest_assignment - child - - - 12 - - - 1 - 2 - 392 - - - - - - - child - ruby_rest_assignment - - - 12 - - - 1 - 2 - 392 - - - - - - - - - ruby_rest_assignment_def - 414 - - - id - 414 - - - - - - ruby_retry_child - 0 - - - ruby_retry - 0 - - - child - 0 - - - - - ruby_retry - child - - - 12 - - - 1 - 2 - 2 - - - - - - - child - ruby_retry - - - 12 - - - 1 - 2 - 2 - - - - - - - - - ruby_retry_def - 58 - - - id - 58 - - - - - - ruby_return_child - 4938 - - - ruby_return - 4938 - - - child - 4938 - - - - - ruby_return - child - - - 12 - - - 1 - 2 - 4938 - - - - - - - child - ruby_return - - - 12 - - - 1 - 2 - 4938 - - - - - - - - - ruby_return_def - 7979 - - - id - 7979 - - - - - - ruby_right_assignment_list_child - 2741 - - - ruby_right_assignment_list - 1280 - - - index - 14 - - - child - 2741 - - - - - ruby_right_assignment_list - index - - - 12 - - - 2 - 3 - 1136 - - - 3 - 4 - 113 - - - 4 - 6 - 29 - - - - - - - ruby_right_assignment_list - child - - - 12 - - - 2 - 3 - 1136 - - - 3 - 4 - 113 - - - 4 - 6 - 29 - - - - - - - index - ruby_right_assignment_list - - - 12 - - - 2 - 3 - 2 - - - 10 - 11 - 2 - - - 48 - 49 - 2 - - - 427 - 428 - 5 - - - - - - - index - child - - - 12 - - - 2 - 3 - 2 - - - 10 - 11 - 2 - - - 48 - 49 - 2 - - - 427 - 428 - 5 - - - - - - - child - ruby_right_assignment_list - - - 12 - - - 1 - 2 - 2741 - - - - - - - child - index - - - 12 - - - 1 - 2 - 2741 - - - - - - - - - ruby_right_assignment_list_def - 1280 - - - id - 1280 - - - - - - ruby_scope_resolution_def - 87113 - - - id - 87113 - - - name - 87113 - - - - - id - name - - - 12 - - - 1 - 2 - 87113 - - - - - - - name - id - - - 12 - - - 1 - 2 - 87113 - - - - - - - - - ruby_scope_resolution_scope - 85203 - - - ruby_scope_resolution - 85203 - - - scope - 85203 - - - - - ruby_scope_resolution - scope - - - 12 - - - 1 - 2 - 85203 - - - - - - - scope - ruby_scope_resolution - - - 12 - - - 1 - 2 - 85203 - - - - - - - - - ruby_setter_def - 656 - - - id - 656 - - - name - 656 - - - - - id - name - - - 12 - - - 1 - 2 - 656 - - - - - - - name - id - - - 12 - - - 1 - 2 - 656 - - - - - - - - - ruby_singleton_class_body - 677 - - - ruby_singleton_class - 677 - - - body - 677 - - - - - ruby_singleton_class - body - - - 12 - - - 1 - 2 - 677 - - - - - - - body - ruby_singleton_class - - - 12 - - - 1 - 2 - 677 - - - - - - - - - ruby_singleton_class_def - 677 - - - id - 677 - - - value - 677 - - - - - id - value - - - 12 - - - 1 - 2 - 677 - - - - - - - value - id - - - 12 - - - 1 - 2 - 677 - - - - - - - - - ruby_singleton_method_body - 6313 - - - ruby_singleton_method - 6313 - - - body - 6313 - - - - - ruby_singleton_method - body - - - 12 - - - 1 - 2 - 6313 - - - - - - - body - ruby_singleton_method - - - 12 - - - 1 - 2 - 6313 - - - - - - - - - ruby_singleton_method_def - 6325 - - - id - 6325 - - - name - 6325 - - - object - 6325 - - - - - id - name - - - 12 - - - 1 - 2 - 6325 - - - - - - - id - object - - - 12 - - - 1 - 2 - 6325 - - - - - - - name - id - - - 12 - - - 1 - 2 - 6325 - - - - - - - name - object - - - 12 - - - 1 - 2 - 6325 - - - - - - - object - id - - - 12 - - - 1 - 2 - 6325 - - - - - - - object - name - - - 12 - - - 1 - 2 - 6325 - - - - - - - - - ruby_singleton_method_parameters - 3929 - - - ruby_singleton_method - 3929 - - - parameters - 3929 - - - - - ruby_singleton_method - parameters - - - 12 - - - 1 - 2 - 3929 - - - - - - - parameters - ruby_singleton_method - - - 12 - - - 1 - 2 - 3929 - - - - - - - - - ruby_splat_argument_child - 3605 - - - ruby_splat_argument - 3605 - - - child - 3605 - - - - - ruby_splat_argument - child - - - 12 - - - 1 - 2 - 3605 - - - - - - - child - ruby_splat_argument - - - 12 - - - 1 - 2 - 3605 - - - - - - - - - ruby_splat_argument_def - 3606 - - - id - 3606 - - - - - - ruby_splat_parameter_def - 3014 - - - id - 3014 - - - - - - ruby_splat_parameter_name - 2297 - - - ruby_splat_parameter - 2297 - - - name - 2297 - - - - - ruby_splat_parameter - name - - - 12 - - - 1 - 2 - 2297 - - - - - - - name - ruby_splat_parameter - - - 12 - - - 1 - 2 - 2297 - - - - - - - - - ruby_string_array_child - 13136 - - - ruby_string_array - 4120 - - - index - 606 - - - child - 13136 - - - - - ruby_string_array - index - - - 12 - - - 1 - 2 - 1350 - - - 2 - 3 - 1304 - - - 3 - 4 - 630 - - - 4 - 5 - 356 - - - 5 - 10 - 332 - - - 10 - 607 - 148 - - - - - - - ruby_string_array - child - - - 12 - - - 1 - 2 - 1350 - - - 2 - 3 - 1304 - - - 3 - 4 - 630 - - - 4 - 5 - 356 - - - 5 - 10 - 332 - - - 10 - 607 - 148 - - - - - - - index - ruby_string_array - - - 12 - - - 1 - 2 - 506 - - - 2 - 10 - 48 - - - 11 - 266 - 46 - - - 344 - 4121 - 6 - - - - - - - index - child - - - 12 - - - 1 - 2 - 506 - - - 2 - 10 - 48 - - - 11 - 266 - 46 - - - 344 - 4121 - 6 - - - - - - - child - ruby_string_array - - - 12 - - - 1 - 2 - 13136 - - - - - - - child - index - - - 12 - - - 1 - 2 - 13136 - - - - - - - - - ruby_string_array_def - 4287 - - - id - 4287 - - - - - - ruby_string_child - 559228 - - - ruby_string__ - 483542 - - - index - 281 - - - child - 559228 - - - - - ruby_string__ - index - - - 12 - - - 1 - 2 - 454555 - - - 2 - 282 - 28987 - - - - - - - ruby_string__ - child - - - 12 - - - 1 - 2 - 454555 - - - 2 - 282 - 28987 - - - - - - - index - ruby_string__ - - - 12 - - - 1 - 2 - 95 - - - 2 - 3 - 34 - - - 5 - 6 - 64 - - - 6 - 9 - 22 - - - 9 - 37 - 22 - - - 37 - 108 - 22 - - - 129 - 483543 - 22 - - - - - - - index - child - - - 12 - - - 1 - 2 - 95 - - - 2 - 3 - 34 - - - 5 - 6 - 64 - - - 6 - 9 - 22 - - - 9 - 37 - 22 - - - 37 - 108 - 22 - - - 129 - 483543 - 22 - - - - - - - child - ruby_string__ - - - 12 - - - 1 - 2 - 559228 - - - - - - - child - index - - - 12 - - - 1 - 2 - 559228 - - - - - - - - - ruby_string_def - 490602 - - - id - 490602 - - - - - - ruby_subshell_child - 551 - - - ruby_subshell - 359 - - - index - 32 - - - child - 551 - - - - - ruby_subshell - index - - - 12 - - - 1 - 2 - 263 - - - 2 - 3 - 53 - - - 3 - 5 - 32 - - - 5 - 12 - 8 - - - - - - - ruby_subshell - child - - - 12 - - - 1 - 2 - 263 - - - 2 - 3 - 53 - - - 3 - 5 - 32 - - - 5 - 12 - 8 - - - - - - - index - ruby_subshell - - - 12 - - - 1 - 2 - 11 - - - 2 - 3 - 5 - - - 3 - 4 - 2 - - - 7 - 8 - 2 - - - 14 - 15 - 2 - - - 32 - 33 - 2 - - - 120 - 121 - 2 - - - - - - - index - child - - - 12 - - - 1 - 2 - 11 - - - 2 - 3 - 5 - - - 3 - 4 - 2 - - - 7 - 8 - 2 - - - 14 - 15 - 2 - - - 32 - 33 - 2 - - - 120 - 121 - 2 - - - - - - - child - ruby_subshell - - - 12 - - - 1 - 2 - 551 - - - - - - - child - index - - - 12 - - - 1 - 2 - 551 - - - - - - - - - ruby_subshell_def - 359 - - - id - 359 - - - - - - ruby_superclass_def - 13806 - - - id - 13806 - - - child - 13806 - - - - - id - child - - - 12 - - - 1 - 2 - 13806 - - - - - - - child - id - - - 12 - - - 1 - 2 - 13806 - - - - - - - - - ruby_symbol_array_child - 8435 - - - ruby_symbol_array - 2240 - - - index - 233 - - - child - 8435 - - - - - ruby_symbol_array - index - - - 12 - - - 1 - 2 - 219 - - - 2 - 3 - 1129 - - - 3 - 4 - 347 - - - 4 - 5 - 160 - - - 5 - 8 - 189 - - - 8 - 24 - 170 - - - 24 - 100 - 23 - - - - - - - ruby_symbol_array - child - - - 12 - - - 1 - 2 - 219 - - - 2 - 3 - 1129 - - - 3 - 4 - 347 - - - 4 - 5 - 160 - - - 5 - 8 - 189 - - - 8 - 24 - 170 - - - 24 - 100 - 23 - - - - - - - index - ruby_symbol_array - - - 12 - - - 1 - 2 - 9 - - - 2 - 3 - 139 - - - 4 - 8 - 18 - - - 8 - 17 - 18 - - - 19 - 41 - 18 - - - 44 - 163 - 18 - - - 230 - 949 - 9 - - - - - - - index - child - - - 12 - - - 1 - 2 - 9 - - - 2 - 3 - 139 - - - 4 - 8 - 18 - - - 8 - 17 - 18 - - - 19 - 41 - 18 - - - 44 - 163 - 18 - - - 230 - 949 - 9 - - - - - - - child - ruby_symbol_array - - - 12 - - - 1 - 2 - 8435 - - - - - - - child - index - - - 12 - - - 1 - 2 - 8435 - - - - - - - - - ruby_symbol_array_def - 2240 - - - id - 2240 - - - - - - ruby_test_pattern_def - 5 - - - id - 5 - - - pattern - 5 - - - value - 5 - - - - - id - pattern - - - 12 - - - 1 - 2 - 5 - - - - - - - id - value - - - 12 - - - 1 - 2 - 5 - - - - - - - pattern - id - - - 12 - - - 1 - 2 - 5 - - - - - - - pattern - value - - - 12 - - - 1 - 2 - 5 - - - - - - - value - id - - - 12 - - - 1 - 2 - 5 - - - - - - - value - pattern - - - 12 - - - 1 - 2 - 5 - - - - - - - - - ruby_then_child - 37016 - - - ruby_then - 22229 - - - index - 85 - - - child - 37016 - - - - - ruby_then - index - - - 12 - - - 1 - 2 - 13943 - - - 2 - 3 - 5070 - - - 3 - 4 - 1817 - - - 4 - 37 - 1398 - - - - - - - ruby_then - child - - - 12 - - - 1 - 2 - 13943 - - - 2 - 3 - 5070 - - - 3 - 4 - 1817 - - - 4 - 37 - 1398 - - - - - - - index - ruby_then - - - 12 - - - 1 - 2 - 30 - - - 2 - 4 - 4 - - - 4 - 5 - 9 - - - 6 - 8 - 4 - - - 8 - 9 - 4 - - - 10 - 19 - 7 - - - 30 - 61 - 7 - - - 98 - 310 - 7 - - - 592 - 3508 - 7 - - - 9408 - 9409 - 2 - - - - - - - index - child - - - 12 - - - 1 - 2 - 30 - - - 2 - 4 - 4 - - - 4 - 5 - 9 - - - 6 - 8 - 4 - - - 8 - 9 - 4 - - - 10 - 19 - 7 - - - 30 - 61 - 7 - - - 98 - 310 - 7 - - - 592 - 3508 - 7 - - - 9408 - 9409 - 2 - - - - - - - child - ruby_then - - - 12 - - - 1 - 2 - 37016 - - - - - - - child - index - - - 12 - - - 1 - 2 - 37016 - - - - - - - - - ruby_then_def - 22229 - - - id - 22229 - - - - - - ruby_tokeninfo - 6351611 - - - id - 6351611 - - - kind - 56 - - - value - 275925 - - - - - id - kind - - - 12 - - - 1 - 2 - 6351611 - - - - - - - id - value - - - 12 - - - 1 - 2 - 6351611 - - - - - - - kind - id - - - 12 - - - 1 - 2 - 4 - - - 49 - 160 - 4 - - - 291 - 443 - 4 - - - 2054 - 2055 - 2 - - - 2462 - 2463 - 4 - - - 5047 - 5260 - 4 - - - 5496 - 7346 - 4 - - - 10365 - 10609 - 4 - - - 15376 - 22709 - 4 - - - 31415 - 70704 - 4 - - - 77014 - 106932 - 4 - - - 129596 - 673263 - 4 - - - 1509036 - 1509037 - 2 - - - - - - - kind - value - - - 12 - - - 1 - 2 - 16 - - - 6 - 26 - 4 - - - 36 - 48 - 4 - - - 68 - 121 - 4 - - - 151 - 181 - 4 - - - 1509 - 2060 - 4 - - - 3983 - 4628 - 4 - - - 5781 - 9380 - 4 - - - 13063 - 24102 - 4 - - - 58689 - 58690 - 2 - - - - - - - value - id - - - 12 - - - 1 - 2 - 164156 - - - 2 - 3 - 41140 - - - 3 - 4 - 19333 - - - 4 - 7 - 22761 - - - 7 - 29 - 20750 - - - 29 - 243390 - 7783 - - - - - - - value - kind - - - 12 - - - 1 - 2 - 262839 - - - 2 - 5 - 13085 - - - - - - - - - ruby_unary_def - 14535 - - - id - 14535 - - - operand - 14535 - - - operator - 6 - - - - - id - operand - - - 12 - - - 1 - 2 - 14535 - - - - - - - id - operator - - - 12 - - - 1 - 2 - 14535 - - - - - - - operand - id - - - 12 - - - 1 - 2 - 14535 - - - - - - - operand - operator - - - 12 - - - 1 - 2 - 14535 - - - - - - - operator - id - - - 12 - - - 97 - 98 - 1 - - - 172 - 173 - 1 - - - 947 - 948 - 1 - - - 1369 - 1370 - 1 - - - 2120 - 2121 - 1 - - - 9830 - 9831 - 1 - - - - - - - operator - operand - - - 12 - - - 97 - 98 - 1 - - - 172 - 173 - 1 - - - 947 - 948 - 1 - - - 1369 - 1370 - 1 - - - 2120 - 2121 - 1 - - - 9830 - 9831 - 1 - - - - - - - - - ruby_undef_child - 183 - - - ruby_undef - 182 - - - index - 2 - - - child - 183 - - - - - ruby_undef - index - - - 12 - - - 1 - 2 - 181 - - - 2 - 3 - 1 - - - - - - - ruby_undef - child - - - 12 - - - 1 - 2 - 181 - - - 2 - 3 - 1 - - - - - - - index - ruby_undef - - - 12 - - - 1 - 2 - 1 - - - 182 - 183 - 1 - - - - - - - index - child - - - 12 - - - 1 - 2 - 1 - - - 182 - 183 - 1 - - - - - - - child - ruby_undef - - - 12 - - - 1 - 2 - 183 - - - - - - - child - index - - - 12 - - - 1 - 2 - 183 - - - - - - - - - ruby_undef_def - 182 - - - id - 182 - - - - - - ruby_unless_alternative - 43 - - - ruby_unless - 43 - - - alternative - 43 - - - - - ruby_unless - alternative - - - 12 - - - 1 - 2 - 43 - - - - - - - alternative - ruby_unless - - - 12 - - - 1 - 2 - 43 - - - - - - - - - ruby_unless_consequence - 2721 - - - ruby_unless - 2721 - - - consequence - 2721 - - - - - ruby_unless - consequence - - - 12 - - - 1 - 2 - 2721 - - - - - - - consequence - ruby_unless - - - 12 - - - 1 - 2 - 2721 - - - - - - - - - ruby_unless_def - 2723 - - - id - 2723 - - - condition - 2723 - - - - - id - condition - - - 12 - - - 1 - 2 - 2723 - - - - - - - condition - id - - - 12 - - - 1 - 2 - 2723 - - - - - - - - - ruby_unless_guard_def - 4 - - - id - 4 - - - condition - 4 - - - - - id - condition - - - 12 - - - 1 - 2 - 4 - - - - - - - condition - id - - - 12 - - - 1 - 2 - 4 - - - - - - - - - ruby_unless_modifier_def - 3416 - - - id - 3416 - - - body - 3416 - - - condition - 3416 - - - - - id - body - - - 12 - - - 1 - 2 - 3416 - - - - - - - id - condition - - - 12 - - - 1 - 2 - 3416 - - - - - - - body - id - - - 12 - - - 1 - 2 - 3416 - - - - - - - body - condition - - - 12 - - - 1 - 2 - 3416 - - - - - - - condition - id - - - 12 - - - 1 - 2 - 3416 - - - - - - - condition - body - - - 12 - - - 1 - 2 - 3416 - - - - - - - - - ruby_until_def - 126 - - - id - 126 - - - body - 126 - - - condition - 126 - - - - - id - body - - - 12 - - - 1 - 2 - 126 - - - - - - - id - condition - - - 12 - - - 1 - 2 - 126 - - - - - - - body - id - - - 12 - - - 1 - 2 - 126 - - - - - - - body - condition - - - 12 - - - 1 - 2 - 126 - - - - - - - condition - id - - - 12 - - - 1 - 2 - 126 - - - - - - - condition - body - - - 12 - - - 1 - 2 - 126 - - - - - - - - - ruby_until_modifier_def - 238 - - - id - 238 - - - body - 238 - - - condition - 238 - - - - - id - body - - - 12 - - - 1 - 2 - 238 - - - - - - - id - condition - - - 12 - - - 1 - 2 - 238 - - - - - - - body - id - - - 12 - - - 1 - 2 - 238 - - - - - - - body - condition - - - 12 - - - 1 - 2 - 238 - - - - - - - condition - id - - - 12 - - - 1 - 2 - 238 - - - - - - - condition - body - - - 12 - - - 1 - 2 - 238 - - - - - - - - - ruby_variable_reference_pattern_def - 5 - - - id - 5 - - - name - 5 - - - - - id - name - - - 12 - - - 1 - 2 - 5 - - - - - - - name - id - - - 12 - - - 1 - 2 - 5 - - - - - - - - - ruby_when_body - 3790 - - - ruby_when - 3790 - - - body - 3790 - - - - - ruby_when - body - - - 12 - - - 1 - 2 - 3790 - - - - - - - body - ruby_when - - - 12 - - - 1 - 2 - 3790 - - - - - - - - - ruby_when_def - 3882 - - - id - 3882 - - - - - - ruby_when_pattern - 4745 - - - ruby_when - 3882 - - - index - 15 - - - pattern - 4745 - - - - - ruby_when - index - - - 12 - - - 1 - 2 - 3393 - - - 2 - 3 - 330 - - - 3 - 16 - 159 - - - - - - - ruby_when - pattern - - - 12 - - - 1 - 2 - 3393 - - - 2 - 3 - 330 - - - 3 - 16 - 159 - - - - - - - index - ruby_when - - - 12 - - - 1 - 2 - 2 - - - 3 - 4 - 2 - - - 4 - 5 - 2 - - - 5 - 6 - 1 - - - 10 - 11 - 1 - - - 19 - 20 - 1 - - - 31 - 32 - 1 - - - 44 - 45 - 1 - - - 90 - 91 - 1 - - - 159 - 160 - 1 - - - 489 - 490 - 1 - - - 3882 - 3883 - 1 - - - - - - - index - pattern - - - 12 - - - 1 - 2 - 2 - - - 3 - 4 - 2 - - - 4 - 5 - 2 - - - 5 - 6 - 1 - - - 10 - 11 - 1 - - - 19 - 20 - 1 - - - 31 - 32 - 1 - - - 44 - 45 - 1 - - - 90 - 91 - 1 - - - 159 - 160 - 1 - - - 489 - 490 - 1 - - - 3882 - 3883 - 1 - - - - - - - pattern - ruby_when - - - 12 - - - 1 - 2 - 4745 - - - - - - - pattern - index - - - 12 - - - 1 - 2 - 4745 - - - - - - - - - ruby_while_def - 1413 - - - id - 1413 - - - body - 1413 - - - condition - 1413 - - - - - id - body - - - 12 - - - 1 - 2 - 1413 - - - - - - - id - condition - - - 12 - - - 1 - 2 - 1413 - - - - - - - body - id - - - 12 - - - 1 - 2 - 1413 - - - - - - - body - condition - - - 12 - - - 1 - 2 - 1413 - - - - - - - condition - id - - - 12 - - - 1 - 2 - 1413 - - - - - - - condition - body - - - 12 - - - 1 - 2 - 1413 - - - - - - - - - ruby_while_modifier_def - 198 - - - id - 198 - - - body - 198 - - - condition - 198 - - - - - id - body - - - 12 - - - 1 - 2 - 198 - - - - - - - id - condition - - - 12 - - - 1 - 2 - 198 - - - - - - - body - id - - - 12 - - - 1 - 2 - 198 - - - - - - - body - condition - - - 12 - - - 1 - 2 - 198 - - - - - - - condition - id - - - 12 - - - 1 - 2 - 198 - - - - - - - condition - body - - - 12 - - - 1 - 2 - 198 - - - - - - - - - ruby_yield_child - 1103 - - - ruby_yield - 1103 - - - child - 1103 - - - - - ruby_yield - child - - - 12 - - - 1 - 2 - 1103 - - - - - - - child - ruby_yield - - - 12 - - - 1 - 2 - 1103 - - - - - - - - - ruby_yield_def - 2450 - - - id - 2450 - - - - - - sourceLocationPrefix - 13 - - - prefix - 13 - - - - - - yaml - 0 - - - id - 0 - - - kind - 0 - - - parent - 0 - - - idx - 0 - - - tag - 0 - - - tostring - 0 - - - - - id - kind - - - 12 - - - 1 - 2 - 2 - - - - - - - id - parent - - - 12 - - - 1 - 2 - 2 - - - - - - - id - idx - - - 12 - - - 1 - 2 - 2 - - - - - - - id - tag - - - 12 - - - 1 - 2 - 2 - - - - - - - id - tostring - - - 12 - - - 1 - 2 - 2 - - - - - - - kind - id - - - 12 - - - - - - kind - parent - - - 12 - - - - - - kind - idx - - - 12 - - - - - - kind - tag - - - 12 - - - - - - kind - tostring - - - 12 - - - - - - parent - id - - - 12 - - - - - - parent - kind - - - 12 - - - - - - parent - idx - - - 12 - - - - - - parent - tag - - - 12 - - - - - - parent - tostring - - - 12 - - - - - - idx - id - - - 12 - - - - - - idx - kind - - - 12 - - - - - - idx - parent - - - 12 - - - - - - idx - tag - - - 12 - - - - - - idx - tostring - - - 12 - - - - - - tag - id - - - 12 - - - - - - tag - kind - - - 12 - - - - - - tag - parent - - - 12 - - - - - - tag - idx - - - 12 - - - - - - tag - tostring - - - 12 - - - - - - tostring - id - - - 12 - - - - - - tostring - kind - - - 12 - - - - - - tostring - parent - - - 12 - - - - - - tostring - idx - - - 12 - - - - - - tostring - tag - - - 12 - - - - - - - - databaseMetadata - 1 - - - metadataKey - 1 - - - value - 1 - - - - - metadataKey - value - - - 12 - - - - - - value - metadataKey - - - 12 - - - - - - - - overlayChangedFiles - 50 - - - path - 50 - - - - - - yaml_aliases - 0 - - - alias - 0 - - - target - 0 - - - - - alias - target - - - 12 - - - 1 - 2 - 2 - - - - - - - target - alias - - - 12 - - - - - - - - yaml_anchors - 0 - - - node - 0 - - - anchor - 0 - - - - - node - anchor - - - 12 - - - 1 - 2 - 2 - - - - - - - anchor - node - - - 12 - - - - - - - - yaml_errors - 0 - - - id - 0 - - - message - 0 - - - - - id - message - - - 12 - - - 1 - 2 - 2 - - - - - - - message - id - - - 12 - - - - - - - - yaml_locations - 0 - - - locatable - 0 - - - location - 0 - - - - - locatable - location - - - 12 - - - 1 - 2 - 2 - - - - - - - location - locatable - - - 12 - - - - - - - - yaml_scalars - 0 - - - scalar - 0 - - - style - 0 - - - value - 0 - - - - - scalar - style - - - 12 - - - 1 - 2 - 2 - - - - - - - scalar - value - - - 12 - - - 1 - 2 - 2 - - - - - - - style - scalar - - - 12 - - - - - - style - value - - - 12 - - - - - - value - scalar - - - 12 - - - - - - value - style - - - 12 - - - - - - - + + From d191d09c5553e4b2851bc8b2612f0e98831f4cbf Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Thu, 19 Mar 2026 15:48:47 -0700 Subject: [PATCH 17/48] Apply suggestions from code review Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com> --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll index 51cc7430f62..25e675053e2 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll @@ -619,7 +619,7 @@ module Public { /** * Gets the uninitialized local variable corresponding to this node behind - * the given levels of indirection, if any. + * `index` number of indirections, if any. */ LocalVariable asIndirectUninitialized(int indirectionIndex) { exists(IndirectUninitializedNode indirectUninitializedNode | @@ -632,7 +632,7 @@ module Public { /** * Gets the uninitialized local variable corresponding to this node behind - * any levels of indirection, if any. + * a number indirections, if any. */ LocalVariable asIndirectUninitialized() { result = this.asIndirectUninitialized(_) } @@ -815,7 +815,7 @@ module Public { class IndirectUninitializedNode extends AbstractUninitializedNode { IndirectUninitializedNode() { indirectionIndex > 0 } - /** Gets the level of indirection to get to this node. */ + /** Gets the indirection index of this node. */ int getIndirectionIndex() { result = indirectionIndex } } From dc291ffad76b569c9c23d55630858f6afb8f0d0b Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Thu, 19 Mar 2026 15:51:00 -0700 Subject: [PATCH 18/48] Address code review --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll index 51cc7430f62..5c5b20f9e81 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll @@ -621,10 +621,10 @@ module Public { * Gets the uninitialized local variable corresponding to this node behind * the given levels of indirection, if any. */ - LocalVariable asIndirectUninitialized(int indirectionIndex) { + LocalVariable asIndirectUninitialized(int index) { exists(IndirectUninitializedNode indirectUninitializedNode | this = indirectUninitializedNode and - indirectUninitializedNode.getIndirectionIndex() = indirectionIndex + indirectUninitializedNode.getIndirectionIndex() = index | result = indirectUninitializedNode.getLocalVariable() ) @@ -808,9 +808,6 @@ module Public { /** * The value of an uninitialized local variable behind one or more levels of * indirection, viewed as a node in a data flow graph. - * - * NOTE: For the direct value of the uninitialized local variable, see - * `UninitializedNode`. */ class IndirectUninitializedNode extends AbstractUninitializedNode { IndirectUninitializedNode() { indirectionIndex > 0 } From bceab0b44e4a071575799b6e39a1adc611de4450 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Sat, 21 Feb 2026 22:25:02 +0000 Subject: [PATCH 19/48] Add extensible predicates --- .../rust/dataflow/internal/ModelsAsData.qll | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll index 8b55de8d54d..27143392e1f 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll @@ -98,6 +98,29 @@ extensible predicate neutralModel( string path, string kind, string provenance, QlBuiltins::ExtensionId madId ); +/** + * Holds if in a call to the function with canonical path `path`, the value referred + * to by `output` is a barrier of the given `kind` and `madId` is the data + * extension row number. + */ +extensible predicate barrierModel( + string path, string output, string kind, string provenance, QlBuiltins::ExtensionId madId +); + +/** + * Holds if in a call to the function with canonical path `path`, the value referred + * to by `input` is a barrier guard of the given `kind` and `madId` is the data + * extension row number. + * the value referred to by `input` is assumed to lead to a parameter of a call + * (possibly `self`), and the call is guarding the parameter. + * `branch` is either `true` or `false`, indicating which branch of the guard + * is protecting the parameter. + */ +extensible predicate barrierGuardModel( + string path, string input, string branch, string kind, string provenance, + QlBuiltins::ExtensionId madId +); + /** * Holds if the given extension tuple `madId` should pretty-print as `model`. * From f342bae962af40397a25ecbb0258290bdf9b7d84 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Sat, 21 Feb 2026 22:25:12 +0000 Subject: [PATCH 20/48] Update empty.model.yml --- .../lib/codeql/rust/dataflow/internal/empty.model.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/empty.model.yml b/rust/ql/lib/codeql/rust/dataflow/internal/empty.model.yml index 1a33951dfc3..61c0327171a 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/empty.model.yml +++ b/rust/ql/lib/codeql/rust/dataflow/internal/empty.model.yml @@ -15,3 +15,13 @@ extensions: pack: codeql/rust-all extensible: summaryModel data: [] + + - addsTo: + pack: codeql/rust-all + extensible: barrierModel + data: [] + + - addsTo: + pack: codeql/rust-all + extensible: barrierGuardModel + data: [] From f9521e9e883f36f997998fe05603439cf9c5198a Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 24 Feb 2026 19:36:17 +0000 Subject: [PATCH 21/48] Update `interpretModelForTest` --- .../lib/codeql/rust/dataflow/internal/ModelsAsData.qll | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll index 27143392e1f..ada06fafb4b 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll @@ -146,6 +146,16 @@ predicate interpretModelForTest(QlBuiltins::ExtensionId madId, string model) { neutralModel(path, kind, _, madId) and model = "Neutral: " + path + "; " + kind ) + or + exists(string path, string output, string kind | + barrierModel(path, output, kind, _, madId) and + model = "Barrier: " + path + "; " + output + "; " + kind + ) + or + exists(string path, string input, string branch, string kind | + barrierGuardModel(path, input, branch, kind, _, madId) and + model = "Barrier guard: " + path + "; " + input + "; " + branch + "; " + kind + ) } private class SummarizedCallableFromModel extends SummarizedCallable::Range { From f4550544ceea56275a4758ac7368853c4371de83 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 16 Mar 2026 22:11:58 +0000 Subject: [PATCH 22/48] Shared: Add `barrierElement` in FlowSummaryImpl.qll --- .../dataflow/internal/FlowSummaryImpl.qll | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll b/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll index d7667257192..fa20405f788 100644 --- a/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll @@ -368,6 +368,19 @@ module Make< abstract predicate isSink(string input, string kind, Provenance provenance, string model); } + /** A barrier element. */ + abstract class BarrierElement extends SourceBaseFinal { + bindingset[this] + BarrierElement() { any() } + + /** + * Holds if this element is a flow barrier of kind `kind`, where data + * flows out as described by `output`. + */ + pragma[nomagic] + abstract predicate isBarrier(string output, string kind, Provenance provenance, string model); + } + private signature predicate hasKindSig(string kind); signature class NeutralCallableSig extends SummarizedCallableBaseFinal { @@ -723,7 +736,19 @@ module Make< ) } - private predicate summarySpec(string spec) { + private predicate isRelevantBarrier( + BarrierElement e, string output, string kind, Provenance provenance, string model + ) { + e.isBarrier(output, kind, provenance, model) and + ( + provenance.isManual() + or + provenance.isGenerated() and + not exists(Provenance p | p.isManual() and e.isBarrier(_, kind, p, _)) + ) + } + + private predicate flowSpec(string spec) { exists(SummarizedCallable c | c.propagatesFlow(spec, _, _, _, _, _) or @@ -732,10 +757,12 @@ module Make< or isRelevantSource(_, spec, _, _, _) or + isRelevantBarrier(_, spec, _, _, _) + or isRelevantSink(_, spec, _, _, _) } - import AccessPathSyntax::AccessPath + import AccessPathSyntax::AccessPath /** Holds if specification component `token` parses as parameter `pos`. */ predicate parseParam(AccessPathToken token, ArgumentPosition pos) { @@ -1515,6 +1542,18 @@ module Make< ) } + /** + * Holds if `barrier` is a relevant barrier element with output specification `outSpec`. + */ + predicate barrierSpec( + BarrierElement barrier, SummaryComponentStack outSpec, string kind, string model + ) { + exists(string output | + isRelevantBarrier(barrier, output, kind, _, model) and + External::interpretSpec(output, outSpec) + ) + } + signature module TypesInputSig { /** Gets the type of content `c`. */ DataFlowType getContentType(ContentSet c); From d3177b9e82b28a703dfed8673a954285fff189c7 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 16 Mar 2026 22:14:07 +0000 Subject: [PATCH 23/48] Add FlowBarrier.qll --- .../lib/codeql/rust/dataflow/FlowBarrier.qll | 54 +++++++++++++++++++ .../rust/dataflow/internal/DataFlowImpl.qll | 19 +++++++ .../dataflow/internal/FlowSummaryImpl.qll | 19 +++++-- 3 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll diff --git a/rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll b/rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll new file mode 100644 index 00000000000..1d5e3957112 --- /dev/null +++ b/rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll @@ -0,0 +1,54 @@ +/** + * Provides classes and predicates for defining barriers. + * + * Flow barriers defined here feed into data flow configurations as follows: + * + * ```text + * data from *.model.yml | QL extensions of FlowBarrier::Range + * v v + * FlowBarrier (associated with a models-as-data kind string) + * v + * barrierNode predicate | other QL defined barriers, for example using concepts + * v v + * various Barrier classes for specific data flow configurations <- extending QueryBarrier + * ``` + * + * New barriers should be defined using models-as-data, QL extensions of + * `FlowBarrier::Range`, or concepts. Data flow configurations should use the + * `barrierNode` predicate and/or concepts to define their barriers. + */ + +private import rust +private import internal.FlowSummaryImpl as Impl +private import internal.DataFlowImpl as DataFlowImpl + +// import all instances below +private module Barriers { + private import codeql.rust.Frameworks + private import codeql.rust.dataflow.internal.ModelsAsData +} + +/** Provides the `Range` class used to define the extent of `FlowBarrier`. */ +module FlowBarrier { + /** A flow barrier. */ + abstract class Range extends Impl::Public::BarrierElement { + bindingset[this] + Range() { any() } + + override predicate isBarrier( + string output, string kind, Impl::Public::Provenance provenance, string model + ) { + this.isBarrier(output, kind) and provenance = "manual" and model = "" + } + + /** + * Holds if this element is a flow barrier of kind `kind`, where data + * flows out as described by `output`. + */ + predicate isBarrier(string output, string kind) { none() } + } +} + +final class FlowBarrier = FlowBarrier::Range; + +predicate barrierNode = DataFlowImpl::barrierNode/2; diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll index 23424dbffd9..f416c2a20e5 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll @@ -1157,6 +1157,25 @@ private module Cached { cached predicate sinkNode(Node n, string kind) { n.(FlowSummaryNode).isSink(kind, _) } + /** Holds if `n` is a flow barrier of kind `kind`. */ + cached + predicate barrierNode(Node n, string kind) { + exists( + FlowSummaryImpl::Public::BarrierElement b, + FlowSummaryImpl::Private::SummaryComponentStack stack + | + FlowSummaryImpl::Private::barrierSpec(b, stack, kind, _) + | + n = FlowSummaryImpl::StepsInput::getSourceNode(b, stack, false) + or + // For barriers like `Argument[0]` we want to target the pre-update node + n = + FlowSummaryImpl::StepsInput::getSourceNode(b, stack, true) + .(PostUpdateNode) + .getPreUpdateNode() + ) + } + /** * A step in a flow summary defined using `OptionalStep[name]`. An `OptionalStep` is "opt-in", which means * that by default the step is not present in the flow summary and needs to be explicitly enabled by defining diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/FlowSummaryImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/FlowSummaryImpl.qll index ab0b3aff9ca..85032814651 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/FlowSummaryImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/FlowSummaryImpl.qll @@ -143,7 +143,7 @@ module Input implements InputSig { private import Make as Impl -private module StepsInput implements Impl::Private::StepsInputSig { +module StepsInput implements Impl::Private::StepsInputSig { DataFlowCall getACall(Public::SummarizedCallable sc) { result.asCall().getStaticTarget() = sc } /** Gets the argument of `source` described by `sc`, if any. */ @@ -171,18 +171,27 @@ private module StepsInput implements Impl::Private::StepsInputSig { result.asCfgScope() = source.getEnclosingCfgScope() } - RustDataFlow::Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponentStack s) { + additional RustDataFlow::Node getSourceNode( + Input::SourceBase source, Impl::Private::SummaryComponentStack s, boolean isArgPostUpdate + ) { s.head() = Impl::Private::SummaryComponent::return(_) and - result.asExpr() = source.getCall() + result.asExpr() = source.getCall() and + isArgPostUpdate = false or exists(RustDataFlow::ArgumentPosition pos, Expr arg | s.head() = Impl::Private::SummaryComponent::parameter(pos) and arg = getSourceNodeArgument(source, s.tail().headOfSingleton()) and - result.asParameter() = getCallable(arg).getParam(pos.getPosition()) + result.asParameter() = getCallable(arg).getParam(pos.getPosition()) and + isArgPostUpdate = false ) or result.(RustDataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = - getSourceNodeArgument(source, s.headOfSingleton()) + getSourceNodeArgument(source, s.headOfSingleton()) and + isArgPostUpdate = true + } + + RustDataFlow::Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponentStack s) { + result = getSourceNode(source, s, _) } RustDataFlow::Node getSinkNode(Input::SinkBase sink, Impl::Private::SummaryComponent sc) { From e86ce8feeda3620f73de84c44d4345222368c6bb Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 16 Mar 2026 22:14:38 +0000 Subject: [PATCH 24/48] Instantiate flow barriers from MaD --- .../rust/dataflow/internal/ModelsAsData.qll | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll index ada06fafb4b..943a32e4448 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll @@ -44,6 +44,7 @@ */ private import rust +private import codeql.rust.dataflow.FlowBarrier private import codeql.rust.dataflow.FlowSummary private import codeql.rust.dataflow.FlowSource private import codeql.rust.dataflow.FlowSink @@ -239,6 +240,22 @@ private class FlowSinkFromModel extends FlowSink::Range { } } +private class FlowBarrierFromModel extends FlowBarrier::Range { + private string path; + + FlowBarrierFromModel() { + barrierModel(path, _, _, _, _) and + this.callResolvesTo(path) + } + + override predicate isBarrier(string output, string kind, Provenance provenance, string model) { + exists(QlBuiltins::ExtensionId madId | + barrierModel(path, output, kind, provenance, madId) and + model = "MaD:" + madId.toString() + ) + } +} + private module Debug { private import FlowSummaryImpl private import Private From 93c656065d20428fffe43d7c79850f5dca41fa4e Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 16 Mar 2026 22:16:01 +0000 Subject: [PATCH 25/48] Add test for MaD barriers --- .../dataflow/barrier/inline-flow.expected | 21 ------------------- .../dataflow/barrier/inline-flow.ext.yml | 6 ++++++ .../dataflow/barrier/inline-flow.ql | 13 +++++++++++- .../library-tests/dataflow/barrier/main.rs | 2 +- 4 files changed, 19 insertions(+), 23 deletions(-) create mode 100644 rust/ql/test/library-tests/dataflow/barrier/inline-flow.ext.yml diff --git a/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected b/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected index 68da00c4312..0514da67333 100644 --- a/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected @@ -1,41 +1,20 @@ models edges -| main.rs:9:13:9:19 | ...: ... | main.rs:10:11:10:11 | s | provenance | | -| main.rs:10:11:10:11 | s | main.rs:12:9:12:9 | s | provenance | | -| main.rs:12:9:12:9 | s | main.rs:9:30:14:1 | { ... } | provenance | | | main.rs:21:9:21:9 | s | main.rs:22:10:22:10 | s | provenance | | | main.rs:21:13:21:21 | source(...) | main.rs:21:9:21:9 | s | provenance | | -| main.rs:26:9:26:9 | s | main.rs:27:22:27:22 | s | provenance | | -| main.rs:26:13:26:21 | source(...) | main.rs:26:9:26:9 | s | provenance | | -| main.rs:27:9:27:9 | s | main.rs:28:10:28:10 | s | provenance | | -| main.rs:27:13:27:23 | sanitize(...) | main.rs:27:9:27:9 | s | provenance | | -| main.rs:27:22:27:22 | s | main.rs:9:13:9:19 | ...: ... | provenance | | -| main.rs:27:22:27:22 | s | main.rs:27:13:27:23 | sanitize(...) | provenance | | | main.rs:32:9:32:9 | s | main.rs:33:10:33:10 | s | provenance | | | main.rs:32:13:32:21 | source(...) | main.rs:32:9:32:9 | s | provenance | | nodes -| main.rs:9:13:9:19 | ...: ... | semmle.label | ...: ... | -| main.rs:9:30:14:1 | { ... } | semmle.label | { ... } | -| main.rs:10:11:10:11 | s | semmle.label | s | -| main.rs:12:9:12:9 | s | semmle.label | s | | main.rs:17:10:17:18 | source(...) | semmle.label | source(...) | | main.rs:21:9:21:9 | s | semmle.label | s | | main.rs:21:13:21:21 | source(...) | semmle.label | source(...) | | main.rs:22:10:22:10 | s | semmle.label | s | -| main.rs:26:9:26:9 | s | semmle.label | s | -| main.rs:26:13:26:21 | source(...) | semmle.label | source(...) | -| main.rs:27:9:27:9 | s | semmle.label | s | -| main.rs:27:13:27:23 | sanitize(...) | semmle.label | sanitize(...) | -| main.rs:27:22:27:22 | s | semmle.label | s | -| main.rs:28:10:28:10 | s | semmle.label | s | | main.rs:32:9:32:9 | s | semmle.label | s | | main.rs:32:13:32:21 | source(...) | semmle.label | source(...) | | main.rs:33:10:33:10 | s | semmle.label | s | subpaths -| main.rs:27:22:27:22 | s | main.rs:9:13:9:19 | ...: ... | main.rs:9:30:14:1 | { ... } | main.rs:27:13:27:23 | sanitize(...) | testFailures #select | main.rs:17:10:17:18 | source(...) | main.rs:17:10:17:18 | source(...) | main.rs:17:10:17:18 | source(...) | $@ | main.rs:17:10:17:18 | source(...) | source(...) | | main.rs:22:10:22:10 | s | main.rs:21:13:21:21 | source(...) | main.rs:22:10:22:10 | s | $@ | main.rs:21:13:21:21 | source(...) | source(...) | -| main.rs:28:10:28:10 | s | main.rs:26:13:26:21 | source(...) | main.rs:28:10:28:10 | s | $@ | main.rs:26:13:26:21 | source(...) | source(...) | | main.rs:33:10:33:10 | s | main.rs:32:13:32:21 | source(...) | main.rs:33:10:33:10 | s | $@ | main.rs:32:13:32:21 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/barrier/inline-flow.ext.yml b/rust/ql/test/library-tests/dataflow/barrier/inline-flow.ext.yml new file mode 100644 index 00000000000..98c62dd0758 --- /dev/null +++ b/rust/ql/test/library-tests/dataflow/barrier/inline-flow.ext.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/rust-all + extensible: barrierModel + data: + - ["main::sanitize", "ReturnValue", "test-barrier", "manual"] diff --git a/rust/ql/test/library-tests/dataflow/barrier/inline-flow.ql b/rust/ql/test/library-tests/dataflow/barrier/inline-flow.ql index 5dcb7ee70a9..7cc30bf6350 100644 --- a/rust/ql/test/library-tests/dataflow/barrier/inline-flow.ql +++ b/rust/ql/test/library-tests/dataflow/barrier/inline-flow.ql @@ -3,8 +3,19 @@ */ import rust +import codeql.rust.dataflow.DataFlow +import codeql.rust.dataflow.FlowBarrier import utils.test.InlineFlowTest -import DefaultFlowTest + +module CustomConfig implements DataFlow::ConfigSig { + predicate isSource = DefaultFlowConfig::isSource/1; + + predicate isSink = DefaultFlowConfig::isSink/1; + + predicate isBarrier(DataFlow::Node n) { barrierNode(n, "test-barrier") } +} + +import FlowTest import TaintFlow::PathGraph from TaintFlow::PathNode source, TaintFlow::PathNode sink diff --git a/rust/ql/test/library-tests/dataflow/barrier/main.rs b/rust/ql/test/library-tests/dataflow/barrier/main.rs index 14935f0f328..0791c56f240 100644 --- a/rust/ql/test/library-tests/dataflow/barrier/main.rs +++ b/rust/ql/test/library-tests/dataflow/barrier/main.rs @@ -25,7 +25,7 @@ fn through_variable() { fn with_barrier() { let s = source(1); let s = sanitize(s); - sink(s); // $ SPURIOUS: hasValueFlow=1 + sink(s); } fn main() { From 2f0d3288ce534ab74b3fb8deb3955cd101e9c4db Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 16 Mar 2026 22:18:56 +0000 Subject: [PATCH 26/48] Misc: fix typos in QLDocs --- rust/ql/lib/codeql/rust/dataflow/internal/Node.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/Node.qll b/rust/ql/lib/codeql/rust/dataflow/internal/Node.qll index 1fa3983f811..1ccb7db73f5 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/Node.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/Node.qll @@ -82,12 +82,12 @@ class FlowSummaryNode extends Node, TFlowSummaryNode { result = this.getSummaryNode().getSinkElement() } - /** Holds is this node is a source node of kind `kind`. */ + /** Holds if this node is a source node of kind `kind`. */ predicate isSource(string kind, string model) { this.getSummaryNode().(FlowSummaryImpl::Private::SourceOutputNode).isEntry(kind, model) } - /** Holds is this node is a sink node of kind `kind`. */ + /** Holds if this node is a sink node of kind `kind`. */ predicate isSink(string kind, string model) { this.getSummaryNode().(FlowSummaryImpl::Private::SinkInputNode).isExit(kind, model) } From c5457d3e309dd5abd8778ad213170e4e16e757df Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 17 Mar 2026 10:46:08 +0000 Subject: [PATCH 27/48] Add (failing) test for MaD barrier guard --- .../dataflow/barrier/inline-flow.expected | 6 ++++++ .../ql/test/library-tests/dataflow/barrier/main.rs | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected b/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected index 0514da67333..b1e32f95fb9 100644 --- a/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected @@ -4,6 +4,8 @@ edges | main.rs:21:13:21:21 | source(...) | main.rs:21:9:21:9 | s | provenance | | | main.rs:32:9:32:9 | s | main.rs:33:10:33:10 | s | provenance | | | main.rs:32:13:32:21 | source(...) | main.rs:32:9:32:9 | s | provenance | | +| main.rs:44:9:44:9 | s | main.rs:46:14:46:14 | s | provenance | | +| main.rs:44:13:44:21 | source(...) | main.rs:44:9:44:9 | s | provenance | | nodes | main.rs:17:10:17:18 | source(...) | semmle.label | source(...) | | main.rs:21:9:21:9 | s | semmle.label | s | @@ -12,9 +14,13 @@ nodes | main.rs:32:9:32:9 | s | semmle.label | s | | main.rs:32:13:32:21 | source(...) | semmle.label | source(...) | | main.rs:33:10:33:10 | s | semmle.label | s | +| main.rs:44:9:44:9 | s | semmle.label | s | +| main.rs:44:13:44:21 | source(...) | semmle.label | source(...) | +| main.rs:46:14:46:14 | s | semmle.label | s | subpaths testFailures #select | main.rs:17:10:17:18 | source(...) | main.rs:17:10:17:18 | source(...) | main.rs:17:10:17:18 | source(...) | $@ | main.rs:17:10:17:18 | source(...) | source(...) | | main.rs:22:10:22:10 | s | main.rs:21:13:21:21 | source(...) | main.rs:22:10:22:10 | s | $@ | main.rs:21:13:21:21 | source(...) | source(...) | | main.rs:33:10:33:10 | s | main.rs:32:13:32:21 | source(...) | main.rs:33:10:33:10 | s | $@ | main.rs:32:13:32:21 | source(...) | source(...) | +| main.rs:46:14:46:14 | s | main.rs:44:13:44:21 | source(...) | main.rs:46:14:46:14 | s | $@ | main.rs:44:13:44:21 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/barrier/main.rs b/rust/ql/test/library-tests/dataflow/barrier/main.rs index 0791c56f240..6cf317d105a 100644 --- a/rust/ql/test/library-tests/dataflow/barrier/main.rs +++ b/rust/ql/test/library-tests/dataflow/barrier/main.rs @@ -32,3 +32,17 @@ fn main() { let s = source(1); sink(s); // $ hasValueFlow=1 } + +fn verify_safe(s: &str) -> bool { + match s { + "dangerous" => false, + _ => true, + } +} + +fn with_barrier_guard() { + let s = source(1); + if verify_safe(s) { + sink(s); // $ SPURIOUS: hasValueFlow=1 + } +} From 77cb35380c6d28af2a1027e4446f565007d269d4 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 17 Mar 2026 11:10:25 +0000 Subject: [PATCH 28/48] Add MaD barrier guard model to make test pass --- .../test/library-tests/dataflow/barrier/inline-flow.ext.yml | 5 +++++ rust/ql/test/library-tests/dataflow/barrier/main.rs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/rust/ql/test/library-tests/dataflow/barrier/inline-flow.ext.yml b/rust/ql/test/library-tests/dataflow/barrier/inline-flow.ext.yml index 98c62dd0758..58e55a040d2 100644 --- a/rust/ql/test/library-tests/dataflow/barrier/inline-flow.ext.yml +++ b/rust/ql/test/library-tests/dataflow/barrier/inline-flow.ext.yml @@ -4,3 +4,8 @@ extensions: extensible: barrierModel data: - ["main::sanitize", "ReturnValue", "test-barrier", "manual"] + - addsTo: + pack: codeql/rust-all + extensible: barrierGuardModel + data: + - ["main::verify_safe", "Argument[0]", "true", "test-barrier", "manual"] diff --git a/rust/ql/test/library-tests/dataflow/barrier/main.rs b/rust/ql/test/library-tests/dataflow/barrier/main.rs index 6cf317d105a..268a8673bc9 100644 --- a/rust/ql/test/library-tests/dataflow/barrier/main.rs +++ b/rust/ql/test/library-tests/dataflow/barrier/main.rs @@ -43,6 +43,6 @@ fn verify_safe(s: &str) -> bool { fn with_barrier_guard() { let s = source(1); if verify_safe(s) { - sink(s); // $ SPURIOUS: hasValueFlow=1 + sink(s); } } From 7d65baccb2bd33a30be364a463fec5996cc46d0e Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 20 Mar 2026 11:08:33 +0000 Subject: [PATCH 29/48] Add `FlowBarrierGuard` to FlowBarrier.qll --- .../lib/codeql/rust/dataflow/FlowBarrier.qll | 23 ++++++ .../rust/dataflow/internal/DataFlowImpl.qll | 76 ++++++++++++++++++- .../codeql/rust/dataflow/internal/SsaImpl.qll | 25 ++++++ .../dataflow/internal/FlowSummaryImpl.qll | 43 +++++++++++ 4 files changed, 164 insertions(+), 3 deletions(-) diff --git a/rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll b/rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll index 1d5e3957112..7ca64bedb5f 100644 --- a/rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll +++ b/rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll @@ -51,4 +51,27 @@ module FlowBarrier { final class FlowBarrier = FlowBarrier::Range; +/** Provides the `Range` class used to define the extent of `FlowBarrierGuard`. */ +module FlowBarrierGuard { + /** A flow barrier guard. */ + abstract class Range extends Impl::Public::BarrierGuardElement { + bindingset[this] + Range() { any() } + + override predicate isBarrierGuard( + string input, string branch, string kind, Impl::Public::Provenance provenance, string model + ) { + this.isBarrierGuard(input, branch, kind) and provenance = "manual" and model = "" + } + + /** + * Holds if this element is a flow barrier guard of kind `kind`, for data + * flowing in as described by `input`, when `this` evaluates to `branch`. + */ + predicate isBarrierGuard(string input, string branch, string kind) { none() } + } +} + +final class FlowBarrierGuard = FlowBarrierGuard::Range; + predicate barrierNode = DataFlowImpl::barrierNode/2; diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll index f416c2a20e5..27773758fc4 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll @@ -1157,14 +1157,50 @@ private module Cached { cached predicate sinkNode(Node n, string kind) { n.(FlowSummaryNode).isSink(kind, _) } - /** Holds if `n` is a flow barrier of kind `kind`. */ + private newtype TKindModelPair = + TMkPair(string kind, string model) { + FlowSummaryImpl::Private::barrierGuardSpec(_, _, _, kind, model) + } + + private boolean convertAcceptingValue(FlowSummaryImpl::Public::AcceptingValue av) { + av.isTrue() and result = true + or + av.isFalse() and result = false + // Remaining cases are not supported yet, they depend on the shared Guards library. + // or + // av.isNoException() and result.getDualValue().isThrowsException() + // or + // av.isZero() and result.asIntValue() = 0 + // or + // av.isNotZero() and result.getDualValue().asIntValue() = 0 + // or + // av.isNull() and result.isNullValue() + // or + // av.isNotNull() and result.isNonNullValue() + } + + private predicate barrierGuardChecks(AstNode g, Expr e, boolean gv, TKindModelPair kmp) { + exists( + FlowSummaryImpl::Public::BarrierGuardElement b, + FlowSummaryImpl::Private::SummaryComponentStack stack, + FlowSummaryImpl::Public::AcceptingValue acceptingvalue, string kind, string model + | + FlowSummaryImpl::Private::barrierGuardSpec(b, stack, acceptingvalue, kind, model) and + e = FlowSummaryImpl::StepsInput::getSinkNode(b, stack.headOfSingleton()).asExpr() and + kmp = TMkPair(kind, model) and + gv = convertAcceptingValue(acceptingvalue) and + g = b.getCall() + ) + } + + /** Holds if `n` is a flow barrier of kind `kind` and model `model`. */ cached - predicate barrierNode(Node n, string kind) { + predicate barrierNode(Node n, string kind, string model) { exists( FlowSummaryImpl::Public::BarrierElement b, FlowSummaryImpl::Private::SummaryComponentStack stack | - FlowSummaryImpl::Private::barrierSpec(b, stack, kind, _) + FlowSummaryImpl::Private::barrierSpec(b, stack, kind, model) | n = FlowSummaryImpl::StepsInput::getSourceNode(b, stack, false) or @@ -1174,6 +1210,9 @@ private module Cached { .(PostUpdateNode) .getPreUpdateNode() ) + or + ParameterizedBarrierGuard::getABarrierNode(TMkPair(kind, + model)) = n } /** @@ -1199,3 +1238,34 @@ private module Cached { } import Cached + +/** Holds if `n` is a flow barrier of kind `kind`. */ +predicate barrierNode(Node n, string kind) { barrierNode(n, kind, _) } + +bindingset[this] +private signature class ParamSig; + +private module WithParam { + /** + * Holds if the guard `g` validates the expression `e` upon evaluating to `gv`. + * + * The expression `e` is expected to be a syntactic part of the guard `g`. + * For example, the guard `g` might be a call `isSafe(x)` and the expression `e` + * the argument `x`. + */ + signature predicate guardChecksSig(AstNode g, Expr e, boolean branch, P param); +} + +/** + * Provides a set of barrier nodes for a guard that validates an expression. + * + * This is expected to be used in `isBarrier`/`isSanitizer` definitions + * in data flow and taint tracking. + */ +module ParameterizedBarrierGuard::guardChecksSig/4 guardChecks> { + /** Gets a node that is safely guarded by the given guard check. */ + Node getABarrierNode(P param) { + SsaFlow::asNode(result) = + SsaImpl::DataFlowIntegration::ParameterizedBarrierGuard::getABarrierNode(param) + } +} diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/SsaImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/SsaImpl.qll index 03db7c35b4d..874126f6a08 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/SsaImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/SsaImpl.qll @@ -305,6 +305,31 @@ private module Cached { predicate getABarrierNode = getABarrierNodeImpl/0; } + + bindingset[this] + private signature class ParamSig; + + private module WithParam { + signature predicate guardChecksSig(AstNode g, Expr e, boolean branch, P param); + } + + overlay[global] + cached // nothing is actually cached + module ParameterizedBarrierGuard::guardChecksSig/4 guardChecks> { + private predicate guardChecksAdjTypes( + DataFlowIntegrationInput::Guard g, DataFlowIntegrationInput::Expr e, + DataFlowIntegrationInput::GuardValue branch, P param + ) { + guardChecks(g, e, branch, param) + } + + private Node getABarrierNodeImpl(P param) { + result = + DataFlowIntegrationImpl::BarrierGuardWithState::getABarrierNode(param) + } + + predicate getABarrierNode = getABarrierNodeImpl/1; + } } } diff --git a/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll b/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll index fa20405f788..8b25c54bfa0 100644 --- a/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll @@ -381,6 +381,21 @@ module Make< abstract predicate isBarrier(string output, string kind, Provenance provenance, string model); } + /** A barrier guard element. */ + abstract class BarrierGuardElement extends SinkBaseFinal { + bindingset[this] + BarrierGuardElement() { any() } + + /** + * Holds if this element is a flow barrier guard of kind `kind`, for data + * flowing in as described by `input`, when `this` evaluates to `branch`. + */ + pragma[nomagic] + abstract predicate isBarrierGuard( + string input, string branch, string kind, Provenance provenance, string model + ); + } + private signature predicate hasKindSig(string kind); signature class NeutralCallableSig extends SummarizedCallableBaseFinal { @@ -748,6 +763,19 @@ module Make< ) } + private predicate isRelevantBarrierGuard( + BarrierGuardElement e, string input, string branch, string kind, Provenance provenance, + string model + ) { + e.isBarrierGuard(input, branch, kind, provenance, model) and + ( + provenance.isManual() + or + provenance.isGenerated() and + not exists(Provenance p | p.isManual() and e.isBarrierGuard(_, _, kind, p, _)) + ) + } + private predicate flowSpec(string spec) { exists(SummarizedCallable c | c.propagatesFlow(spec, _, _, _, _, _) @@ -759,6 +787,8 @@ module Make< or isRelevantBarrier(_, spec, _, _, _) or + isRelevantBarrierGuard(_, spec, _, _, _, _) + or isRelevantSink(_, spec, _, _, _) } @@ -1554,6 +1584,19 @@ module Make< ) } + /** + * Holds if `barrierGuard` is a relevant barrier guard element with input specification `inSpec`. + */ + predicate barrierGuardSpec( + BarrierGuardElement barrierGuard, SummaryComponentStack inSpec, string branch, string kind, + string model + ) { + exists(string input | + isRelevantBarrierGuard(barrierGuard, input, branch, kind, _, model) and + External::interpretSpec(input, inSpec) + ) + } + signature module TypesInputSig { /** Gets the type of content `c`. */ DataFlowType getContentType(ContentSet c); From 769b3a6aae2d28093948d70f8b9f1da4cb73fe92 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 17 Mar 2026 13:16:25 +0000 Subject: [PATCH 30/48] Instantiate flow barrier guards from MaD --- .../rust/dataflow/internal/ModelsAsData.qll | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll index 943a32e4448..a3f3da9364d 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll @@ -256,6 +256,24 @@ private class FlowBarrierFromModel extends FlowBarrier::Range { } } +private class FlowBarrierGuardFromModel extends FlowBarrierGuard::Range { + private string path; + + FlowBarrierGuardFromModel() { + barrierGuardModel(path, _, _, _, _, _) and + this.callResolvesTo(path) + } + + override predicate isBarrierGuard( + string input, string branch, string kind, Provenance provenance, string model + ) { + exists(QlBuiltins::ExtensionId madId | + barrierGuardModel(path, input, branch, kind, provenance, madId) and + model = "MaD:" + madId.toString() + ) + } +} + private module Debug { private import FlowSummaryImpl private import Private From bde9378ceeba8321291580b2ea7dc362fa8c7023 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 20 Mar 2026 11:10:08 +0000 Subject: [PATCH 31/48] Update MaD barrier guard test output --- .../library-tests/dataflow/barrier/inline-flow.expected | 6 ------ 1 file changed, 6 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected b/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected index b1e32f95fb9..0514da67333 100644 --- a/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected @@ -4,8 +4,6 @@ edges | main.rs:21:13:21:21 | source(...) | main.rs:21:9:21:9 | s | provenance | | | main.rs:32:9:32:9 | s | main.rs:33:10:33:10 | s | provenance | | | main.rs:32:13:32:21 | source(...) | main.rs:32:9:32:9 | s | provenance | | -| main.rs:44:9:44:9 | s | main.rs:46:14:46:14 | s | provenance | | -| main.rs:44:13:44:21 | source(...) | main.rs:44:9:44:9 | s | provenance | | nodes | main.rs:17:10:17:18 | source(...) | semmle.label | source(...) | | main.rs:21:9:21:9 | s | semmle.label | s | @@ -14,13 +12,9 @@ nodes | main.rs:32:9:32:9 | s | semmle.label | s | | main.rs:32:13:32:21 | source(...) | semmle.label | source(...) | | main.rs:33:10:33:10 | s | semmle.label | s | -| main.rs:44:9:44:9 | s | semmle.label | s | -| main.rs:44:13:44:21 | source(...) | semmle.label | source(...) | -| main.rs:46:14:46:14 | s | semmle.label | s | subpaths testFailures #select | main.rs:17:10:17:18 | source(...) | main.rs:17:10:17:18 | source(...) | main.rs:17:10:17:18 | source(...) | $@ | main.rs:17:10:17:18 | source(...) | source(...) | | main.rs:22:10:22:10 | s | main.rs:21:13:21:21 | source(...) | main.rs:22:10:22:10 | s | $@ | main.rs:21:13:21:21 | source(...) | source(...) | | main.rs:33:10:33:10 | s | main.rs:32:13:32:21 | source(...) | main.rs:33:10:33:10 | s | $@ | main.rs:32:13:32:21 | source(...) | source(...) | -| main.rs:46:14:46:14 | s | main.rs:44:13:44:21 | source(...) | main.rs:46:14:46:14 | s | $@ | main.rs:44:13:44:21 | source(...) | source(...) | From 4b364639a2bf4ae8a63b596917a29183e36ddfbd Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 19 Mar 2026 13:16:27 +0100 Subject: [PATCH 32/48] Ruby: Fix join orders following DB stats removal --- .../lib/codeql/ruby/ast/internal/Literal.qll | 66 ++++++++++--------- .../lib/codeql/ruby/ast/internal/Module.qll | 6 +- .../ql/lib/codeql/ruby/ast/internal/Scope.qll | 16 +++-- .../dataflow/internal/DataFlowDispatch.qll | 38 ++++++----- .../dataflow/internal/DataFlowPrivate.qll | 61 ++++++++++------- .../codeql/ruby/frameworks/ActiveRecord.qll | 38 ++++++----- .../frameworks/actioncontroller/Filters.qll | 7 +- .../actiondispatch/internal/Routing.qll | 1 + .../lib/codeql/ruby/frameworks/core/Array.qll | 4 +- .../lib/codeql/ruby/frameworks/core/Hash.qll | 4 +- 10 files changed, 139 insertions(+), 102 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Literal.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Literal.qll index 6a2df06b349..c6f906a8752 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Literal.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Literal.qll @@ -9,8 +9,12 @@ private import codeql.ruby.ast.internal.Scope private import codeql.ruby.controlflow.CfgNodes private import codeql.util.Numbers +bindingset[t] +pragma[inline_late] +private string getTokenValue(Ruby::Token t) { result = t.getValue() } + int parseInteger(Ruby::Integer i) { - exists(string s | s = i.getValue().toLowerCase().replaceAll("_", "") | + exists(string s | s = getTokenValue(i).toLowerCase().replaceAll("_", "") | s.charAt(0) != "0" and result = s.toInt() or @@ -38,7 +42,7 @@ class IntegerLiteralReal extends IntegerLiteralImpl, TIntegerLiteralReal { final override int getValue() { result = parseInteger(g) } - final override string toString() { result = g.getValue() } + final override string toString() { result = getTokenValue(g) } } class IntegerLiteralSynth extends IntegerLiteralImpl, TIntegerLiteralSynth { @@ -52,7 +56,7 @@ class IntegerLiteralSynth extends IntegerLiteralImpl, TIntegerLiteralSynth { } // TODO: implement properly -float parseFloat(Ruby::Float f) { result = f.getValue().toFloat() } +float parseFloat(Ruby::Float f) { result = getTokenValue(f).toFloat() } class FloatLiteralImpl extends Expr, TFloatLiteral { private Ruby::Float g; @@ -61,7 +65,7 @@ class FloatLiteralImpl extends Expr, TFloatLiteral { final float getValue() { result = parseFloat(g) } - final override string toString() { result = g.getValue() } + final override string toString() { result = getTokenValue(g) } } predicate isRationalValue(Ruby::Rational r, int numerator, int denominator) { @@ -71,8 +75,8 @@ predicate isRationalValue(Ruby::Rational r, int numerator, int denominator) { exists(Ruby::Float f, string regex, string before, string after | f = r.getChild() and regex = "([^.]*)\\.(.*)" and - before = f.getValue().regexpCapture(regex, 1) and - after = f.getValue().regexpCapture(regex, 2) and + before = getTokenValue(f).regexpCapture(regex, 1) and + after = getTokenValue(f).regexpCapture(regex, 2) and numerator = before.toInt() * denominator + after.toInt() and denominator = 10.pow(after.length()) ) @@ -87,14 +91,14 @@ class RationalLiteralImpl extends Expr, TRationalLiteral { isRationalValue(g, numerator, denominator) } - final override string toString() { result = g.getChild().(Ruby::Token).getValue() + "r" } + final override string toString() { result = getTokenValue(g.getChild()) + "r" } } float getComplexValue(Ruby::Complex c) { exists(int n, int d | isRationalValue(c.getChild(), n, d) and result = n.(float) / d.(float)) or exists(string s | - s = c.getChild().(Ruby::Token).getValue() and + s = getTokenValue(c.getChild()) and result = s.prefix(s.length()).toFloat() ) } @@ -109,8 +113,8 @@ class ComplexLiteralImpl extends Expr, TComplexLiteral { } final override string toString() { - result = g.getChild().(Ruby::Token).getValue() + "i" or - result = g.getChild().(Ruby::Rational).getChild().(Ruby::Token).getValue() + "ri" + result = getTokenValue(g.getChild()) + "i" or + result = getTokenValue(g.getChild().(Ruby::Rational).getChild()) + "ri" } } @@ -137,7 +141,7 @@ class TrueLiteral extends BooleanLiteralImpl, TTrueLiteral { TrueLiteral() { this = TTrueLiteral(g) } - final override string toString() { result = g.getValue() } + final override string toString() { result = getTokenValue(g) } final override boolean getValue() { result = true } } @@ -147,7 +151,7 @@ class FalseLiteral extends BooleanLiteralImpl, TFalseLiteral { FalseLiteral() { this = TFalseLiteral(g) } - final override string toString() { result = g.getValue() } + final override string toString() { result = getTokenValue(g) } final override boolean getValue() { result = false } } @@ -290,9 +294,9 @@ class RangeLiteralSynth extends RangeLiteralImpl, TRangeLiteralSynth { } private string getMethodName(MethodName::Token t) { - result = t.(Ruby::Token).getValue() + result = getTokenValue(t) or - result = t.(Ruby::Setter).getName().getValue() + "=" + result = getTokenValue(t.(Ruby::Setter).getName()) + "=" } class TokenMethodName extends Expr, TTokenMethodName { @@ -339,9 +343,9 @@ class StringTextComponentStringOrHeredocContent extends StringTextComponentImpl, final override string getValue() { result = this.getUnescapedText() } - final override string getRawTextImpl() { result = g.getValue() } + final override string getRawTextImpl() { result = getTokenValue(g) } - final private string getUnescapedText() { result = unescapeTextComponent(g.getValue()) } + final private string getUnescapedText() { result = unescapeTextComponent(getTokenValue(g)) } } private class StringTextComponentSimpleSymbol extends StringTextComponentImpl, @@ -352,7 +356,7 @@ private class StringTextComponentSimpleSymbol extends StringTextComponentImpl, StringTextComponentSimpleSymbol() { this = TStringTextComponentNonRegexpSimpleSymbol(g) } // Tree-sitter gives us value text including the colon, which we skip. - private string getSimpleSymbolValue() { result = g.getValue().suffix(1) } + private string getSimpleSymbolValue() { result = getTokenValue(g).suffix(1) } final override string getValue() { result = this.getSimpleSymbolValue() } @@ -366,9 +370,9 @@ private class StringTextComponentHashKeySymbol extends StringTextComponentImpl, StringTextComponentHashKeySymbol() { this = TStringTextComponentNonRegexpHashKeySymbol(g) } - final override string getValue() { result = g.getValue() } + final override string getValue() { result = getTokenValue(g) } - final override string getRawTextImpl() { result = g.getValue() } + final override string getRawTextImpl() { result = getTokenValue(g) } } bindingset[escaped] @@ -438,9 +442,9 @@ class StringEscapeSequenceComponentImpl extends StringComponentImpl, final override string getValue() { result = this.getUnescapedText() } - final string getRawTextImpl() { result = g.getValue() } + final string getRawTextImpl() { result = getTokenValue(g) } - final private string getUnescapedText() { result = unescapeEscapeSequence(g.getValue()) } + final private string getUnescapedText() { result = unescapeEscapeSequence(getTokenValue(g)) } final override string toString() { result = this.getRawTextImpl() } } @@ -473,10 +477,10 @@ class RegExpTextComponentImpl extends RegExpComponentImpl, TStringTextComponentR // Exclude components that are children of a free-spacing regex. // We do this because `ParseRegExp.qll` cannot handle free-spacing regexes. not this.getParent().(RegExpLiteral).hasFreeSpacingFlag() and - result = g.getValue() + result = getTokenValue(g) } - final override string toString() { result = g.getValue() } + final override string toString() { result = getTokenValue(g) } } class RegExpEscapeSequenceComponentImpl extends RegExpComponentImpl, @@ -490,10 +494,10 @@ class RegExpEscapeSequenceComponentImpl extends RegExpComponentImpl, // Exclude components that are children of a free-spacing regex. // We do this because `ParseRegExp.qll` cannot handle free-spacing regexes. not this.getParent().(RegExpLiteral).hasFreeSpacingFlag() and - result = g.getValue() + result = getTokenValue(g) } - final override string toString() { result = g.getValue() } + final override string toString() { result = getTokenValue(g) } } class RegExpInterpolationComponentImpl extends RegExpComponentImpl, @@ -564,7 +568,7 @@ abstract class StringlikeLiteralImpl extends Expr, TStringlikeLiteral { concat(StringComponent c, int i, string s | c = this.getComponentImpl(i) and ( - s = toGenerated(c).(Ruby::Token).getValue() + s = getTokenValue(toGenerated(c)) or not toGenerated(c) instanceof Ruby::Token and s = "#{...}" @@ -635,7 +639,7 @@ class SimpleSymbolLiteralReal extends SimpleSymbolLiteralImpl, TSimpleSymbolLite final override StringComponent getComponentImpl(int n) { n = 0 and toGenerated(result) = g } - final override string toString() { result = g.getValue() } + final override string toString() { result = getTokenValue(g) } } class SimpleSymbolLiteralSynth extends SimpleSymbolLiteralImpl, TSimpleSymbolLiteralSynth, @@ -677,7 +681,7 @@ private class HashKeySymbolLiteral extends SymbolLiteralImpl, THashKeySymbolLite final override StringComponent getComponentImpl(int n) { n = 0 and toGenerated(result) = g } - final override string toString() { result = ":" + g.getValue() } + final override string toString() { result = ":" + getTokenValue(g) } } class RegExpLiteralImpl extends StringlikeLiteralImpl, TRegExpLiteral { @@ -701,9 +705,9 @@ class CharacterLiteralImpl extends Expr, TCharacterLiteral { CharacterLiteralImpl() { this = TCharacterLiteral(g) } - final string getValue() { result = g.getValue() } + final string getValue() { result = getTokenValue(g) } - final override string toString() { result = g.getValue() } + final override string toString() { result = getTokenValue(g) } } class HereDocImpl extends StringlikeLiteralImpl, THereDoc { @@ -715,5 +719,5 @@ class HereDocImpl extends StringlikeLiteralImpl, THereDoc { toGenerated(result) = getHereDocBody(g).getChild(n) } - final override string toString() { result = g.getValue() } + final override string toString() { result = getTokenValue(g) } } diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll index 3670cc5eb98..4d65a743346 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll @@ -639,7 +639,7 @@ private TMethodOrExpr lookupMethodOrConst(Module m, string name) { // For now, we restrict the scope of top-level declarations to their file. // This may remove some plausible targets, but also removes a lot of // implausible targets - if getNode(result).getEnclosingModule() instanceof Toplevel - then getNode(result).getFile() = m.getADeclaration().getFile() - else any() + forall(File file | file = getNode(result).getEnclosingModule().(Toplevel).getFile() | + file = m.getADeclaration().getFile() + ) } diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Scope.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Scope.qll index 9ec237012bc..03fe2ce4350 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Scope.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Scope.qll @@ -149,11 +149,11 @@ cached private module Cached { /** Gets the enclosing scope of a node */ cached - Scope::Range scopeOf(Ruby::AstNode n) { + Scope::Range scopeOfImpl(Ruby::AstNode n) { exists(Ruby::AstNode p | p = parentOf(n) | p = result or - not p instanceof Scope::Range and result = scopeOf(p) + not p instanceof Scope::Range and result = scopeOfImpl(p) ) } @@ -163,16 +163,22 @@ private module Cached { * and synthesized scopes into account. */ cached - Scope scopeOfInclSynth(AstNode n) { + Scope scopeOfInclSynthImpl(AstNode n) { exists(AstNode p | p = parentOfInclSynth(n) | p = result or - not p instanceof Scope and result = scopeOfInclSynth(p) + not p instanceof Scope and result = scopeOfInclSynthImpl(p) ) } } -import Cached +bindingset[n] +pragma[inline_late] +Scope::Range scopeOf(Ruby::AstNode n) { result = Cached::scopeOfImpl(n) } + +bindingset[n] +pragma[inline_late] +Scope scopeOfInclSynth(AstNode n) { result = Cached::scopeOfInclSynthImpl(n) } abstract class ScopeImpl extends AstNode, TScopeType { final Scope getOuterScopeImpl() { result = scopeOfInclSynth(this) } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll index 70c761e411c..3c647f41bbb 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll @@ -687,26 +687,30 @@ pragma[nomagic] private CfgScope getTargetInstance(DataFlowCall call, string method) { exists(boolean exact | result = lookupInstanceMethodCall(call, method, exact) and - ( - if result.(Method).isPrivate() - then - call.asCall().getReceiver().getExpr() instanceof SelfVariableAccess and - // For now, we restrict the scope of top-level declarations to their file. - // This may remove some plausible targets, but also removes a lot of - // implausible targets - ( - isToplevelMethodInFile(result, call.asCall().getFile()) or - not isToplevelMethodInFile(result, _) - ) - else any() - ) and - if result.(Method).isProtected() - then - result = lookupMethod(call.asCall().getExpr().getEnclosingModule().getModule(), method, exact) - else any() + (if result.(Method).isPrivate() then result = privateFilter(call) else any()) and + if result.(Method).isProtected() then result = protectedFilter(call, method, exact) else any() ) } +bindingset[call, result] +pragma[inline_late] +private CfgScope privateFilter(DataFlowCall call) { + call.asCall().getReceiver().getExpr() instanceof SelfVariableAccess and + // For now, we restrict the scope of top-level declarations to their file. + // This may remove some plausible targets, but also removes a lot of + // implausible targets + ( + isToplevelMethodInFile(result, call.asCall().getFile()) or + not isToplevelMethodInFile(result, _) + ) +} + +bindingset[call, method, exact, result] +pragma[inline_late] +private CfgScope protectedFilter(DataFlowCall call, string method, boolean exact) { + result = lookupMethod(call.asCall().getExpr().getEnclosingModule().getModule(), method, exact) +} + private module TrackBlockInput implements CallGraphConstruction::Simple::InputSig { class State = Block; diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll index 9332aa43e52..e4bcf2537a7 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll @@ -28,7 +28,13 @@ abstract class NodeImpl extends Node { DataFlowCallable getEnclosingCallable() { result = TCfgScope(this.getCfgScope()) } /** Do not call: use `getEnclosingCallable()` instead. */ - abstract CfgScope getCfgScope(); + abstract CfgScope getCfgScopeImpl(); + + /** Do not call: use `getEnclosingCallable()` instead. */ + pragma[inline] + final CfgScope getCfgScope() { + pragma[only_bind_into](result) = pragma[only_bind_out](this).getCfgScopeImpl() + } /** Do not call: use `getLocation()` instead. */ abstract Location getLocationImpl(); @@ -38,7 +44,7 @@ abstract class NodeImpl extends Node { } private class ExprNodeImpl extends ExprNode, NodeImpl { - override CfgScope getCfgScope() { result = this.getExprNode().getExpr().getCfgScope() } + override CfgScope getCfgScopeImpl() { result = this.getExprNode().getExpr().getCfgScope() } override Location getLocationImpl() { result = this.getExprNode().getLocation() } @@ -780,7 +786,7 @@ class SsaNode extends NodeImpl, TSsaNode { /** Holds if this node should be hidden from path explanations. */ predicate isHidden() { any() } - override CfgScope getCfgScope() { result = node.getBasicBlock().getScope() } + override CfgScope getCfgScopeImpl() { result = node.getBasicBlock().getScope() } override Location getLocationImpl() { result = node.getLocation() } @@ -827,7 +833,7 @@ class CapturedVariableNode extends NodeImpl, TCapturedVariableNode { /** Gets the captured variable represented by this node. */ VariableCapture::CapturedVariable getVariable() { result = variable } - override CfgScope getCfgScope() { result = variable.getCallable() } + override CfgScope getCfgScopeImpl() { result = variable.getCallable() } override Location getLocationImpl() { result = variable.getLocation() } @@ -849,7 +855,7 @@ class ReturningStatementNode extends NodeImpl, TReturningNode { /** Gets the expression corresponding to this node. */ CfgNodes::ReturningCfgNode getReturningNode() { result = n } - override CfgScope getCfgScope() { result = n.getScope() } + override CfgScope getCfgScopeImpl() { result = n.getScope() } override Location getLocationImpl() { result = n.getLocation() } @@ -867,7 +873,7 @@ class CaptureNode extends NodeImpl, TCaptureNode { VariableCapture::Flow::SynthesizedCaptureNode getSynthesizedCaptureNode() { result = cn } - override CfgScope getCfgScope() { result = cn.getEnclosingCallable() } + override CfgScope getCfgScopeImpl() { result = cn.getEnclosingCallable() } override Location getLocationImpl() { result = cn.getLocation() } @@ -935,7 +941,7 @@ private module ParameterNodes { ) } - override CfgScope getCfgScope() { result = parameter.getCallable() } + override CfgScope getCfgScopeImpl() { result = parameter.getCallable() } override Location getLocationImpl() { result = parameter.getLocation() } @@ -979,7 +985,7 @@ private module ParameterNodes { final override SelfVariable getSelfVariable() { result.getDeclaringScope() = method } - override CfgScope getCfgScope() { result = method } + override CfgScope getCfgScopeImpl() { result = method } override Location getLocationImpl() { result = method.getLocation() } } @@ -1001,7 +1007,7 @@ private module ParameterNodes { final override SelfVariable getSelfVariable() { result.getDeclaringScope() = t } - override CfgScope getCfgScope() { result = t } + override CfgScope getCfgScopeImpl() { result = t } override Location getLocationImpl() { result = t.getLocation() } } @@ -1028,7 +1034,7 @@ private module ParameterNodes { callable = c.asCfgScope() and pos.isLambdaSelf() } - override CfgScope getCfgScope() { result = callable } + override CfgScope getCfgScopeImpl() { result = callable } override Location getLocationImpl() { result = callable.getLocation() } @@ -1071,7 +1077,7 @@ private module ParameterNodes { c.asCfgScope() = method and pos.isBlock() } - override CfgScope getCfgScope() { result = method } + override CfgScope getCfgScopeImpl() { result = method } override Location getLocationImpl() { result = this.getParameter().getLocation() @@ -1130,7 +1136,7 @@ private module ParameterNodes { c = callable and pos.isSynthHashSplat() } - final override CfgScope getCfgScope() { result = callable.asCfgScope() } + final override CfgScope getCfgScopeImpl() { result = callable.asCfgScope() } final override DataFlowCallable getEnclosingCallable() { result = callable } @@ -1193,7 +1199,7 @@ private module ParameterNodes { ) } - final override CfgScope getCfgScope() { result = callable.asCfgScope() } + final override CfgScope getCfgScopeImpl() { result = callable.asCfgScope() } final override DataFlowCallable getEnclosingCallable() { result = callable } @@ -1240,7 +1246,7 @@ private module ParameterNodes { cs = getArrayContent(pos) } - final override CfgScope getCfgScope() { result = callable.asCfgScope() } + final override CfgScope getCfgScopeImpl() { result = callable.asCfgScope() } final override DataFlowCallable getEnclosingCallable() { result = callable } @@ -1278,7 +1284,7 @@ class FlowSummaryNode extends NodeImpl, TFlowSummaryNode { result = this.getSummaryNode().getSummarizedCallable() } - override CfgScope getCfgScope() { none() } + override CfgScope getCfgScopeImpl() { none() } override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = this.getSummarizedCallable() @@ -1349,7 +1355,7 @@ module ArgumentNodes { this.sourceArgumentOf(call.asCall(), pos) } - override CfgScope getCfgScope() { result = yield.getScope() } + override CfgScope getCfgScopeImpl() { result = yield.getScope() } override Location getLocationImpl() { result = yield.getLocation() } } @@ -1379,7 +1385,7 @@ module ArgumentNodes { this.sourceArgumentOf(call.asCall(), pos) } - override CfgScope getCfgScope() { result = sup.getScope() } + override CfgScope getCfgScopeImpl() { result = sup.getScope() } override Location getLocationImpl() { result = sup.getLocation() } } @@ -1415,7 +1421,7 @@ module ArgumentNodes { this.sourceArgumentOf(call.asCall(), pos) } - final override CfgScope getCfgScope() { result = call_.getExpr().getCfgScope() } + final override CfgScope getCfgScopeImpl() { result = call_.getExpr().getCfgScope() } final override Location getLocationImpl() { result = call_.getLocation() } } @@ -1563,7 +1569,7 @@ module ArgumentNodes { ) } - override CfgScope getCfgScope() { result = c.getExpr().getCfgScope() } + override CfgScope getCfgScopeImpl() { result = c.getExpr().getCfgScope() } override Location getLocationImpl() { result = c.getLocation() } @@ -2037,16 +2043,21 @@ private predicate compatibleTypesNonSymRefl(DataFlowType t1, DataFlowType t2) { } pragma[nomagic] -private predicate compatibleModuleTypes(TModuleDataFlowType t1, TModuleDataFlowType t2) { - exists(Module m1, Module m2, Module m3 | - t1 = TModuleDataFlowType(m1) and - t2 = TModuleDataFlowType(m2) - | +private predicate compatibleModules(Module m1, Module m2) { + exists(Module m3 | m3.getAnAncestor() = m1 and m3.getAnAncestor() = m2 ) } +private predicate compatibleModuleTypes(TModuleDataFlowType t1, TModuleDataFlowType t2) { + exists(Module m1, Module m2 | + compatibleModules(m1, m2) and + t1 = TModuleDataFlowType(m1) and + t2 = TModuleDataFlowType(m2) + ) +} + /** * Holds if `t1` and `t2` are compatible, that is, whether data can flow from * a node of type `t1` to a node of type `t2`. @@ -2074,7 +2085,7 @@ private module PostUpdateNodes { override ExprNode getPreUpdateNode() { e = result.getExprNode() } - override CfgScope getCfgScope() { result = e.getExpr().getCfgScope() } + override CfgScope getCfgScopeImpl() { result = e.getExpr().getCfgScope() } override Location getLocationImpl() { result = e.getLocation() } diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll index 42c6286e4ea..6275da6d98c 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll @@ -500,6 +500,7 @@ private module Persistence { class ActiveRecordAssociation extends DataFlow::CallNode { private ActiveRecordModelClass modelClass; + pragma[nomagic] ActiveRecordAssociation() { not exists(this.asExpr().getExpr().getEnclosingMethod()) and this.asExpr().getExpr().getEnclosingModule() = modelClass and @@ -583,6 +584,14 @@ private string pluralize(string input) { exists(string stem | stem + "s" = input) and result = input } +pragma[nomagic] +private predicate activeRecordAssociationMethodCall( + DataFlow::CallNode call, ActiveRecordAssociation assoc, string model +) { + call.getReceiver().(ActiveRecordInstance).getClass() = assoc.getSourceClass() and + model = assoc.getTargetModelName() +} + /** * A call to a method generated by an ActiveRecord association. * These yield ActiveRecord collection proxies, which act like collections but @@ -595,24 +604,21 @@ private class ActiveRecordAssociationMethodCall extends DataFlow::CallNode { ActiveRecordAssociation assoc; ActiveRecordAssociationMethodCall() { - exists(string model | model = assoc.getTargetModelName() | - this.getReceiver().(ActiveRecordInstance).getClass() = assoc.getSourceClass() and + exists(string model | activeRecordAssociationMethodCall(this, assoc, model) | + assoc.isCollection() and ( - assoc.isCollection() and - ( - this.getMethodName() = pluralize(model) + ["", "="] - or - this.getMethodName() = "<<" - or - this.getMethodName() = model + ["_ids", "_ids="] - ) + this.getMethodName() = pluralize(model) + ["", "="] or - assoc.isSingular() and - ( - this.getMethodName() = model + ["", "="] or - this.getMethodName() = ["build_", "reload_"] + model or - this.getMethodName() = "create_" + model + ["!", ""] - ) + this.getMethodName() = "<<" + or + this.getMethodName() = model + ["_ids", "_ids="] + ) + or + assoc.isSingular() and + ( + this.getMethodName() = model + ["", "="] or + this.getMethodName() = ["build_", "reload_"] + model or + this.getMethodName() = "create_" + model + ["!", ""] ) ) } diff --git a/ruby/ql/lib/codeql/ruby/frameworks/actioncontroller/Filters.qll b/ruby/ql/lib/codeql/ruby/frameworks/actioncontroller/Filters.qll index 568f99da475..20bde03daad 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/actioncontroller/Filters.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/actioncontroller/Filters.qll @@ -46,6 +46,10 @@ module Filters { ) } + bindingset[m, name] + pragma[inline_late] + private Method lookupMethodInlineLate(Module m, string name) { result = lookupMethod(m, name) } + /** * A call to a class method that adds or removes a filter from the callback chain. * This class exists to encapsulate common behavior between calls that @@ -140,7 +144,8 @@ module Filters { */ Callable getAFilterCallable() { result = - lookupMethod(this.getExpr().getEnclosingModule().getModule(), this.getFilterArgumentName()) + lookupMethodInlineLate(this.getExpr().getEnclosingModule().getModule(), + this.getFilterArgumentName()) } } diff --git a/ruby/ql/lib/codeql/ruby/frameworks/actiondispatch/internal/Routing.qll b/ruby/ql/lib/codeql/ruby/frameworks/actiondispatch/internal/Routing.qll index 5910317b2c1..e6e453d449f 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/actiondispatch/internal/Routing.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/actiondispatch/internal/Routing.qll @@ -943,6 +943,7 @@ module Routing { * Note: All-uppercase words like `CONSTANT` are not handled correctly. */ bindingset[base] + pragma[inline_late] string underscore(string base) { base = "" and result = "" or diff --git a/ruby/ql/lib/codeql/ruby/frameworks/core/Array.qll b/ruby/ql/lib/codeql/ruby/frameworks/core/Array.qll index ec21ffc7475..a29f7c2a427 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/core/Array.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/core/Array.qll @@ -526,7 +526,7 @@ module Array { MethodCall mc; bindingset[this] - DeleteSummary() { mc.getMethodName() = "delete" } + DeleteSummary() { pragma[only_bind_into](mc).getMethodName() = "delete" } final override MethodCall getACallSimple() { result = mc } @@ -790,7 +790,7 @@ module Array { MethodCall mc; bindingset[this] - FetchSummary() { mc.getMethodName() = "fetch" } + FetchSummary() { pragma[only_bind_into](mc).getMethodName() = "fetch" } override MethodCall getACallSimple() { result = mc } } diff --git a/ruby/ql/lib/codeql/ruby/frameworks/core/Hash.qll b/ruby/ql/lib/codeql/ruby/frameworks/core/Hash.qll index 36d7bd2cc75..c1a4c4d50d1 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/core/Hash.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/core/Hash.qll @@ -286,7 +286,7 @@ abstract private class FetchValuesSummary extends SummarizedCallable::Range { MethodCall mc; bindingset[this] - FetchValuesSummary() { mc.getMethodName() = "fetch_values" } + FetchValuesSummary() { pragma[only_bind_into](mc).getMethodName() = "fetch_values" } final override MethodCall getACallSimple() { result = mc } @@ -390,7 +390,7 @@ abstract private class SliceSummary extends SummarizedCallable::Range { MethodCall mc; bindingset[this] - SliceSummary() { mc.getMethodName() = "slice" } + SliceSummary() { pragma[only_bind_into](mc).getMethodName() = "slice" } final override MethodCall getACallSimple() { result = mc } } From 093c27955ff61cb7e2f940d8a90aad4f9971a055 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com> Date: Fri, 20 Mar 2026 15:24:15 +0000 Subject: [PATCH 33/48] Fix incorrect QLDoc Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll b/rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll index 7ca64bedb5f..5813e9df690 100644 --- a/rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll +++ b/rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll @@ -10,7 +10,7 @@ * v * barrierNode predicate | other QL defined barriers, for example using concepts * v v - * various Barrier classes for specific data flow configurations <- extending QueryBarrier + * various Barrier classes for specific data flow configurations * ``` * * New barriers should be defined using models-as-data, QL extensions of From d2fcced5adf53ee9dde4338ceae57c49b5290736 Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Fri, 20 Mar 2026 09:59:12 -0700 Subject: [PATCH 34/48] Add a `feature` change note --- .../2026-03-20-add-indirect-uninitialized-node.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cpp/ql/lib/change-notes/2026-03-20-add-indirect-uninitialized-node.md diff --git a/cpp/ql/lib/change-notes/2026-03-20-add-indirect-uninitialized-node.md b/cpp/ql/lib/change-notes/2026-03-20-add-indirect-uninitialized-node.md new file mode 100644 index 00000000000..9dd67f8910d --- /dev/null +++ b/cpp/ql/lib/change-notes/2026-03-20-add-indirect-uninitialized-node.md @@ -0,0 +1,4 @@ +--- +category: feature +--- +* A new data flow class called `IndirectUninitializedNode` represents uninitialized data of a variable behind some level of indirection. From a9eb801fea3c20b17882d74f3e92afe88cd81a78 Mon Sep 17 00:00:00 2001 From: Gregro Date: Thu, 19 Mar 2026 02:33:38 +0000 Subject: [PATCH 35/48] C#: Fix false positives in cs/log-forging for extension methods --- ...03-19-fix-log-forging-extension-methods.md | 8 ++++ ...crosoft.Extensions.Logging.Sinks.model.yml | 40 +++++++++++++++++++ .../security/dataflow/LogForgingQuery.qll | 12 +++++- .../Security Features/CWE-117/LogForging.cs | 18 +++++++++ .../CWE-117/LogForging.expected | 14 +++++-- 5 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 csharp/ql/lib/change-notes/2026-03-19-fix-log-forging-extension-methods.md create mode 100644 csharp/ql/lib/ext/Microsoft.Extensions.Logging.Sinks.model.yml diff --git a/csharp/ql/lib/change-notes/2026-03-19-fix-log-forging-extension-methods.md b/csharp/ql/lib/change-notes/2026-03-19-fix-log-forging-extension-methods.md new file mode 100644 index 00000000000..7bf22b65221 --- /dev/null +++ b/csharp/ql/lib/change-notes/2026-03-19-fix-log-forging-extension-methods.md @@ -0,0 +1,8 @@ +--- +category: minorAnalysis +--- +* The `cs/log-forging` query no longer treats arguments to user-defined extension methods + on `ILogger` types as sinks. Instead, taint is tracked interprocedurally through extension + method bodies, reducing false positives when extension methods sanitize input internally. + Known framework extension methods (`Microsoft.Extensions.Logging.LoggerExtensions`) are + now modeled as explicit sinks via Models as Data. diff --git a/csharp/ql/lib/ext/Microsoft.Extensions.Logging.Sinks.model.yml b/csharp/ql/lib/ext/Microsoft.Extensions.Logging.Sinks.model.yml new file mode 100644 index 00000000000..c42173c3f7a --- /dev/null +++ b/csharp/ql/lib/ext/Microsoft.Extensions.Logging.Sinks.model.yml @@ -0,0 +1,40 @@ +extensions: + - addsTo: + pack: codeql/csharp-all + extensible: sinkModel + data: + # Log overloads + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "Log", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.LogLevel,Microsoft.Extensions.Logging.EventId,System.Exception,System.String,System.Object[])", "", "Argument[4..5]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "Log", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.LogLevel,Microsoft.Extensions.Logging.EventId,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "Log", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.LogLevel,System.Exception,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "Log", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.LogLevel,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] + # LogCritical overloads + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogCritical", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.Exception,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogCritical", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogCritical", "(Microsoft.Extensions.Logging.ILogger,System.Exception,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogCritical", "(Microsoft.Extensions.Logging.ILogger,System.String,System.Object[])", "", "Argument[1..2]", "log-injection", "manual"] + # LogDebug overloads + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogDebug", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.Exception,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogDebug", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogDebug", "(Microsoft.Extensions.Logging.ILogger,System.Exception,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogDebug", "(Microsoft.Extensions.Logging.ILogger,System.String,System.Object[])", "", "Argument[1..2]", "log-injection", "manual"] + # LogError overloads + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogError", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.Exception,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogError", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogError", "(Microsoft.Extensions.Logging.ILogger,System.Exception,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogError", "(Microsoft.Extensions.Logging.ILogger,System.String,System.Object[])", "", "Argument[1..2]", "log-injection", "manual"] + # LogInformation overloads + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogInformation", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.Exception,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogInformation", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogInformation", "(Microsoft.Extensions.Logging.ILogger,System.Exception,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogInformation", "(Microsoft.Extensions.Logging.ILogger,System.String,System.Object[])", "", "Argument[1..2]", "log-injection", "manual"] + # LogTrace overloads + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogTrace", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.Exception,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogTrace", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogTrace", "(Microsoft.Extensions.Logging.ILogger,System.Exception,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogTrace", "(Microsoft.Extensions.Logging.ILogger,System.String,System.Object[])", "", "Argument[1..2]", "log-injection", "manual"] + # LogWarning overloads + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogWarning", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.Exception,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogWarning", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogWarning", "(Microsoft.Extensions.Logging.ILogger,System.Exception,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] + - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogWarning", "(Microsoft.Extensions.Logging.ILogger,System.String,System.Object[])", "", "Argument[1..2]", "log-injection", "manual"] diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/LogForgingQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/LogForgingQuery.qll index 22023ebc409..b3e0149c2f0 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/LogForgingQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/LogForgingQuery.qll @@ -10,6 +10,7 @@ private import semmle.code.csharp.frameworks.system.text.RegularExpressions private import semmle.code.csharp.security.Sanitizers private import semmle.code.csharp.security.dataflow.flowsinks.ExternalLocationSink private import semmle.code.csharp.dataflow.internal.ExternalFlow +private import semmle.code.csharp.commons.Loggers /** * A data flow source for untrusted user input used in log entries. @@ -52,9 +53,16 @@ private class HtmlSanitizer extends Sanitizer { } /** - * An argument to a call to a method on a logger class. + * An argument to a call to a method on a logger class, excluding extension methods + * which are analyzed interprocedurally. */ -private class LogForgingLogMessageSink extends Sink, LogMessageSink { } +private class LogForgingLogMessageSink extends Sink { + LogForgingLogMessageSink() { + this.getExpr() = any(LoggerType i).getAMethod().getACall().getAnArgument() or + this.getExpr() = + any(MethodCall call | call.getQualifier().getType() instanceof LoggerType).getAnArgument() + } +} /** * An argument to a call to a method on a trace class. diff --git a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs index 18169e4a4b0..70cce8493ff 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs @@ -33,6 +33,11 @@ public class LogForgingHandler : IHttpHandler Microsoft.Extensions.Logging.ILogger logger2 = null; // BAD: Logged as-is logger2.LogError(username); // $ Alert + + // GOOD: uses safe extension method that sanitizes internally + logger.WarnSafe(username + " logged in"); + // BAD: uses unsafe extension method that does not sanitize + logger.WarnUnsafe(username + " logged in"); } public bool IsReusable @@ -43,3 +48,16 @@ public class LogForgingHandler : IHttpHandler } } } + +static class LoggerExtensions +{ + public static void WarnSafe(this ILogger logger, string message) + { + logger.Warn(message.Replace(Environment.NewLine, "")); + } + + public static void WarnUnsafe(this ILogger logger, string message) + { + logger.Warn(message); // $ Alert + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected index 1820eaa07d9..04397886a0b 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected @@ -2,17 +2,22 @@ | LogForging.cs:21:21:21:43 | ... + ... | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:21:21:21:43 | ... + ... | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value | | LogForging.cs:31:50:31:72 | ... + ... | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:31:50:31:72 | ... + ... | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value | | LogForging.cs:35:26:35:33 | access to local variable username | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:35:26:35:33 | access to local variable username | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value | +| LogForging.cs:61:21:61:27 | access to parameter message | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:61:21:61:27 | access to parameter message | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value | | LogForgingAsp.cs:17:21:17:43 | ... + ... | LogForgingAsp.cs:13:32:13:39 | username : String | LogForgingAsp.cs:17:21:17:43 | ... + ... | This log entry depends on a $@. | LogForgingAsp.cs:13:32:13:39 | username | user-provided value | edges | LogForging.cs:18:16:18:23 | access to local variable username : String | LogForging.cs:21:21:21:43 | ... + ... | provenance | | | LogForging.cs:18:16:18:23 | access to local variable username : String | LogForging.cs:31:50:31:72 | ... + ... | provenance | | -| LogForging.cs:18:16:18:23 | access to local variable username : String | LogForging.cs:35:26:35:33 | access to local variable username | provenance | | +| LogForging.cs:18:16:18:23 | access to local variable username : String | LogForging.cs:35:26:35:33 | access to local variable username | provenance | Sink:MaD:1 | +| LogForging.cs:18:16:18:23 | access to local variable username : String | LogForging.cs:40:27:40:49 | ... + ... : String | provenance | | | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:18:16:18:23 | access to local variable username : String | provenance | | -| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:18:27:18:61 | access to indexer : String | provenance | MaD:1 | +| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:18:27:18:61 | access to indexer : String | provenance | MaD:2 | | LogForging.cs:18:27:18:61 | access to indexer : String | LogForging.cs:18:16:18:23 | access to local variable username : String | provenance | | +| LogForging.cs:40:27:40:49 | ... + ... : String | LogForging.cs:59:63:59:69 | message : String | provenance | | +| LogForging.cs:59:63:59:69 | message : String | LogForging.cs:61:21:61:27 | access to parameter message | provenance | | | LogForgingAsp.cs:13:32:13:39 | username : String | LogForgingAsp.cs:17:21:17:43 | ... + ... | provenance | | models -| 1 | Summary: System.Collections.Specialized; NameValueCollection; false; get_Item; (System.String); ; Argument[this]; ReturnValue; taint; df-generated | +| 1 | Sink: Microsoft.Extensions.Logging; LoggerExtensions; false; LogError; (Microsoft.Extensions.Logging.ILogger,System.String,System.Object[]); ; Argument[1..2]; log-injection; manual | +| 2 | Summary: System.Collections.Specialized; NameValueCollection; false; get_Item; (System.String); ; Argument[this]; ReturnValue; taint; df-generated | nodes | LogForging.cs:18:16:18:23 | access to local variable username : String | semmle.label | access to local variable username : String | | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection | @@ -20,6 +25,9 @@ nodes | LogForging.cs:21:21:21:43 | ... + ... | semmle.label | ... + ... | | LogForging.cs:31:50:31:72 | ... + ... | semmle.label | ... + ... | | LogForging.cs:35:26:35:33 | access to local variable username | semmle.label | access to local variable username | +| LogForging.cs:40:27:40:49 | ... + ... : String | semmle.label | ... + ... : String | +| LogForging.cs:59:63:59:69 | message : String | semmle.label | message : String | +| LogForging.cs:61:21:61:27 | access to parameter message | semmle.label | access to parameter message | | LogForgingAsp.cs:13:32:13:39 | username : String | semmle.label | username : String | | LogForgingAsp.cs:17:21:17:43 | ... + ... | semmle.label | ... + ... | subpaths From d99247cf13c5792bd6d36cbb5b08e0a631bcaab9 Mon Sep 17 00:00:00 2001 From: Gregro Date: Sat, 21 Mar 2026 18:12:14 +0000 Subject: [PATCH 36/48] Clarify static extension method class name --- .../ql/test/query-tests/Security Features/CWE-117/LogForging.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs index 70cce8493ff..adc10f75715 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs @@ -49,7 +49,7 @@ public class LogForgingHandler : IHttpHandler } } -static class LoggerExtensions +static class UserLoggerExtensions { public static void WarnSafe(this ILogger logger, string message) { From d0c48893f59b771efd7caa43280c6ae9897cb5ab Mon Sep 17 00:00:00 2001 From: Gregro Date: Sat, 21 Mar 2026 18:30:44 +0000 Subject: [PATCH 37/48] update test helper to use more robust .ReplaceLineEndings() sanitizer --- .../ql/test/query-tests/Security Features/CWE-117/LogForging.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs index adc10f75715..10ff408e226 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs @@ -53,7 +53,7 @@ static class UserLoggerExtensions { public static void WarnSafe(this ILogger logger, string message) { - logger.Warn(message.Replace(Environment.NewLine, "")); + logger.Warn(message.ReplaceLineEndings("")); } public static void WarnUnsafe(this ILogger logger, string message) From a59c865328fde4832848239fdff96832a8fedcef Mon Sep 17 00:00:00 2001 From: Gregro Date: Sat, 21 Mar 2026 19:30:31 +0000 Subject: [PATCH 38/48] let interprocedural analysis handle source-available extension methods for LogForgingLogMessageSink's --- ...03-19-fix-log-forging-extension-methods.md | 9 ++--- ...crosoft.Extensions.Logging.Sinks.model.yml | 40 ------------------- .../security/dataflow/LogForgingQuery.qll | 12 +++--- .../CWE-117/LogForging.expected | 7 ++-- 4 files changed, 13 insertions(+), 55 deletions(-) delete mode 100644 csharp/ql/lib/ext/Microsoft.Extensions.Logging.Sinks.model.yml diff --git a/csharp/ql/lib/change-notes/2026-03-19-fix-log-forging-extension-methods.md b/csharp/ql/lib/change-notes/2026-03-19-fix-log-forging-extension-methods.md index 7bf22b65221..65ce217b105 100644 --- a/csharp/ql/lib/change-notes/2026-03-19-fix-log-forging-extension-methods.md +++ b/csharp/ql/lib/change-notes/2026-03-19-fix-log-forging-extension-methods.md @@ -1,8 +1,7 @@ --- category: minorAnalysis --- -* The `cs/log-forging` query no longer treats arguments to user-defined extension methods - on `ILogger` types as sinks. Instead, taint is tracked interprocedurally through extension - method bodies, reducing false positives when extension methods sanitize input internally. - Known framework extension methods (`Microsoft.Extensions.Logging.LoggerExtensions`) are - now modeled as explicit sinks via Models as Data. +* The `cs/log-forging` query no longer treats arguments to extension methods with + source code on `ILogger` types as sinks. Instead, taint is tracked interprocedurally + through extension method bodies, reducing false positives when extension methods + sanitize input internally. diff --git a/csharp/ql/lib/ext/Microsoft.Extensions.Logging.Sinks.model.yml b/csharp/ql/lib/ext/Microsoft.Extensions.Logging.Sinks.model.yml deleted file mode 100644 index c42173c3f7a..00000000000 --- a/csharp/ql/lib/ext/Microsoft.Extensions.Logging.Sinks.model.yml +++ /dev/null @@ -1,40 +0,0 @@ -extensions: - - addsTo: - pack: codeql/csharp-all - extensible: sinkModel - data: - # Log overloads - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "Log", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.LogLevel,Microsoft.Extensions.Logging.EventId,System.Exception,System.String,System.Object[])", "", "Argument[4..5]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "Log", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.LogLevel,Microsoft.Extensions.Logging.EventId,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "Log", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.LogLevel,System.Exception,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "Log", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.LogLevel,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] - # LogCritical overloads - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogCritical", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.Exception,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogCritical", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogCritical", "(Microsoft.Extensions.Logging.ILogger,System.Exception,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogCritical", "(Microsoft.Extensions.Logging.ILogger,System.String,System.Object[])", "", "Argument[1..2]", "log-injection", "manual"] - # LogDebug overloads - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogDebug", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.Exception,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogDebug", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogDebug", "(Microsoft.Extensions.Logging.ILogger,System.Exception,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogDebug", "(Microsoft.Extensions.Logging.ILogger,System.String,System.Object[])", "", "Argument[1..2]", "log-injection", "manual"] - # LogError overloads - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogError", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.Exception,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogError", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogError", "(Microsoft.Extensions.Logging.ILogger,System.Exception,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogError", "(Microsoft.Extensions.Logging.ILogger,System.String,System.Object[])", "", "Argument[1..2]", "log-injection", "manual"] - # LogInformation overloads - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogInformation", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.Exception,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogInformation", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogInformation", "(Microsoft.Extensions.Logging.ILogger,System.Exception,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogInformation", "(Microsoft.Extensions.Logging.ILogger,System.String,System.Object[])", "", "Argument[1..2]", "log-injection", "manual"] - # LogTrace overloads - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogTrace", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.Exception,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogTrace", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogTrace", "(Microsoft.Extensions.Logging.ILogger,System.Exception,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogTrace", "(Microsoft.Extensions.Logging.ILogger,System.String,System.Object[])", "", "Argument[1..2]", "log-injection", "manual"] - # LogWarning overloads - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogWarning", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.Exception,System.String,System.Object[])", "", "Argument[3..4]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogWarning", "(Microsoft.Extensions.Logging.ILogger,Microsoft.Extensions.Logging.EventId,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogWarning", "(Microsoft.Extensions.Logging.ILogger,System.Exception,System.String,System.Object[])", "", "Argument[2..3]", "log-injection", "manual"] - - ["Microsoft.Extensions.Logging", "LoggerExtensions", false, "LogWarning", "(Microsoft.Extensions.Logging.ILogger,System.String,System.Object[])", "", "Argument[1..2]", "log-injection", "manual"] diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/LogForgingQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/LogForgingQuery.qll index b3e0149c2f0..293b8ff9b8b 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/LogForgingQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/LogForgingQuery.qll @@ -10,7 +10,6 @@ private import semmle.code.csharp.frameworks.system.text.RegularExpressions private import semmle.code.csharp.security.Sanitizers private import semmle.code.csharp.security.dataflow.flowsinks.ExternalLocationSink private import semmle.code.csharp.dataflow.internal.ExternalFlow -private import semmle.code.csharp.commons.Loggers /** * A data flow source for untrusted user input used in log entries. @@ -54,13 +53,14 @@ private class HtmlSanitizer extends Sanitizer { /** * An argument to a call to a method on a logger class, excluding extension methods - * which are analyzed interprocedurally. + * with source code which are analyzed interprocedurally. */ -private class LogForgingLogMessageSink extends Sink { +private class LogForgingLogMessageSink extends Sink, LogMessageSink { LogForgingLogMessageSink() { - this.getExpr() = any(LoggerType i).getAMethod().getACall().getAnArgument() or - this.getExpr() = - any(MethodCall call | call.getQualifier().getType() instanceof LoggerType).getAnArgument() + not exists(ExtensionMethodCall mc | + this.getExpr() = mc.getAnArgument() and + mc.getTarget().fromSource() + ) } } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected index 04397886a0b..994cabadc75 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected @@ -7,17 +7,16 @@ edges | LogForging.cs:18:16:18:23 | access to local variable username : String | LogForging.cs:21:21:21:43 | ... + ... | provenance | | | LogForging.cs:18:16:18:23 | access to local variable username : String | LogForging.cs:31:50:31:72 | ... + ... | provenance | | -| LogForging.cs:18:16:18:23 | access to local variable username : String | LogForging.cs:35:26:35:33 | access to local variable username | provenance | Sink:MaD:1 | +| LogForging.cs:18:16:18:23 | access to local variable username : String | LogForging.cs:35:26:35:33 | access to local variable username | provenance | | | LogForging.cs:18:16:18:23 | access to local variable username : String | LogForging.cs:40:27:40:49 | ... + ... : String | provenance | | | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:18:16:18:23 | access to local variable username : String | provenance | | -| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:18:27:18:61 | access to indexer : String | provenance | MaD:2 | +| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:18:27:18:61 | access to indexer : String | provenance | MaD:1 | | LogForging.cs:18:27:18:61 | access to indexer : String | LogForging.cs:18:16:18:23 | access to local variable username : String | provenance | | | LogForging.cs:40:27:40:49 | ... + ... : String | LogForging.cs:59:63:59:69 | message : String | provenance | | | LogForging.cs:59:63:59:69 | message : String | LogForging.cs:61:21:61:27 | access to parameter message | provenance | | | LogForgingAsp.cs:13:32:13:39 | username : String | LogForgingAsp.cs:17:21:17:43 | ... + ... | provenance | | models -| 1 | Sink: Microsoft.Extensions.Logging; LoggerExtensions; false; LogError; (Microsoft.Extensions.Logging.ILogger,System.String,System.Object[]); ; Argument[1..2]; log-injection; manual | -| 2 | Summary: System.Collections.Specialized; NameValueCollection; false; get_Item; (System.String); ; Argument[this]; ReturnValue; taint; df-generated | +| 1 | Summary: System.Collections.Specialized; NameValueCollection; false; get_Item; (System.String); ; Argument[this]; ReturnValue; taint; df-generated | nodes | LogForging.cs:18:16:18:23 | access to local variable username : String | semmle.label | access to local variable username : String | | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection | From ee00b98476df28c8d1698d3c6a93644db0c4d66a Mon Sep 17 00:00:00 2001 From: Jeroen Ketema <93738568+jketema@users.noreply.github.com> Date: Mon, 23 Mar 2026 10:44:21 +0100 Subject: [PATCH 39/48] Update cpp/ql/lib/change-notes/2026-03-20-add-indirect-uninitialized-node.md --- .../change-notes/2026-03-20-add-indirect-uninitialized-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/lib/change-notes/2026-03-20-add-indirect-uninitialized-node.md b/cpp/ql/lib/change-notes/2026-03-20-add-indirect-uninitialized-node.md index 9dd67f8910d..60f6b0a276e 100644 --- a/cpp/ql/lib/change-notes/2026-03-20-add-indirect-uninitialized-node.md +++ b/cpp/ql/lib/change-notes/2026-03-20-add-indirect-uninitialized-node.md @@ -1,4 +1,4 @@ --- category: feature --- -* A new data flow class called `IndirectUninitializedNode` represents uninitialized data of a variable behind some level of indirection. +* Added a new data flow node, `IndirectUninitializedNode`, that represents uninitialized local variables behind a number of indirections. From 09caeca7e9b3347cebd9f4a5e2a563d9c38a9ea9 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 23 Mar 2026 13:27:20 +0000 Subject: [PATCH 40/48] C++: Move parameter indirection nodes into the public API. --- .../code/cpp/ir/dataflow/internal/DataFlowNodes.qll | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll index fe954c640d1..36dc85f4f40 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll @@ -795,6 +795,12 @@ module Public { /** An explicit positional parameter, including `this`, but not `...`. */ final class DirectParameterNode = AbstractDirectParameterNode; + /** + * A node representing an indirection of a positional parameter, + * including `*this`, but not `*...`. + */ + final class IndirectParameterNode = AbstractIndirectParameterNode; + final class ExplicitParameterNode = AbstractExplicitParameterNode; /** An implicit `this` parameter. */ @@ -954,11 +960,6 @@ module Public { private import Public -/** - * A node representing an indirection of a parameter. - */ -final class IndirectParameterNode = AbstractIndirectParameterNode; - /** * A class that lifts pre-SSA dataflow nodes to regular dataflow nodes. */ From 1363c54a9f16d26e52c845478f67eb2b55f10d09 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 23 Mar 2026 13:28:33 +0000 Subject: [PATCH 41/48] C++: Add 'asIndirectInstruction' as a public predicate. --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll index 36dc85f4f40..51eabe8b223 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll @@ -321,6 +321,12 @@ module Public { */ Operand asIndirectOperand(int index) { hasOperandAndIndex(this, result, index) } + /** + * Gets the instruction that is indirectly tracked by this node behind + * `index` number of indirections. + */ + Instruction asIndirectInstruction(int index) { hasInstructionAndIndex(this, result, index) } + /** * Holds if this node is at index `i` in basic block `block`. * From fef314e27fff8f92d06aa807545097443fdf0aa2 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 23 Mar 2026 13:39:15 +0000 Subject: [PATCH 42/48] C++: Add change note. --- ...-23-indirect-parameter-nodes-and-indirect-instructions.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 cpp/ql/lib/change-notes/2026-03-23-indirect-parameter-nodes-and-indirect-instructions.md diff --git a/cpp/ql/lib/change-notes/2026-03-23-indirect-parameter-nodes-and-indirect-instructions.md b/cpp/ql/lib/change-notes/2026-03-23-indirect-parameter-nodes-and-indirect-instructions.md new file mode 100644 index 00000000000..c3bd4028ee9 --- /dev/null +++ b/cpp/ql/lib/change-notes/2026-03-23-indirect-parameter-nodes-and-indirect-instructions.md @@ -0,0 +1,5 @@ +--- +category: feature +--- +* Added a class `DataFlow::IndirectParameterNode` to represent the indirection of a parameter as a dataflow node. +* Added a predicate `Node::asIndirectInstruction` which returns the `Instruction` that defines the indirect dataflow node, if any. \ No newline at end of file From 8cebf510dc9964c40121dd89cf43dedbb3be2b73 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 23 Mar 2026 13:45:46 +0000 Subject: [PATCH 43/48] C++: Reword the change note from #21458. --- .../change-notes/2026-03-20-add-indirect-uninitialized-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/lib/change-notes/2026-03-20-add-indirect-uninitialized-node.md b/cpp/ql/lib/change-notes/2026-03-20-add-indirect-uninitialized-node.md index 60f6b0a276e..07235e047d4 100644 --- a/cpp/ql/lib/change-notes/2026-03-20-add-indirect-uninitialized-node.md +++ b/cpp/ql/lib/change-notes/2026-03-20-add-indirect-uninitialized-node.md @@ -1,4 +1,4 @@ --- category: feature --- -* Added a new data flow node, `IndirectUninitializedNode`, that represents uninitialized local variables behind a number of indirections. +* Added a class `IndirectUninitializedNode` to represent the indirection of an uninitialized local variable as a dataflow node. From d82fc67b364ea63ba60441d45eabd01edf2caf64 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 23 Mar 2026 16:11:22 +0000 Subject: [PATCH 44/48] Fix QLDoc formatting --- .../ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll index a3f3da9364d..451608329f6 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll @@ -112,10 +112,10 @@ extensible predicate barrierModel( * Holds if in a call to the function with canonical path `path`, the value referred * to by `input` is a barrier guard of the given `kind` and `madId` is the data * extension row number. - * the value referred to by `input` is assumed to lead to a parameter of a call - * (possibly `self`), and the call is guarding the parameter. - * `branch` is either `true` or `false`, indicating which branch of the guard - * is protecting the parameter. + * + * The value referred to by `input` is assumed to lead to a parameter of a call + * (possibly `self`), and the call is guarding the parameter. `branch` is either `true` + * or `false`, indicating which branch of the guard is protecting the parameter. */ extensible predicate barrierGuardModel( string path, string input, string branch, string kind, string provenance, From 97ebc0e8398023a0e18c8d5c3ccb743c2ae1980f Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 23 Mar 2026 16:22:27 +0000 Subject: [PATCH 45/48] Update QLDoc in FlowBarrier.qll --- rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll b/rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll index 5813e9df690..49e1d676921 100644 --- a/rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll +++ b/rust/ql/lib/codeql/rust/dataflow/FlowBarrier.qll @@ -1,7 +1,7 @@ /** - * Provides classes and predicates for defining barriers. + * Provides classes and predicates for defining barriers and barrier guards. * - * Flow barriers defined here feed into data flow configurations as follows: + * Flow barriers and barrier guards defined here feed into data flow configurations as follows: * * ```text * data from *.model.yml | QL extensions of FlowBarrier::Range @@ -11,10 +11,18 @@ * barrierNode predicate | other QL defined barriers, for example using concepts * v v * various Barrier classes for specific data flow configurations + * + * data from *.model.yml | QL extensions of FlowBarrierGuard::Range + * v v + * FlowBarrierGuard (associated with a models-as-data kind string) + * v + * barrierNode predicate | other QL defined barrier guards, for example using concepts + * v v + * various Barrier classes for specific data flow configurations * ``` * - * New barriers should be defined using models-as-data, QL extensions of - * `FlowBarrier::Range`, or concepts. Data flow configurations should use the + * New barriers and barrier guards should be defined using models-as-data, QL extensions of + * `FlowBarrier::Range`/`FlowBarrierGuard::Range`, or concepts. Data flow configurations should use the * `barrierNode` predicate and/or concepts to define their barriers. */ From 8d16a2b4fa51dce30c15cd401599a2d9c3090982 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 23 Mar 2026 16:24:03 +0000 Subject: [PATCH 46/48] Fix `parameter` -> `argument` in QLDoc --- rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll index 451608329f6..4d28dd8de81 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll @@ -113,9 +113,9 @@ extensible predicate barrierModel( * to by `input` is a barrier guard of the given `kind` and `madId` is the data * extension row number. * - * The value referred to by `input` is assumed to lead to a parameter of a call - * (possibly `self`), and the call is guarding the parameter. `branch` is either `true` - * or `false`, indicating which branch of the guard is protecting the parameter. + * The value referred to by `input` is assumed to lead to an argument of a call + * (possibly `self`), and the call is guarding the argument. `branch` is either `true` + * or `false`, indicating which branch of the guard is protecting the argument. */ extensible predicate barrierGuardModel( string path, string input, string branch, string kind, string provenance, From 19424627c16d3460a7cca37652f5904d0feb5465 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Mar 2026 20:19:09 +0000 Subject: [PATCH 47/48] update codeql documentation --- .../codeql-changelog/codeql-cli-2.19.1.rst | 2 +- .../codeql-changelog/codeql-cli-2.21.3.rst | 2 +- .../codeql-changelog/codeql-cli-2.22.3.rst | 2 +- .../codeql-changelog/codeql-cli-2.25.0.rst | 131 ++++++++++++++++++ .../codeql-changelog/index.rst | 1 + 5 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.25.0.rst diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst index f2948d0db67..39d4d36537c 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.19.1.rst @@ -129,7 +129,7 @@ Java/Kotlin """"""""""" * The Java extractor and QL libraries now support Java 23. -* Kotlin versions up to 2.1.0\ *x* are now supported. +* Kotlin versions up to 2.1.0*x* are now supported. Python """""" diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst index 71a8e3a6824..fffe94c04b8 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.3.rst @@ -144,7 +144,7 @@ New Features Java/Kotlin """"""""""" -* Kotlin versions up to 2.2.0\ *x* are now supported. Support for the Kotlin 1.5.x series is dropped (so the minimum Kotlin version is now 1.6.0). +* Kotlin versions up to 2.2.0*x* are now supported. Support for the Kotlin 1.5.x series is dropped (so the minimum Kotlin version is now 1.6.0). Swift """"" diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst index 4f1d34ff2dd..8e5a18a0c74 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.22.3.rst @@ -98,4 +98,4 @@ C/C++ Java/Kotlin """"""""""" -* Kotlin versions up to 2.2.2\ *x* are now supported. +* Kotlin versions up to 2.2.2*x* are now supported. diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.25.0.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.25.0.rst new file mode 100644 index 00000000000..7c371a3a365 --- /dev/null +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.25.0.rst @@ -0,0 +1,131 @@ +.. _codeql-cli-2.25.0: + +========================== +CodeQL 2.25.0 (2026-03-19) +========================== + +.. contents:: Contents + :depth: 2 + :local: + :backlinks: none + +This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog `__, `relevant GitHub Changelog updates `__, `changes in the CodeQL extension for Visual Studio Code `__, and the `CodeQL Action changelog `__. + +Security Coverage +----------------- + +CodeQL 2.25.0 runs a total of 491 security queries when configured with the Default suite (covering 166 CWE). The Extended suite enables an additional 135 queries (covering 35 more CWE). + +CodeQL CLI +---------- + +Breaking Changes +~~~~~~~~~~~~~~~~ + +* :code:`codeql database interpret-results` and :code:`codeql database analyze` no longer attempt to reconstruct file baseline information from databases created with CLI versions before 2.11.2. + +Bug Fixes +~~~~~~~~~ + +* Upgraded Jackson library from 2.16.1 to 2.18.6 to address a high-severity denial of service vulnerability (GHSA-72hv-8253-57qq) in jackson-core's async JSON parser. +* Upgraded snakeyaml (which is a dependency of jackson-dataformat-yaml) from 2.2 to 2.3. + +Language Libraries +------------------ + +Breaking Changes +~~~~~~~~~~~~~~~~ + +Java/Kotlin +""""""""""" + +* The Java control flow graph (CFG) implementation has been completely rewritten. The CFG now includes additional nodes to more accurately represent certain constructs. This also means that any existing code that implicitly relies on very specific details about the CFG may need to be updated. + The CFG now only includes the nodes that are reachable from the entry point. + Additionally, the following breaking changes have been made: + + * :code:`ControlFlowNode.asCall` has been removed - use :code:`Call.getControlFlowNode` instead. + * :code:`ControlFlowNode.getEnclosingStmt` has been removed. + * :code:`ControlFlow::ExprNode` has been removed. + * :code:`ControlFlow::StmtNode` has been removed. + * :code:`ControlFlow::Node` has been removed - this was merely an alias of + :code:`ControlFlowNode`, which is still available. + * Previously deprecated predicates on :code:`BasicBlock` have been removed. + +Major Analysis Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Swift +""""" + +* Upgraded to allow analysis of Swift 6.2.4. + +Minor Analysis Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +C/C++ +""""" + +* Inline expectations test comments, which are of the form :code:`// $ tag` or :code:`// $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the :code:`$` symbol. + +C# +"" + +* Inline expectations test comments, which are of the form :code:`// $ tag` or :code:`// $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the :code:`$` symbol. +* Added :code:`System.Net.WebSockets::ReceiveAsync` as a remote flow source. +* Added reverse taint flow from implicit conversion operator calls to their arguments. +* Added post-update nodes for struct-type arguments, allowing data flow out of method calls via those arguments. +* C# 14: Added support for partial constructors. + +Golang +"""""" + +* Inline expectations test comments, which are of the form :code:`// $ tag` or :code:`// $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the :code:`$` symbol. + +Java/Kotlin +""""""""""" + +* Inline expectations test comments, which are of the form :code:`// $ tag` or :code:`// $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the :code:`$` symbol. +* The class :code:`Assignment` now extends :code:`BinaryExpr`. Uses of :code:`BinaryExpr` may in some cases need slight adjustment. + +JavaScript/TypeScript +""""""""""""""""""""" + +* Added support for browser-specific source kinds (:code:`browser`, :code:`browser-url-query`, :code:`browser-url-fragment`, :code:`browser-url-path`, :code:`browser-url`, :code:`browser-window-name`, :code:`browser-message-event`) that can be used in data extensions to model sources in browser environments. +* Inline expectations test comments, which are of the form :code:`// $ tag` or :code:`// $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the :code:`$` symbol. + +Python +"""""" + +* The call graph resolution no longer considers methods marked using |link-code-typing-overload-1|_ as valid targets. This ensures that only the method that contains the actual implementation gets resolved as a target. +* Inline expectations test comments, which are of the form :code:`# $ tag` or :code:`# $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the :code:`$` symbol. + +Ruby +"""" + +* Inline expectations test comments, which are of the form :code:`# $ tag` or :code:`# $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the :code:`$` symbol. + +Swift +""""" + +* Inline expectations test comments, which are of the form :code:`// $ tag` or :code:`// $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the :code:`$` symbol. + +Rust +"""" + +* Inline expectations test comments, which are of the form :code:`// $ tag` or :code:`// $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the :code:`$` symbol. +* Added neutral models to inhibit spurious generated sink models for :code:`map` and :code:`from`. This fixes some false positive query results. + +Shared Libraries +---------------- + +New Features +~~~~~~~~~~~~ + +Dataflow Analysis +""""""""""""""""" + +* Two new flow features :code:`FeatureEscapesSourceCallContext` and :code:`FeatureEscapesSourceCallContextOrEqualSourceSinkCallContext` have been added. The former implies that the sink must be reached from the source by escaping the source call context, that is, flow must either return from the callable containing the source or use a jump-step before reaching the sink. The latter is the disjunction of the former and the existing :code:`FeatureEqualSourceSinkCallContext` flow feature. + +.. |link-code-typing-overload-1| replace:: :code:`@typing.overload`\ +.. _link-code-typing-overload-1: https://typing.python.org/en/latest/spec/overload.html#overloads + diff --git a/docs/codeql/codeql-overview/codeql-changelog/index.rst b/docs/codeql/codeql-overview/codeql-changelog/index.rst index c128fe96410..d880a7e56d8 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/index.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/index.rst @@ -11,6 +11,7 @@ A list of queries for each suite and language `is available here Date: Mon, 23 Mar 2026 23:17:22 +0000 Subject: [PATCH 48/48] C++: Fix bad join in `callsVariadicFormatter` On `wireshark` this reduces the intermediate tuple count from roughly 88 million tuples to roughly 3000 (with the new helper predicate materialising ~300 tuples). --- cpp/ql/lib/semmle/code/cpp/commons/Printf.qll | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll b/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll index 023ce09c5c1..d189dd36f87 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll @@ -163,12 +163,23 @@ predicate primitiveVariadicFormatter( ) } +/** + * Gets a function call whose target is a variadic formatter with the given + * `type`, `format` parameter index and `output` parameter index. + * + * Join-order helper for `callsVariadicFormatter`. + */ +pragma[nomagic] +private predicate callsVariadicFormatterCall(FunctionCall fc, string type, int format, int output) { + variadicFormatter(fc.getTarget(), type, format, output) +} + private predicate callsVariadicFormatter( Function f, string type, int formatParamIndex, int outputParamIndex ) { // calls a variadic formatter with `formatParamIndex`, `outputParamIndex` linked exists(FunctionCall fc, int format, int output | - variadicFormatter(pragma[only_bind_into](fc.getTarget()), type, format, output) and + callsVariadicFormatterCall(fc, type, format, output) and fc.getEnclosingFunction() = f and fc.getArgument(format) = f.getParameter(formatParamIndex).getAnAccess() and fc.getArgument(output) = f.getParameter(outputParamIndex).getAnAccess() @@ -176,7 +187,7 @@ private predicate callsVariadicFormatter( or // calls a variadic formatter with only `formatParamIndex` linked exists(FunctionCall fc, string calledType, int format, int output | - variadicFormatter(pragma[only_bind_into](fc.getTarget()), calledType, format, output) and + callsVariadicFormatterCall(fc, calledType, format, output) and fc.getEnclosingFunction() = f and fc.getArgument(format) = f.getParameter(formatParamIndex).getAnAccess() and not fc.getArgument(output) = f.getParameter(_).getAnAccess() and