From 8808f0f8249c10790d35be1785368ac0ee8c5ee5 Mon Sep 17 00:00:00 2001 From: Taus Date: Wed, 8 Jan 2025 15:56:17 +0000 Subject: [PATCH 001/336] Misc: Add script for calculating MRVA totals Use this script if you want to quickly calculate the totals of some query across all the queries in a MRVA run. For an example of such a query, see e.g. `python/ql/src/Metrics/Internal/TypeAnnotations.ql` The script expects the query to produce an output table of the form ``` | header0 | header1 | header2 | header3 | ... |----------|----------|----------|----------|---- | message1 | value11 | value12 | value13 | ... | message2 | value21 | value22 | value23 | ... ... ``` where all of the `values` are numbers. For each `(message, header)` pair, it then calculates the total of all the values in that cell, across all of the repos in the MRVA run. To use the script, simply pass it the URL of the exported Gist of the MRVA run. After calculating the totals, the script will then (optionally, but by default) add the totals to the `_summary.md` file, and push these changes to the Gist. --- misc/scripts/calculate_mrva_totals.py | 131 ++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 misc/scripts/calculate_mrva_totals.py diff --git a/misc/scripts/calculate_mrva_totals.py b/misc/scripts/calculate_mrva_totals.py new file mode 100644 index 000000000000..cec1b8b54bfd --- /dev/null +++ b/misc/scripts/calculate_mrva_totals.py @@ -0,0 +1,131 @@ +import os +import subprocess +import tempfile +import argparse +from collections import defaultdict + +help_text = """ +To use this script, pass the URL of a GitHub Gist as an argument. The Gist should contain the +exported MarkDown output of a MRVA run. + +The script expects the query to produce an output table of the form +``` +| header0 | header1 | header2 | header3 | ... +|----------|----------|----------|----------|---- +| message1 | value11 | value12 | value13 | ... +| message2 | value21 | value22 | value23 | ... +... +``` +The script will calculate the totals for each message and header, and put a table containing these +totals in the `_summary.md` file in the Gist. By default it will then commit and push these changes +to the Gist (having first displayed a diff of the changes). +""" + +first_header = "" + +def split_line(line): + return [item.strip() for item in line.strip('|').split('|')] + +def parse_markdown_table(stream): + global first_header + iterator = (line.strip() for line in stream) + + # Skip irrelevant lines until we find the header line + for line in iterator: + if line.startswith('|'): + first_header, *headers = split_line(line) + break + + # Skip the separator line + next(iterator) + + data_dict = {} + + # Process the remaining lines + for line in iterator: + if line.startswith('|'): + message, *values = [value.strip('`') for value in split_line(line)] + data_dict[message] = { + headers[i]: int(value) if value.isdigit() else value + for i, value in enumerate(values) + } + + return data_dict + +def clone_gist(gist_url, repo_dir): + try: + subprocess.run(["gh", "gist", "clone", gist_url, repo_dir], check=True) + except subprocess.CalledProcessError: + print(f"Failed to clone the gist from {gist_url}") + subprocess.run(["rm", "-rf", repo_dir]) + exit(1) + +def process_gist_files(repo_dir): + total_data = defaultdict(lambda: defaultdict(int)) + + for filename in os.listdir(repo_dir): + if filename.endswith(".md") and filename != "_summary.md": + with open(os.path.join(repo_dir, filename), "r") as file: + data_dict = parse_markdown_table(file) + + for message, values in data_dict.items(): + for header, value in values.items(): + if isinstance(value, int): + total_data[message][header] += value + + return total_data + +def append_totals_to_summary(total_data, repo_dir): + global first_header + summary_path = os.path.join(repo_dir, "_summary.md") + with open(summary_path, "r") as summary_file: + content = summary_file.read() + + totals_table = "\n\n### Totals\n\n" + headers = [first_header] + list(next(iter(total_data.values())).keys()) + totals_table += "| " + " | ".join(headers) + " |\n" + totals_table += "| " + "|".join(["---"] + ["---:"] * (len(headers) - 1)) + " |\n" # Right align all but the first column + for message, values in total_data.items(): + row = [message] + [f"{values[header]:,}" for header in headers[1:]] + totals_table += "| " + " | ".join(row) + " |\n" + + new_content = content.replace("### Summary", totals_table + "\n### Summary") + + with open(summary_path, "w") as summary_file: + summary_file.write(new_content) + +def commit_and_push_changes(repo_dir): + subprocess.run(["git", "add", "_summary.md"], cwd=repo_dir, check=True) + subprocess.run(["git", "commit", "-m", "Update summary with totals"], cwd=repo_dir, check=True) + subprocess.run(["git", "push"], cwd=repo_dir, check=True) + +def show_git_diff(repo_dir): + subprocess.run(["git", "diff", "_summary.md"], cwd=repo_dir, check=True) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Calculate MRVA totals from a GitHub Gist", epilog=help_text, formatter_class=argparse.RawTextHelpFormatter) + parser.add_argument("gist_url", nargs='?', help="URL of the GitHub Gist") + parser.add_argument("--keep-dir", action="store_true", help="Keep the temporary directory") + + args = parser.parse_args() + + if not args.gist_url: + parser.print_help() + exit(1) + + repo_dir = tempfile.mkdtemp(dir=".") + clone_gist(args.gist_url, repo_dir) + + total_data = process_gist_files(repo_dir) + + append_totals_to_summary(total_data, repo_dir) + + show_git_diff(repo_dir) + + if input("Do you want to push the changes to the gist? (Y/n): ").strip().lower() in ['y', '']: + commit_and_push_changes(repo_dir) + + if args.keep_dir: + print(f"Temporary directory retained at: {repo_dir}") + else: + subprocess.run(["rm", "-rf", repo_dir]) From 395d54bf867803acddc8012c4c44bf8b56531165 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 23 Jan 2025 12:46:09 +0100 Subject: [PATCH 002/336] Create Base.qll --- cpp/ql/lib/experimental/Quantum/Base.qll | 165 +++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 cpp/ql/lib/experimental/Quantum/Base.qll diff --git a/cpp/ql/lib/experimental/Quantum/Base.qll b/cpp/ql/lib/experimental/Quantum/Base.qll new file mode 100644 index 000000000000..bfdd509174e5 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/Base.qll @@ -0,0 +1,165 @@ +/** + * A language-independent library for reasoning about cryptography. + */ + +import codeql.util.Location +import codeql.util.Option + +signature module InputSig { + class KnownUnknownLocation extends Location; + + class LocatableElement { + Location getLocation(); + } +} + +module CryptographyBase Input> { + final class LocatableElement = Input::LocatableElement; + + newtype TNode = + TNodeUnknown() or + TNodeAsset() or + TNodeValue() // currently unused + + class KnownNode = TNodeAsset or TNodeValue; + + abstract class NodeBase extends TNode { + /** + * Returns a string representation of this node, usually the name of the operation/algorithm/property. + */ + abstract string toString(); + + /** + * Returns the location of this node in the code. + */ + abstract Location getLocation(); + + /** + * Returns the child of this node with the given edge name. + * + * This predicate is used by derived classes to construct the graph of cryptographic operations. + */ + NodeBase getChild(string edgeName) { none() } + + /** + * Returns the parent of this node. + */ + final NodeBase getAParent() { result.getChild(_) = this } + } + + /** + * A node representing an unknown value. + * + * If a property should have a value but that value is unknown, `UnknownNode` to represent that value. + */ + final class UnknownNode extends NodeBase, TNodeUnknown { + override string toString() { result = "unknown" } + + override Location getLocation() { result instanceof Input::KnownUnknownLocation } + } + + /** + * A node with a known location in the code. + */ + abstract class LocatableNode extends NodeBase, TNodeAsset { + abstract LocatableElement toElement(); + + override Location getLocation() { result = this.toElement().getLocation() } + } + + /** + * A node representing a known asset, i.e., an algorithm, operation, or property. + */ + class Asset = LocatableNode; + + /** + * A cryptographic operation, such as hashing or encryption. + */ + abstract class Operation extends Asset { + /** + * Gets the algorithm associated with this operation. + */ + private NodeBase getAlgorithmOrUnknown() { + if exists(this.getAlgorithm()) + then result = this.getAlgorithm() + else result instanceof UnknownNode + } + + abstract Algorithm getAlgorithm(); + + /** + * Gets the name of this operation, e.g., "hash" or "encrypt". + */ + abstract string getOperationName(); + + final override string toString() { result = this.getOperationName() } + + override NodeBase getChild(string edgeName) { + edgeName = "algorithm" and + this.getAlgorithmOrUnknown() = result + } + } + + abstract class Algorithm extends Asset { + /** + * Gets the name of this algorithm, e.g., "AES" or "SHA". + */ + abstract string getAlgorithmName(); + + final override string toString() { result = this.getAlgorithmName() } + } + + /** + * A hashing operation that processes data to generate a hash value. + * This operation takes an input message of arbitrary content and length and produces a fixed-size + * hash value as the output using a specified hashing algorithm. + */ + abstract class HashOperation extends Operation { + abstract override HashAlgorithm getAlgorithm(); + + override string getOperationName() { result = "hash" } + } + + /** + * A hashing algorithm that transforms variable-length input into a fixed-size hash value. + */ + abstract class HashAlgorithm extends Algorithm { } + + /** + * An operation that derives one or more keys from an input value. + */ + abstract class KeyDerivationOperation extends Operation { + override string getOperationName() { result = "key derivation" } + } + + /** + * An algorithm that derives one or more keys from an input value. + */ + abstract class KeyDerivationAlgorithm extends Algorithm { + abstract override string getAlgorithmName(); + } + + /** + * HKDF Extract+Expand key derivation function. + */ + abstract class HKDFAlgorithm extends KeyDerivationAlgorithm { + final override string getAlgorithmName() { result = "HKDF" } + + private NodeBase getHashAlgorithmOrUnknown() { + if exists(this.getHashAlgorithm()) + then result = this.getHashAlgorithm() + else result instanceof UnknownNode + } + + abstract HashAlgorithm getHashAlgorithm(); + + /** + * digest:HashAlgorithm + */ + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + edgeName = "digest" and result = this.getHashAlgorithmOrUnknown() + } + } +} From 1a7d8cb99db194624238ab0d2880bd6984c96904 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Fri, 24 Jan 2025 17:33:03 +0100 Subject: [PATCH 003/336] WIP --- cpp/ql/lib/experimental/Quantum/Base.qll | 80 ++++------- .../lib/experimental/Quantum/BaseBackup.qll | 125 ++++++++++++++++++ cpp/ql/lib/experimental/Quantum/Language.qll | 10 ++ cpp/ql/lib/experimental/Quantum/OpenSSL.qll | 100 ++++++++++++++ cpp/ql/src/experimental/Quantum/Test.ql | 17 +++ cpp/ql/src/experimental/Quantum/Test2.ql | 8 ++ 6 files changed, 288 insertions(+), 52 deletions(-) create mode 100644 cpp/ql/lib/experimental/Quantum/BaseBackup.qll create mode 100644 cpp/ql/lib/experimental/Quantum/Language.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL.qll create mode 100644 cpp/ql/src/experimental/Quantum/Test.ql create mode 100644 cpp/ql/src/experimental/Quantum/Test2.ql diff --git a/cpp/ql/lib/experimental/Quantum/Base.qll b/cpp/ql/lib/experimental/Quantum/Base.qll index bfdd509174e5..8a910eb44143 100644 --- a/cpp/ql/lib/experimental/Quantum/Base.qll +++ b/cpp/ql/lib/experimental/Quantum/Base.qll @@ -6,8 +6,6 @@ import codeql.util.Location import codeql.util.Option signature module InputSig { - class KnownUnknownLocation extends Location; - class LocatableElement { Location getLocation(); } @@ -16,14 +14,7 @@ signature module InputSig { module CryptographyBase Input> { final class LocatableElement = Input::LocatableElement; - newtype TNode = - TNodeUnknown() or - TNodeAsset() or - TNodeValue() // currently unused - - class KnownNode = TNodeAsset or TNodeValue; - - abstract class NodeBase extends TNode { + abstract class NodeBase instanceof LocatableElement { /** * Returns a string representation of this node, usually the name of the operation/algorithm/property. */ @@ -32,14 +23,19 @@ module CryptographyBase Input> { /** * Returns the location of this node in the code. */ - abstract Location getLocation(); + Location getLocation() { result = super.getLocation() } /** * Returns the child of this node with the given edge name. * * This predicate is used by derived classes to construct the graph of cryptographic operations. */ - NodeBase getChild(string edgeName) { none() } + NodeBase getChild(string edgeName) { edgeName = "origin" and result = this.getOrigin() } + + /** + * Gets the origin of this node, e.g., a string literal in source describing it. + */ + NodeBase getOrigin() { none() } /** * Returns the parent of this node. @@ -47,30 +43,7 @@ module CryptographyBase Input> { final NodeBase getAParent() { result.getChild(_) = this } } - /** - * A node representing an unknown value. - * - * If a property should have a value but that value is unknown, `UnknownNode` to represent that value. - */ - final class UnknownNode extends NodeBase, TNodeUnknown { - override string toString() { result = "unknown" } - - override Location getLocation() { result instanceof Input::KnownUnknownLocation } - } - - /** - * A node with a known location in the code. - */ - abstract class LocatableNode extends NodeBase, TNodeAsset { - abstract LocatableElement toElement(); - - override Location getLocation() { result = this.toElement().getLocation() } - } - - /** - * A node representing a known asset, i.e., an algorithm, operation, or property. - */ - class Asset = LocatableNode; + class Asset = NodeBase; /** * A cryptographic operation, such as hashing or encryption. @@ -79,12 +52,6 @@ module CryptographyBase Input> { /** * Gets the algorithm associated with this operation. */ - private NodeBase getAlgorithmOrUnknown() { - if exists(this.getAlgorithm()) - then result = this.getAlgorithm() - else result instanceof UnknownNode - } - abstract Algorithm getAlgorithm(); /** @@ -95,8 +62,10 @@ module CryptographyBase Input> { final override string toString() { result = this.getOperationName() } override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or edgeName = "algorithm" and - this.getAlgorithmOrUnknown() = result + if exists(this.getAlgorithm()) then result = this.getAlgorithm() else result = this } } @@ -125,6 +94,10 @@ module CryptographyBase Input> { */ abstract class HashAlgorithm extends Algorithm { } + abstract class SHA1 extends HashAlgorithm { + override string getAlgorithmName() { result = "SHA1" } + } + /** * An operation that derives one or more keys from an input value. */ @@ -142,24 +115,27 @@ module CryptographyBase Input> { /** * HKDF Extract+Expand key derivation function. */ - abstract class HKDFAlgorithm extends KeyDerivationAlgorithm { + abstract class HKDF extends KeyDerivationAlgorithm { final override string getAlgorithmName() { result = "HKDF" } - private NodeBase getHashAlgorithmOrUnknown() { - if exists(this.getHashAlgorithm()) - then result = this.getHashAlgorithm() - else result instanceof UnknownNode + abstract HashAlgorithm getHashAlgorithm(); + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + edgeName = "digest" and result = this.getHashAlgorithm() } + } + + abstract class PKCS12KDF extends KeyDerivationAlgorithm { + final override string getAlgorithmName() { result = "PKCS12KDF" } abstract HashAlgorithm getHashAlgorithm(); - /** - * digest:HashAlgorithm - */ override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) or - edgeName = "digest" and result = this.getHashAlgorithmOrUnknown() + edgeName = "digest" and result = this.getHashAlgorithm() } } } diff --git a/cpp/ql/lib/experimental/Quantum/BaseBackup.qll b/cpp/ql/lib/experimental/Quantum/BaseBackup.qll new file mode 100644 index 000000000000..821c89eb8f57 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/BaseBackup.qll @@ -0,0 +1,125 @@ +/** + * A language-independent library for reasoning about cryptography. + */ + +import codeql.util.Location +import codeql.util.Option + +signature module InputSig { + class KnownUnknownLocation extends Location; + + class LocatableElement { + Location getLocation(); + } +} + +// An operation = a specific loc in code +// An algorithm +// Properties +// Node -> Operation -> Algorithm -> Symmetric -> SpecificSymmetricAlgo +// -[Language-Specific]-> LibrarySymmetricAlgo -> Properties +// For example (nsted newtypes): +/* + * newtype for each algo, and each one of those would have params for their properties + * implementation: optional/range for example + * + * + * + * /** + * Constructs an `Option` type that is a disjoint union of the given type and an + * additional singleton element. + */ + +module CryptographyBase Input> { + newtype TNode = + TNodeUnknown() or + TNodeAlgorithm() or + TNodeOperation() + + /* + * A cryptographic asset in code, i.e., an algorithm, operation, property, or known unknown. + */ + + abstract class Node extends TNode { + // this would then extend LanguageNode + abstract Location getLocation(); + + abstract string toString(); + + abstract Node getChild(int childIndex); + + final Node getAChild() { result = this.getChild(_) } + + final Node getAParent() { result.getAChild() = this } + } + + final class KnownUnknown extends Node, TNodeUnknown { + override string toString() { result = "unknown" } + + override Node getChild(int childIndex) { none() } + + override Location getLocation() { result instanceof Input::KnownUnknownLocation } + } + + abstract class Operation extends Node, TNodeOperation { + /** + * Gets the algorithm associated with this operation. + */ + abstract Node getAlgorithm(); + + /** + * Gets the name of this operation, e.g., "hash" or "encrypt". + */ + abstract string getOperationName(); + + final override Node getChild(int childIndex) { childIndex = 0 and result = this.getAlgorithm() } + + final override string toString() { result = this.getOperationName() } + } + + abstract class Algorithm extends Node, TNodeAlgorithm { + /** + * Gets the name of this algorithm, e.g., "AES" or "SHA". + */ + abstract string getAlgorithmName(); + } + + /** + * A hashing operation that processes data to generate a hash value. + * This operation takes an input message of arbitrary content and length and produces a fixed-size + * hash value as the output using a specified hashing algorithm. + */ + abstract class HashOperation extends Operation { + abstract override HashAlgorithm getAlgorithm(); + + override string getOperationName() { result = "hash" } + } + + /** + * A hashing algorithm that transforms variable-length input into a fixed-size hash value. + */ + abstract class HashAlgorithm extends Algorithm { } + + /** + * An operation that derives one or more keys from an input value. + */ + abstract class KeyDerivationOperation extends Operation { + override string getOperationName() { result = "key derivation" } + } + + /** + * An algorithm that derives one or more keys from an input value. + */ + abstract class KeyDerivationAlgorithm extends Algorithm { + abstract override string getAlgorithmName(); + } + + /** + * HKDF Extract+Expand key derivation function. + */ + abstract class HKDFAlgorithm extends KeyDerivationAlgorithm { + final override string getAlgorithmName() { result = "HKDF" } + + abstract Node getDigestAlgorithm(); + } +} diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll new file mode 100644 index 000000000000..108993fb134c --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/Language.qll @@ -0,0 +1,10 @@ +private import Base +private import cpp as Lang + +module CryptoInput implements InputSig { + class LocatableElement = Lang::Locatable; +} + +module Crypto = CryptographyBase; + +import OpenSSL diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll new file mode 100644 index 000000000000..b489a6630a0e --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll @@ -0,0 +1,100 @@ +import cpp +import semmle.code.cpp.dataflow.new.DataFlow + +module OpenSSLModel { + import Language + + abstract class KeyDerivationOperation extends Crypto::KeyDerivationOperation { } + + class SHA1Algo extends Crypto::SHA1 instanceof MacroAccess { + SHA1Algo() { this.getMacro().getName() = "SN_sha1" } + } + + module AlgorithmToEVPKeyDeriveConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr() instanceof KeyDerivationAlgorithm } + + predicate isSink(DataFlow::Node sink) { + exists(EVP_KDF_derive kdo | sink.asExpr() = kdo.getAlgorithmArg()) + } + } + + module AlgorithmToEVPKeyDeriveFlow = DataFlow::Global; + + predicate algorithm_to_EVP_KDF_derive(Crypto::Algorithm algo, EVP_KDF_derive derive) { + algo.(Expr).getEnclosingFunction() = derive.(Expr).getEnclosingFunction() + } + + class EVP_KDF_derive extends KeyDerivationOperation instanceof FunctionCall { + EVP_KDF_derive() { this.getTarget().getName() = "EVP_KDF_derive" } + + override Crypto::Algorithm getAlgorithm() { algorithm_to_EVP_KDF_derive(result, this) } + + Expr getAlgorithmArg() { result = this.(FunctionCall).getArgument(3) } + } + + abstract class KeyDerivationAlgorithm extends Crypto::KeyDerivationAlgorithm { } + + class EVP_KDF_fetch_Call extends FunctionCall { + EVP_KDF_fetch_Call() { this.getTarget().getName() = "EVP_KDF_fetch" } + + Expr getAlgorithmArg() { result = this.getArgument(1) } + } + + predicate kdf_names(string algo) { algo = ["HKDF", "PKCS12KDF"] } + + class KDFAlgorithmStringLiteral extends Crypto::NodeBase instanceof StringLiteral { + KDFAlgorithmStringLiteral() { kdf_names(this.getValue().toUpperCase()) } + + override string toString() { result = this.(StringLiteral).toString() } + + string getValue() { result = this.(StringLiteral).getValue() } + } + + private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof KDFAlgorithmStringLiteral } + + predicate isSink(DataFlow::Node sink) { + exists(EVP_KDF_fetch_Call call | sink.asExpr() = call.getAlgorithmArg()) + } + } + + module AlgorithmStringToFetchFlow = DataFlow::Global; + + predicate algorithmStringToKDFFetchArgFlow(string name, KDFAlgorithmStringLiteral origin, Expr arg) { + exists(EVP_KDF_fetch_Call sinkCall | + origin.getValue().toUpperCase() = name and + arg = sinkCall.getAlgorithmArg() and + AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), DataFlow::exprNode(arg)) + ) + } + + class HKDF extends KeyDerivationAlgorithm, Crypto::HKDF instanceof Expr { + KDFAlgorithmStringLiteral origin; + + HKDF() { algorithmStringToKDFFetchArgFlow("HKDF", origin, this) } + + override Crypto::HashAlgorithm getHashAlgorithm() { none() } + + override Crypto::NodeBase getOrigin() { result = origin } + } + + class TestKeyDerivationOperationHacky extends KeyDerivationOperation instanceof FunctionCall { + HKDF hkdf; + + TestKeyDerivationOperationHacky() { + this.getEnclosingFunction() = hkdf.(Expr).getEnclosingFunction() + } + + override Crypto::KeyDerivationAlgorithm getAlgorithm() { result = hkdf } + } + + class PKCS12KDF extends KeyDerivationAlgorithm, Crypto::PKCS12KDF instanceof Expr { + KDFAlgorithmStringLiteral origin; + + PKCS12KDF() { algorithmStringToKDFFetchArgFlow("PKCS12KDF", origin, this) } + + override Crypto::HashAlgorithm getHashAlgorithm() { none() } + + override Crypto::NodeBase getOrigin() { result = origin } + } +} diff --git a/cpp/ql/src/experimental/Quantum/Test.ql b/cpp/ql/src/experimental/Quantum/Test.ql new file mode 100644 index 000000000000..a9ad5021a295 --- /dev/null +++ b/cpp/ql/src/experimental/Quantum/Test.ql @@ -0,0 +1,17 @@ +/** + * @name "PQC Test" + * @kind graph + */ + +import experimental.Quantum.Language + +query predicate nodes(Crypto::NodeBase node) { any() } + +query predicate edges(Crypto::NodeBase source, Crypto::NodeBase target, string key, string value) { + target = source.getChild(value) and + key = "semmle.label" +} + +query predicate graphProperties(string key, string value) { + key = "semmle.graphKind" and value = "tree" +} diff --git a/cpp/ql/src/experimental/Quantum/Test2.ql b/cpp/ql/src/experimental/Quantum/Test2.ql new file mode 100644 index 000000000000..f5971da96443 --- /dev/null +++ b/cpp/ql/src/experimental/Quantum/Test2.ql @@ -0,0 +1,8 @@ +/** + * @name "PQC Test" + */ + +import experimental.Quantum.Language + +from Crypto::KeyDerivationAlgorithm n +select n From 78362341fff9adb73deaf5a3a3f85f1da66481b0 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Fri, 24 Jan 2025 22:32:32 +0100 Subject: [PATCH 004/336] WIP: hash types example and documentation --- cpp/ql/lib/experimental/Quantum/Base.qll | 38 ++++++++++++++++++--- cpp/ql/lib/experimental/Quantum/OpenSSL.qll | 4 ++- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/Base.qll b/cpp/ql/lib/experimental/Quantum/Base.qll index 8a910eb44143..22e810f4aff4 100644 --- a/cpp/ql/lib/experimental/Quantum/Base.qll +++ b/cpp/ql/lib/experimental/Quantum/Base.qll @@ -64,7 +64,7 @@ module CryptographyBase Input> { override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) or - edgeName = "algorithm" and + edgeName = "uses" and if exists(this.getAlgorithm()) then result = this.getAlgorithm() else result = this } } @@ -89,13 +89,43 @@ module CryptographyBase Input> { override string getOperationName() { result = "hash" } } + // Rule: no newtype representing a type of algorithm should be modelled with multiple interfaces + // + // Example: HKDF and PKCS12KDF are both key derivation algorithms. + // However, PKCS12KDF also has a property: the iteration count. + // + // If we have HKDF and PKCS12KDF under TKeyDerivationType, + // someone modelling a library might try to make a generic identification of both of those algorithms. + // + // They will therefore not use the specialized type for PKCS12KDF, + // meaning "from PKCS12KDF algo select algo" will have no results. + // + newtype THashType = + // We're saying by this that all of these have an identical interface / properties / edges + MD5() or + SHA1() or + SHA256() or + SHA512() + + class HashAlgorithmType extends THashType { + string toString() { hashTypeToNameMapping(this, result) } + } + + predicate hashTypeToNameMapping(THashType type, string name) { + type instanceof SHA1 and name = "SHA-1" + or + type instanceof SHA256 and name = "SHA-256" + or + type instanceof SHA512 and name = "SHA-512" + } + /** * A hashing algorithm that transforms variable-length input into a fixed-size hash value. */ - abstract class HashAlgorithm extends Algorithm { } + abstract class HashAlgorithm extends Algorithm { + abstract HashAlgorithmType getHashType(); - abstract class SHA1 extends HashAlgorithm { - override string getAlgorithmName() { result = "SHA1" } + override string getAlgorithmName() { hashTypeToNameMapping(this.getHashType(), result) } } /** diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll index b489a6630a0e..17de5ddab604 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll @@ -6,8 +6,10 @@ module OpenSSLModel { abstract class KeyDerivationOperation extends Crypto::KeyDerivationOperation { } - class SHA1Algo extends Crypto::SHA1 instanceof MacroAccess { + class SHA1Algo extends Crypto::HashAlgorithm instanceof MacroAccess { SHA1Algo() { this.getMacro().getName() = "SN_sha1" } + + override Crypto::HashAlgorithmType getHashType() { result instanceof Crypto::SHA1 } } module AlgorithmToEVPKeyDeriveConfig implements DataFlow::ConfigSig { From e027b0e9a0e56f21226d832bcd87751a8c0ee47f Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Tue, 28 Jan 2025 02:02:06 +0100 Subject: [PATCH 005/336] WIP: add properties --- cpp/ql/lib/experimental/Quantum/Base.qll | 95 +++++++++++++++----- cpp/ql/lib/experimental/Quantum/Language.qll | 2 + cpp/ql/lib/experimental/Quantum/OpenSSL.qll | 12 ++- cpp/ql/src/experimental/Quantum/Test.ql | 28 +++++- cpp/ql/src/experimental/Quantum/Test2.ql | 4 +- 5 files changed, 114 insertions(+), 27 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/Base.qll b/cpp/ql/lib/experimental/Quantum/Base.qll index 22e810f4aff4..b3f4d619f4d8 100644 --- a/cpp/ql/lib/experimental/Quantum/Base.qll +++ b/cpp/ql/lib/experimental/Quantum/Base.qll @@ -9,11 +9,19 @@ signature module InputSig { class LocatableElement { Location getLocation(); } + + class UnknownLocation instanceof Location; } module CryptographyBase Input> { final class LocatableElement = Input::LocatableElement; + final class UnknownLocation = Input::UnknownLocation; + + final class UnknownPropertyValue extends string { + UnknownPropertyValue() { this = "" } + } + abstract class NodeBase instanceof LocatableElement { /** * Returns a string representation of this node, usually the name of the operation/algorithm/property. @@ -25,17 +33,26 @@ module CryptographyBase Input> { */ Location getLocation() { result = super.getLocation() } + /** + * Gets the origin of this node, e.g., a string literal in source describing it. + */ + LocatableElement getOrigin(string value) { none() } + /** * Returns the child of this node with the given edge name. * * This predicate is used by derived classes to construct the graph of cryptographic operations. */ - NodeBase getChild(string edgeName) { edgeName = "origin" and result = this.getOrigin() } + NodeBase getChild(string edgeName) { none() } /** - * Gets the origin of this node, e.g., a string literal in source describing it. + * Defines properties of this node by name and either a value or location or both. + * + * This predicate is used by derived classes to construct the graph of cryptographic operations. */ - NodeBase getOrigin() { none() } + predicate properties(string key, string value, Location location) { + key = "origin" and location = this.getOrigin(value).getLocation() + } /** * Returns the parent of this node. @@ -86,7 +103,7 @@ module CryptographyBase Input> { abstract class HashOperation extends Operation { abstract override HashAlgorithm getAlgorithm(); - override string getOperationName() { result = "hash" } + override string getOperationName() { result = "HASH" } } // Rule: no newtype representing a type of algorithm should be modelled with multiple interfaces @@ -105,34 +122,40 @@ module CryptographyBase Input> { MD5() or SHA1() or SHA256() or - SHA512() - - class HashAlgorithmType extends THashType { - string toString() { hashTypeToNameMapping(this, result) } - } - - predicate hashTypeToNameMapping(THashType type, string name) { - type instanceof SHA1 and name = "SHA-1" - or - type instanceof SHA256 and name = "SHA-256" - or - type instanceof SHA512 and name = "SHA-512" - } + SHA512() or + OtherHashType() /** * A hashing algorithm that transforms variable-length input into a fixed-size hash value. */ abstract class HashAlgorithm extends Algorithm { - abstract HashAlgorithmType getHashType(); + final predicate hashTypeToNameMapping(THashType type, string name) { + type instanceof MD5 and name = "MD5" + or + type instanceof SHA1 and name = "SHA-1" + or + type instanceof SHA256 and name = "SHA-256" + or + type instanceof SHA512 and name = "SHA-512" + or + type instanceof OtherHashType and name = this.getRawAlgorithmName() + } + + abstract THashType getHashType(); + + override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashType(), result) } - override string getAlgorithmName() { hashTypeToNameMapping(this.getHashType(), result) } + /** + * Gets the raw name of this hash algorithm from source. + */ + abstract string getRawAlgorithmName(); } /** * An operation that derives one or more keys from an input value. */ abstract class KeyDerivationOperation extends Operation { - override string getOperationName() { result = "key derivation" } + override string getOperationName() { result = "KEY_DERIVATION" } } /** @@ -143,7 +166,7 @@ module CryptographyBase Input> { } /** - * HKDF Extract+Expand key derivation function. + * HKDF key derivation function */ abstract class HKDF extends KeyDerivationAlgorithm { final override string getAlgorithmName() { result = "HKDF" } @@ -157,6 +180,9 @@ module CryptographyBase Input> { } } + /** + * PKCS #12 key derivation function + */ abstract class PKCS12KDF extends KeyDerivationAlgorithm { final override string getAlgorithmName() { result = "PKCS12KDF" } @@ -168,4 +194,31 @@ module CryptographyBase Input> { edgeName = "digest" and result = this.getHashAlgorithm() } } + + /** + * Elliptic curve algorithm + */ + abstract class EllipticCurve extends Algorithm { + abstract string getVersion(Location location); + + abstract string getKeySize(Location location); + + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + key = "version" and + if exists(this.getVersion(location)) + then value = this.getVersion(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + or + key = "key_size" and + if exists(this.getKeySize(location)) + then value = this.getKeySize(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + } + } } diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index 108993fb134c..c9398c9e3245 100644 --- a/cpp/ql/lib/experimental/Quantum/Language.qll +++ b/cpp/ql/lib/experimental/Quantum/Language.qll @@ -3,6 +3,8 @@ private import cpp as Lang module CryptoInput implements InputSig { class LocatableElement = Lang::Locatable; + + class UnknownLocation = Lang::UnknownDefaultLocation; } module Crypto = CryptographyBase; diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll index 17de5ddab604..852fedf646a8 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll @@ -9,7 +9,9 @@ module OpenSSLModel { class SHA1Algo extends Crypto::HashAlgorithm instanceof MacroAccess { SHA1Algo() { this.getMacro().getName() = "SN_sha1" } - override Crypto::HashAlgorithmType getHashType() { result instanceof Crypto::SHA1 } + override string getRawAlgorithmName() { result = "SN_sha1" } + + override Crypto::THashType getHashType() { result instanceof Crypto::SHA1 } } module AlgorithmToEVPKeyDeriveConfig implements DataFlow::ConfigSig { @@ -77,7 +79,9 @@ module OpenSSLModel { override Crypto::HashAlgorithm getHashAlgorithm() { none() } - override Crypto::NodeBase getOrigin() { result = origin } + override Crypto::LocatableElement getOrigin(string name) { + result = origin and name = origin.toString() + } } class TestKeyDerivationOperationHacky extends KeyDerivationOperation instanceof FunctionCall { @@ -97,6 +101,8 @@ module OpenSSLModel { override Crypto::HashAlgorithm getHashAlgorithm() { none() } - override Crypto::NodeBase getOrigin() { result = origin } + override Crypto::NodeBase getOrigin(string name) { + result = origin and name = origin.toString() + } } } diff --git a/cpp/ql/src/experimental/Quantum/Test.ql b/cpp/ql/src/experimental/Quantum/Test.ql index a9ad5021a295..87341a6b612c 100644 --- a/cpp/ql/src/experimental/Quantum/Test.ql +++ b/cpp/ql/src/experimental/Quantum/Test.ql @@ -5,7 +5,33 @@ import experimental.Quantum.Language -query predicate nodes(Crypto::NodeBase node) { any() } +string getValueAndLocationPairs(Crypto::NodeBase node, string key) { + exists(string value, Location location | + node.properties(key, value, location) and + result = "(" + value + "," + location.toString() + ")" + ) +} + +string properties(Crypto::NodeBase node) { + forex(string key | node.properties(key, _, _) | + result = key + ":" + strictconcat(getValueAndLocationPairs(node, key), ",") + ) +} + +string getLabel(Crypto::NodeBase node) { + result = + "[" + node.toString() + "]" + + any(string prop | + if exists(properties(node)) then prop = " " + properties(node) else prop = "" + | + prop + ) +} + +query predicate nodes(Crypto::NodeBase node, string key, string value) { + key = "semmle.label" and + value = getLabel(node) +} query predicate edges(Crypto::NodeBase source, Crypto::NodeBase target, string key, string value) { target = source.getChild(value) and diff --git a/cpp/ql/src/experimental/Quantum/Test2.ql b/cpp/ql/src/experimental/Quantum/Test2.ql index f5971da96443..3f48f156a430 100644 --- a/cpp/ql/src/experimental/Quantum/Test2.ql +++ b/cpp/ql/src/experimental/Quantum/Test2.ql @@ -4,5 +4,5 @@ import experimental.Quantum.Language -from Crypto::KeyDerivationAlgorithm n -select n +from Crypto::NodeBase node +select node From 0cd3df9d2685d9aef55b2305c2ef2d478d3e1223 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Wed, 29 Jan 2025 10:27:46 -0500 Subject: [PATCH 006/336] Concepts for elliptic cureve and misc. updates. --- cpp/ql/lib/experimental/Quantum/Base.qll | 50 +++- python/ql/lib/experimental/Quantum/Base.qll | 250 ++++++++++++++++++ .../ql/lib/experimental/Quantum/Language.qll | 12 + .../experimental/Quantum/PycaCryptography.qll | 55 ++++ python/ql/lib/semmle/python/Files.qll | 37 +++ 5 files changed, 392 insertions(+), 12 deletions(-) create mode 100644 python/ql/lib/experimental/Quantum/Base.qll create mode 100644 python/ql/lib/experimental/Quantum/Language.qll create mode 100644 python/ql/lib/experimental/Quantum/PycaCryptography.qll diff --git a/cpp/ql/lib/experimental/Quantum/Base.qll b/cpp/ql/lib/experimental/Quantum/Base.qll index b3f4d619f4d8..9be24ca6efaa 100644 --- a/cpp/ql/lib/experimental/Quantum/Base.qll +++ b/cpp/ql/lib/experimental/Quantum/Base.qll @@ -92,6 +92,11 @@ module CryptographyBase Input> { */ abstract string getAlgorithmName(); + /** + * Gets the raw name of this algorithm from source (no parsing or formatting) + */ + abstract string getRawAlgorithmName(); + final override string toString() { result = this.getAlgorithmName() } } @@ -145,10 +150,6 @@ module CryptographyBase Input> { override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashType(), result) } - /** - * Gets the raw name of this hash algorithm from source. - */ - abstract string getRawAlgorithmName(); } /** @@ -195,30 +196,55 @@ module CryptographyBase Input> { } } + newtype TEllipticCurveFamilyType = + // We're saying by this that all of these have an identical interface / properties / edges + NIST() or + SEC() or + NUMS() or + PRIME() or + BRAINPOOL() or + CURVE25519() or + CURVE448() or + C2() or + SM2() or + ES() or + OtherEllipticCurveFamilyType() + + /** * Elliptic curve algorithm */ abstract class EllipticCurve extends Algorithm { - abstract string getVersion(Location location); + abstract string getKeySize(Location location); + abstract TEllipticCurveFamilyType getCurveFamilyType(); + override predicate properties(string key, string value, Location location) { super.properties(key, value, location) or - key = "version" and - if exists(this.getVersion(location)) - then value = this.getVersion(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - or key = "key_size" and if exists(this.getKeySize(location)) then value = this.getKeySize(location) else ( value instanceof UnknownPropertyValue and location instanceof UnknownLocation ) + // other properties, like field type are possible, but not modeled until considered necessary } + + override string getAlgorithmName() { result = this.getRawAlgorithmName().toUpperCase()} + + /** + * Mandating that for Elliptic Curves specifically, users are responsible + * for providing as the 'raw' name, the official name of the algorithm. + * Casing doesn't matter, we will enforce further naming restrictions on + * `getAlgorithmName` by default. + * Rationale: elliptic curve names can have a lot of variation in their components + * (e.g., "secp256r1" vs "P-256"), trying to produce generalized set of properties + * is possible to capture all cases, but such modeling is likely not necessary. + * if all properties need to be captured, we can reassess how names are generated. + */ + override abstract string getRawAlgorithmName(); } } diff --git a/python/ql/lib/experimental/Quantum/Base.qll b/python/ql/lib/experimental/Quantum/Base.qll new file mode 100644 index 000000000000..9be24ca6efaa --- /dev/null +++ b/python/ql/lib/experimental/Quantum/Base.qll @@ -0,0 +1,250 @@ +/** + * A language-independent library for reasoning about cryptography. + */ + +import codeql.util.Location +import codeql.util.Option + +signature module InputSig { + class LocatableElement { + Location getLocation(); + } + + class UnknownLocation instanceof Location; +} + +module CryptographyBase Input> { + final class LocatableElement = Input::LocatableElement; + + final class UnknownLocation = Input::UnknownLocation; + + final class UnknownPropertyValue extends string { + UnknownPropertyValue() { this = "" } + } + + abstract class NodeBase instanceof LocatableElement { + /** + * Returns a string representation of this node, usually the name of the operation/algorithm/property. + */ + abstract string toString(); + + /** + * Returns the location of this node in the code. + */ + Location getLocation() { result = super.getLocation() } + + /** + * Gets the origin of this node, e.g., a string literal in source describing it. + */ + LocatableElement getOrigin(string value) { none() } + + /** + * Returns the child of this node with the given edge name. + * + * This predicate is used by derived classes to construct the graph of cryptographic operations. + */ + NodeBase getChild(string edgeName) { none() } + + /** + * Defines properties of this node by name and either a value or location or both. + * + * This predicate is used by derived classes to construct the graph of cryptographic operations. + */ + predicate properties(string key, string value, Location location) { + key = "origin" and location = this.getOrigin(value).getLocation() + } + + /** + * Returns the parent of this node. + */ + final NodeBase getAParent() { result.getChild(_) = this } + } + + class Asset = NodeBase; + + /** + * A cryptographic operation, such as hashing or encryption. + */ + abstract class Operation extends Asset { + /** + * Gets the algorithm associated with this operation. + */ + abstract Algorithm getAlgorithm(); + + /** + * Gets the name of this operation, e.g., "hash" or "encrypt". + */ + abstract string getOperationName(); + + final override string toString() { result = this.getOperationName() } + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + edgeName = "uses" and + if exists(this.getAlgorithm()) then result = this.getAlgorithm() else result = this + } + } + + abstract class Algorithm extends Asset { + /** + * Gets the name of this algorithm, e.g., "AES" or "SHA". + */ + abstract string getAlgorithmName(); + + /** + * Gets the raw name of this algorithm from source (no parsing or formatting) + */ + abstract string getRawAlgorithmName(); + + final override string toString() { result = this.getAlgorithmName() } + } + + /** + * A hashing operation that processes data to generate a hash value. + * This operation takes an input message of arbitrary content and length and produces a fixed-size + * hash value as the output using a specified hashing algorithm. + */ + abstract class HashOperation extends Operation { + abstract override HashAlgorithm getAlgorithm(); + + override string getOperationName() { result = "HASH" } + } + + // Rule: no newtype representing a type of algorithm should be modelled with multiple interfaces + // + // Example: HKDF and PKCS12KDF are both key derivation algorithms. + // However, PKCS12KDF also has a property: the iteration count. + // + // If we have HKDF and PKCS12KDF under TKeyDerivationType, + // someone modelling a library might try to make a generic identification of both of those algorithms. + // + // They will therefore not use the specialized type for PKCS12KDF, + // meaning "from PKCS12KDF algo select algo" will have no results. + // + newtype THashType = + // We're saying by this that all of these have an identical interface / properties / edges + MD5() or + SHA1() or + SHA256() or + SHA512() or + OtherHashType() + + /** + * A hashing algorithm that transforms variable-length input into a fixed-size hash value. + */ + abstract class HashAlgorithm extends Algorithm { + final predicate hashTypeToNameMapping(THashType type, string name) { + type instanceof MD5 and name = "MD5" + or + type instanceof SHA1 and name = "SHA-1" + or + type instanceof SHA256 and name = "SHA-256" + or + type instanceof SHA512 and name = "SHA-512" + or + type instanceof OtherHashType and name = this.getRawAlgorithmName() + } + + abstract THashType getHashType(); + + override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashType(), result) } + + } + + /** + * An operation that derives one or more keys from an input value. + */ + abstract class KeyDerivationOperation extends Operation { + override string getOperationName() { result = "KEY_DERIVATION" } + } + + /** + * An algorithm that derives one or more keys from an input value. + */ + abstract class KeyDerivationAlgorithm extends Algorithm { + abstract override string getAlgorithmName(); + } + + /** + * HKDF key derivation function + */ + abstract class HKDF extends KeyDerivationAlgorithm { + final override string getAlgorithmName() { result = "HKDF" } + + abstract HashAlgorithm getHashAlgorithm(); + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + edgeName = "digest" and result = this.getHashAlgorithm() + } + } + + /** + * PKCS #12 key derivation function + */ + abstract class PKCS12KDF extends KeyDerivationAlgorithm { + final override string getAlgorithmName() { result = "PKCS12KDF" } + + abstract HashAlgorithm getHashAlgorithm(); + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + edgeName = "digest" and result = this.getHashAlgorithm() + } + } + + newtype TEllipticCurveFamilyType = + // We're saying by this that all of these have an identical interface / properties / edges + NIST() or + SEC() or + NUMS() or + PRIME() or + BRAINPOOL() or + CURVE25519() or + CURVE448() or + C2() or + SM2() or + ES() or + OtherEllipticCurveFamilyType() + + + /** + * Elliptic curve algorithm + */ + abstract class EllipticCurve extends Algorithm { + + + abstract string getKeySize(Location location); + + abstract TEllipticCurveFamilyType getCurveFamilyType(); + + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + key = "key_size" and + if exists(this.getKeySize(location)) + then value = this.getKeySize(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + // other properties, like field type are possible, but not modeled until considered necessary + } + + override string getAlgorithmName() { result = this.getRawAlgorithmName().toUpperCase()} + + /** + * Mandating that for Elliptic Curves specifically, users are responsible + * for providing as the 'raw' name, the official name of the algorithm. + * Casing doesn't matter, we will enforce further naming restrictions on + * `getAlgorithmName` by default. + * Rationale: elliptic curve names can have a lot of variation in their components + * (e.g., "secp256r1" vs "P-256"), trying to produce generalized set of properties + * is possible to capture all cases, but such modeling is likely not necessary. + * if all properties need to be captured, we can reassess how names are generated. + */ + override abstract string getRawAlgorithmName(); + } +} diff --git a/python/ql/lib/experimental/Quantum/Language.qll b/python/ql/lib/experimental/Quantum/Language.qll new file mode 100644 index 000000000000..9abf3e7fa7e4 --- /dev/null +++ b/python/ql/lib/experimental/Quantum/Language.qll @@ -0,0 +1,12 @@ +private import Base +private import python as Lang + +module CryptoInput implements InputSig { + class LocatableElement = Lang::Expr; + + class UnknownLocation = Lang::UnknownDefaultLocation; +} + +module Crypto = CryptographyBase; + +import PycaCryptography diff --git a/python/ql/lib/experimental/Quantum/PycaCryptography.qll b/python/ql/lib/experimental/Quantum/PycaCryptography.qll new file mode 100644 index 000000000000..802ad23cf9d9 --- /dev/null +++ b/python/ql/lib/experimental/Quantum/PycaCryptography.qll @@ -0,0 +1,55 @@ +import python +import semmle.python.ApiGraphs + +module PycaCryptographyModule { + import Language + + /** + * Gets a predefined curve class constructor call from + * `cryptography.hazmat.primitives.asymmetric.ec` + * https://cryptography.io/en/latest/hazmat/primitives/asymmetric/ec/#elliptic-curves + */ + DataFlow::Node predefinedCurveClass(string rawName, string curveName, Crypto::TEllipticCurveFamilyType family, int keySize) { + // getACall since the typical case is to construct the curve with initialization values, + // not to pass the mode uninitialized + result = + API::moduleImport("cryptography") + .getMember("hazmat") + .getMember("primitives") + .getMember("asymmetric") + .getMember("ec") + .getMember(rawName) + .getACall() + and + curveName = rawName.toUpperCase() + and + curveName.matches("SEC%") and family instanceof Crypto::SEC + and + curveName.matches("BRAINPOOL%") and family instanceof Crypto::BRAINPOOL + and + // Enumerating all key sizes known in the API + // TODO: should we dynamically extract them through a regex? + keySize in [160, 163, 192, 224, 233, 256, 283, 320, 384, 409, 512, 571] + and + curveName.matches("%" + keySize + "%") + } + + + class EllipticCurve extends Crypto::EllipticCurve instanceof Expr{ + int keySize; + string rawName; + string curveName; + Crypto::TEllipticCurveFamilyType family; + EllipticCurve() { + this = predefinedCurveClass(rawName, curveName, family, keySize).asExpr() + } + + override string getRawAlgorithmName() { result = rawName } + override string getAlgorithmName() { result = curveName } + Crypto::TEllipticCurveFamilyType getFamily() { result = family } + + override string getKeySize(Location location) { + location = this and + result = keySize.toString() } + } +} diff --git a/python/ql/lib/semmle/python/Files.qll b/python/ql/lib/semmle/python/Files.qll index 2da0dd61f885..67f21ad0b249 100644 --- a/python/ql/lib/semmle/python/Files.qll +++ b/python/ql/lib/semmle/python/Files.qll @@ -368,3 +368,40 @@ class EncodingError extends SyntaxError { override string toString() { result = "Encoding Error" } } + + + +/** + * A dummy location which is used when something doesn't have a location in + * the source code but needs to have a `Location` associated with it. There + * may be several distinct kinds of unknown locations. For example: one for + * expressions, one for statements and one for other program elements. + */ +class UnknownLocation extends Location { + UnknownLocation() { this.getFile().getAbsolutePath() = "" } +} + +/** + * A dummy location which is used when something doesn't have a location in + * the source code but needs to have a `Location` associated with it. + */ +class UnknownDefaultLocation extends UnknownLocation { + UnknownDefaultLocation() { locations_default(this, _, 0, 0, 0, 0) } +} + +/** + * A dummy location which is used when an expression doesn't have a + * location in the source code but needs to have a `Location` associated + * with it. + */ +class UnknownExprLocation extends UnknownLocation { + UnknownExprLocation() { locations_default(this, _, 0, 0, 0, 0) } +} + +/** + * A dummy location which is used when a statement doesn't have a location + * in the source code but needs to have a `Location` associated with it. + */ +class UnknownStmtLocation extends UnknownLocation { + UnknownStmtLocation() { locations_default(this, _, 0, 0, 0, 0) } +} From 9af18bc1002e4b32b18a8f56d2fbf9c2ffa7405f Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Wed, 29 Jan 2025 19:45:04 +0100 Subject: [PATCH 007/336] WIP: add dgml/dot output/remove test code --- cpp/ql/lib/experimental/Quantum/Base.qll | 4 +- .../lib/experimental/Quantum/BaseBackup.qll | 125 ------------------ cpp/ql/lib/experimental/Quantum/OpenSSL.qll | 10 -- cpp/ql/src/experimental/Quantum/CBOMGraph.ql | 47 +++++++ cpp/ql/src/experimental/Quantum/Test.ql | 43 ------ cpp/ql/src/experimental/Quantum/cbom.sh | 8 ++ .../src/experimental/Quantum/generate_cbom.py | 104 +++++++++++++++ 7 files changed, 162 insertions(+), 179 deletions(-) delete mode 100644 cpp/ql/lib/experimental/Quantum/BaseBackup.qll create mode 100644 cpp/ql/src/experimental/Quantum/CBOMGraph.ql delete mode 100644 cpp/ql/src/experimental/Quantum/Test.ql create mode 100755 cpp/ql/src/experimental/Quantum/cbom.sh create mode 100644 cpp/ql/src/experimental/Quantum/generate_cbom.py diff --git a/cpp/ql/lib/experimental/Quantum/Base.qll b/cpp/ql/lib/experimental/Quantum/Base.qll index b3f4d619f4d8..cb0f53f468e7 100644 --- a/cpp/ql/lib/experimental/Quantum/Base.qll +++ b/cpp/ql/lib/experimental/Quantum/Base.qll @@ -51,7 +51,9 @@ module CryptographyBase Input> { * This predicate is used by derived classes to construct the graph of cryptographic operations. */ predicate properties(string key, string value, Location location) { - key = "origin" and location = this.getOrigin(value).getLocation() + key = "origin" and + location = this.getOrigin(value).getLocation() and + not location = this.getLocation() } /** diff --git a/cpp/ql/lib/experimental/Quantum/BaseBackup.qll b/cpp/ql/lib/experimental/Quantum/BaseBackup.qll deleted file mode 100644 index 821c89eb8f57..000000000000 --- a/cpp/ql/lib/experimental/Quantum/BaseBackup.qll +++ /dev/null @@ -1,125 +0,0 @@ -/** - * A language-independent library for reasoning about cryptography. - */ - -import codeql.util.Location -import codeql.util.Option - -signature module InputSig { - class KnownUnknownLocation extends Location; - - class LocatableElement { - Location getLocation(); - } -} - -// An operation = a specific loc in code -// An algorithm -// Properties -// Node -> Operation -> Algorithm -> Symmetric -> SpecificSymmetricAlgo -// -[Language-Specific]-> LibrarySymmetricAlgo -> Properties -// For example (nsted newtypes): -/* - * newtype for each algo, and each one of those would have params for their properties - * implementation: optional/range for example - * - * - * - * /** - * Constructs an `Option` type that is a disjoint union of the given type and an - * additional singleton element. - */ - -module CryptographyBase Input> { - newtype TNode = - TNodeUnknown() or - TNodeAlgorithm() or - TNodeOperation() - - /* - * A cryptographic asset in code, i.e., an algorithm, operation, property, or known unknown. - */ - - abstract class Node extends TNode { - // this would then extend LanguageNode - abstract Location getLocation(); - - abstract string toString(); - - abstract Node getChild(int childIndex); - - final Node getAChild() { result = this.getChild(_) } - - final Node getAParent() { result.getAChild() = this } - } - - final class KnownUnknown extends Node, TNodeUnknown { - override string toString() { result = "unknown" } - - override Node getChild(int childIndex) { none() } - - override Location getLocation() { result instanceof Input::KnownUnknownLocation } - } - - abstract class Operation extends Node, TNodeOperation { - /** - * Gets the algorithm associated with this operation. - */ - abstract Node getAlgorithm(); - - /** - * Gets the name of this operation, e.g., "hash" or "encrypt". - */ - abstract string getOperationName(); - - final override Node getChild(int childIndex) { childIndex = 0 and result = this.getAlgorithm() } - - final override string toString() { result = this.getOperationName() } - } - - abstract class Algorithm extends Node, TNodeAlgorithm { - /** - * Gets the name of this algorithm, e.g., "AES" or "SHA". - */ - abstract string getAlgorithmName(); - } - - /** - * A hashing operation that processes data to generate a hash value. - * This operation takes an input message of arbitrary content and length and produces a fixed-size - * hash value as the output using a specified hashing algorithm. - */ - abstract class HashOperation extends Operation { - abstract override HashAlgorithm getAlgorithm(); - - override string getOperationName() { result = "hash" } - } - - /** - * A hashing algorithm that transforms variable-length input into a fixed-size hash value. - */ - abstract class HashAlgorithm extends Algorithm { } - - /** - * An operation that derives one or more keys from an input value. - */ - abstract class KeyDerivationOperation extends Operation { - override string getOperationName() { result = "key derivation" } - } - - /** - * An algorithm that derives one or more keys from an input value. - */ - abstract class KeyDerivationAlgorithm extends Algorithm { - abstract override string getAlgorithmName(); - } - - /** - * HKDF Extract+Expand key derivation function. - */ - abstract class HKDFAlgorithm extends KeyDerivationAlgorithm { - final override string getAlgorithmName() { result = "HKDF" } - - abstract Node getDigestAlgorithm(); - } -} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll index 852fedf646a8..18feda6c8c6c 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll @@ -84,16 +84,6 @@ module OpenSSLModel { } } - class TestKeyDerivationOperationHacky extends KeyDerivationOperation instanceof FunctionCall { - HKDF hkdf; - - TestKeyDerivationOperationHacky() { - this.getEnclosingFunction() = hkdf.(Expr).getEnclosingFunction() - } - - override Crypto::KeyDerivationAlgorithm getAlgorithm() { result = hkdf } - } - class PKCS12KDF extends KeyDerivationAlgorithm, Crypto::PKCS12KDF instanceof Expr { KDFAlgorithmStringLiteral origin; diff --git a/cpp/ql/src/experimental/Quantum/CBOMGraph.ql b/cpp/ql/src/experimental/Quantum/CBOMGraph.ql new file mode 100644 index 000000000000..1df6611aab9a --- /dev/null +++ b/cpp/ql/src/experimental/Quantum/CBOMGraph.ql @@ -0,0 +1,47 @@ +/** + * @name "Outputs a graph representation of the cryptographic bill of materials." + * @kind graph + * @id cbomgraph + */ + +import experimental.Quantum.Language + +string getPropertyString(Crypto::NodeBase node, string key) { + result = + strictconcat(any(string value, Location location, string parsed | + node.properties(key, value, location) and + parsed = "(" + value + "," + location.toString() + ")" + | + parsed + ), "," + ) +} + +string getLabel(Crypto::NodeBase node) { result = node.toString() } + +query predicate nodes(Crypto::NodeBase node, string key, string value) { + key = "semmle.label" and + value = getLabel(node) + or + // CodeQL's DGML output does not include a location + key = "Location" and + value = node.getLocation().toString() + or + // Known unknown edges should be reported as properties rather than edges + node = node.getChild(key) and + value = "" + or + // Report properties + value = getPropertyString(node, key) +} + +query predicate edges(Crypto::NodeBase source, Crypto::NodeBase target, string key, string value) { + key = "semmle.label" and + target = source.getChild(value) and + // Known unknowns are reported as properties rather than edges + not source = target +} + +query predicate graphProperties(string key, string value) { + key = "semmle.graphKind" and value = "graph" +} diff --git a/cpp/ql/src/experimental/Quantum/Test.ql b/cpp/ql/src/experimental/Quantum/Test.ql deleted file mode 100644 index 87341a6b612c..000000000000 --- a/cpp/ql/src/experimental/Quantum/Test.ql +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @name "PQC Test" - * @kind graph - */ - -import experimental.Quantum.Language - -string getValueAndLocationPairs(Crypto::NodeBase node, string key) { - exists(string value, Location location | - node.properties(key, value, location) and - result = "(" + value + "," + location.toString() + ")" - ) -} - -string properties(Crypto::NodeBase node) { - forex(string key | node.properties(key, _, _) | - result = key + ":" + strictconcat(getValueAndLocationPairs(node, key), ",") - ) -} - -string getLabel(Crypto::NodeBase node) { - result = - "[" + node.toString() + "]" + - any(string prop | - if exists(properties(node)) then prop = " " + properties(node) else prop = "" - | - prop - ) -} - -query predicate nodes(Crypto::NodeBase node, string key, string value) { - key = "semmle.label" and - value = getLabel(node) -} - -query predicate edges(Crypto::NodeBase source, Crypto::NodeBase target, string key, string value) { - target = source.getChild(value) and - key = "semmle.label" -} - -query predicate graphProperties(string key, string value) { - key = "semmle.graphKind" and value = "tree" -} diff --git a/cpp/ql/src/experimental/Quantum/cbom.sh b/cpp/ql/src/experimental/Quantum/cbom.sh new file mode 100755 index 000000000000..df1c58b1efb8 --- /dev/null +++ b/cpp/ql/src/experimental/Quantum/cbom.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +CODEQL_PATH="/Users/nicolaswill/Library/Application Support/Code/User/globalStorage/github.vscode-codeql/distribution5/codeql/codeql" +DATABASE_PATH="/Users/nicolaswill/openssl_codeql/openssl/openssl_db" +QUERY_FILE="CBOMGraph.ql" +OUTPUT_DIR="graph_output" + +python3 generate_cbom.py -c "$CODEQL_PATH" -d "$DATABASE_PATH" -q "$QUERY_FILE" -o "$OUTPUT_DIR" diff --git a/cpp/ql/src/experimental/Quantum/generate_cbom.py b/cpp/ql/src/experimental/Quantum/generate_cbom.py new file mode 100644 index 000000000000..10ec895dc629 --- /dev/null +++ b/cpp/ql/src/experimental/Quantum/generate_cbom.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 + +import os +import sys +import argparse +import subprocess +import xml.etree.ElementTree as ET + +def run_codeql_analysis(codeql_path, database_path, query_path, output_dir): + """Runs the CodeQL analysis and generates a DGML file.""" + os.makedirs(output_dir, exist_ok=True) + command = [ + codeql_path, "database", "analyze", database_path, query_path, + "--rerun", "--format=dgml", "--output", output_dir + ] + + print(f"Running CodeQL analysis: {' '.join(command)}") + result = subprocess.run(command, capture_output=True, text=True) + + if result.returncode == 0: + print("Analysis completed successfully.") + else: + print("Analysis failed.") + print(result.stderr) + sys.exit(1) + + return result.returncode + + +def convert_dgml_to_dot(dgml_file, dot_file): + """Converts the DGML file to DOT format using the exact original implementation.""" + print(f"Processing DGML file: {dgml_file}") + + # Read source DGML + with open(dgml_file, "r", encoding="utf-8") as f: + xml_content = f.read() + + root = ET.fromstring(xml_content) + + # Form dot element sequence + body_l = ["digraph cbom {", + "node [shape=box];", + "rankdir=LR;" + ] + + # Process nodes + for node in root.find("{http://schemas.microsoft.com/vs/2009/dgml}Nodes"): + att = node.attrib + node_id = att['Id'] + label_parts = [] + for key, value in att.items(): + if key == 'Id': + continue + elif key == 'Label': + label_parts.append(value) + else: + label_parts.append(f"{key}={value}") + label = "\\n".join(label_parts) + prop_l = [f'label="{label}"'] + node_s = f'nd_{node_id} [{", ".join(prop_l)}];' + body_l.append(node_s) + + # Process edges + for edge in root.find("{http://schemas.microsoft.com/vs/2009/dgml}Links"): + att = edge.attrib + edge_s = 'nd_{} -> nd_{} [label="{}"];'.format( + att["Source"], att["Target"], att.get("Label", "")) + body_l.append(edge_s) + + body_l.append("}") + + # Write DOT output + with open(dot_file, "w", encoding="utf-8") as f: + f.write("\n".join(body_l)) + + print(f"DGML file successfully converted to DOT format: {dot_file}") + + +def main(): + parser = argparse.ArgumentParser(description="Run CodeQL analysis and convert DGML to DOT.") + parser.add_argument("-c", "--codeql", required=True, help="Path to CodeQL CLI executable.") + parser.add_argument("-d", "--database", required=True, help="Path to the CodeQL database.") + parser.add_argument("-q", "--query", required=True, help="Path to the .ql query file.") + parser.add_argument("-o", "--output", required=True, help="Output directory for analysis results.") + + args = parser.parse_args() + + # Run CodeQL analysis + run_codeql_analysis(args.codeql, args.database, args.query, args.output) + + # Locate DGML file + dgml_file = os.path.join(args.output, "cbomgraph.dgml") + dot_file = dgml_file.replace(".dgml", ".dot") + + if os.path.exists(dgml_file): + # Convert DGML to DOT + convert_dgml_to_dot(dgml_file, dot_file) + else: + print(f"No DGML file found in {args.output}.") + sys.exit(1) + + +if __name__ == "__main__": + main() From 69a63855cc07c7a5d4b0b48f2e4b3f51b274ed3a Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Wed, 29 Jan 2025 21:55:57 +0100 Subject: [PATCH 008/336] Update CBOMGraph.ql --- cpp/ql/src/experimental/Quantum/CBOMGraph.ql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Quantum/CBOMGraph.ql b/cpp/ql/src/experimental/Quantum/CBOMGraph.ql index 1df6611aab9a..edcc40aca6a4 100644 --- a/cpp/ql/src/experimental/Quantum/CBOMGraph.ql +++ b/cpp/ql/src/experimental/Quantum/CBOMGraph.ql @@ -1,5 +1,6 @@ /** - * @name "Outputs a graph representation of the cryptographic bill of materials." + * @name "Print CBOM Graph" + * @description "Outputs a graph representation of the cryptographic bill of materials." * @kind graph * @id cbomgraph */ From 5f355c7f555748cb47b9cbaab862a0a05daf211c Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Tue, 4 Feb 2025 11:55:09 -0500 Subject: [PATCH 009/336] Add first sample JCA encryption model --- java/ql/lib/experimental/Quantum/Base.qll | 235 ++++++++++++++++++ java/ql/lib/experimental/Quantum/JCA.qll | 105 ++++++++ java/ql/lib/experimental/Quantum/Language.qll | 30 +++ java/ql/src/experimental/Quantum/Test.ql | 13 + 4 files changed, 383 insertions(+) create mode 100644 java/ql/lib/experimental/Quantum/Base.qll create mode 100644 java/ql/lib/experimental/Quantum/JCA.qll create mode 100644 java/ql/lib/experimental/Quantum/Language.qll create mode 100644 java/ql/src/experimental/Quantum/Test.ql diff --git a/java/ql/lib/experimental/Quantum/Base.qll b/java/ql/lib/experimental/Quantum/Base.qll new file mode 100644 index 000000000000..bbcd60ee891a --- /dev/null +++ b/java/ql/lib/experimental/Quantum/Base.qll @@ -0,0 +1,235 @@ +/** + * A language-independent library for reasoning about cryptography. + */ + + import codeql.util.Location + import codeql.util.Option + + signature module InputSig { + class LocatableElement { + Location getLocation(); + } + + class UnknownLocation instanceof Location; + } + + module CryptographyBase Input> { + final class LocatableElement = Input::LocatableElement; + + final class UnknownLocation = Input::UnknownLocation; + + final class UnknownPropertyValue extends string { + UnknownPropertyValue() { this = "" } + } + + abstract class NodeBase instanceof LocatableElement { + /** + * Returns a string representation of this node, usually the name of the operation/algorithm/property. + */ + abstract string toString(); + + /** + * Returns the location of this node in the code. + */ + Location getLocation() { result = super.getLocation() } + + /** + * Gets the origin of this node, e.g., a string literal in source describing it. + */ + LocatableElement getOrigin(string value) { none() } + + /** + * Returns the child of this node with the given edge name. + * + * This predicate is used by derived classes to construct the graph of cryptographic operations. + */ + NodeBase getChild(string edgeName) { none() } + + /** + * Defines properties of this node by name and either a value or location or both. + * + * This predicate is used by derived classes to construct the graph of cryptographic operations. + */ + predicate properties(string key, string value, Location location) { + key = "origin" and location = this.getOrigin(value).getLocation() + } + + /** + * Returns the parent of this node. + */ + final NodeBase getAParent() { result.getChild(_) = this } + } + + class Asset = NodeBase; + + /** + * A cryptographic operation, such as hashing or encryption. + */ + abstract class Operation extends Asset { + /** + * Gets the algorithm associated with this operation. + */ + abstract Algorithm getAlgorithm(); + + /** + * Gets the name of this operation, e.g., "hash" or "encrypt". + */ + abstract string getOperationName(); + + final override string toString() { result = this.getOperationName() } + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + edgeName = "uses" and + if exists(this.getAlgorithm()) then result = this.getAlgorithm() else result = this + } + } + + abstract class Algorithm extends Asset { + /** + * Gets the name of this algorithm, e.g., "AES" or "SHA". + */ + abstract string getAlgorithmName(); + + final override string toString() { result = this.getAlgorithmName() } + } + + /** + * A hashing operation that processes data to generate a hash value. + * This operation takes an input message of arbitrary content and length and produces a fixed-size + * hash value as the output using a specified hashing algorithm. + */ + abstract class HashOperation extends Operation { + abstract override HashAlgorithm getAlgorithm(); + + override string getOperationName() { result = "HASH" } + } + + // Rule: no newtype representing a type of algorithm should be modelled with multiple interfaces + // + // Example: HKDF and PKCS12KDF are both key derivation algorithms. + // However, PKCS12KDF also has a property: the iteration count. + // + // If we have HKDF and PKCS12KDF under TKeyDerivationType, + // someone modelling a library might try to make a generic identification of both of those algorithms. + // + // They will therefore not use the specialized type for PKCS12KDF, + // meaning "from PKCS12KDF algo select algo" will have no results. + // + newtype THashType = + // We're saying by this that all of these have an identical interface / properties / edges + MD5() or + SHA1() or + SHA256() or + SHA512() or + OtherHashType() + + /** + * A hashing algorithm that transforms variable-length input into a fixed-size hash value. + */ + abstract class HashAlgorithm extends Algorithm { + final predicate hashTypeToNameMapping(THashType type, string name) { + type instanceof MD5 and name = "MD5" + or + type instanceof SHA1 and name = "SHA-1" + or + type instanceof SHA256 and name = "SHA-256" + or + type instanceof SHA512 and name = "SHA-512" + or + type instanceof OtherHashType and name = this.getRawAlgorithmName() + } + + abstract THashType getHashType(); + + override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashType(), result) } + + /** + * Gets the raw name of this hash algorithm from source. + */ + abstract string getRawAlgorithmName(); + } + + /** + * An operation that derives one or more keys from an input value. + */ + abstract class KeyDerivationOperation extends Operation { + override string getOperationName() { result = "KEY_DERIVATION" } + } + + /** + * An algorithm that derives one or more keys from an input value. + */ + abstract class KeyDerivationAlgorithm extends Algorithm { + abstract override string getAlgorithmName(); + } + + /** + * HKDF key derivation function + */ + abstract class HKDF extends KeyDerivationAlgorithm { + final override string getAlgorithmName() { result = "HKDF" } + + abstract HashAlgorithm getHashAlgorithm(); + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + edgeName = "digest" and result = this.getHashAlgorithm() + } + } + + /** + * PKCS #12 key derivation function + */ + abstract class PKCS12KDF extends KeyDerivationAlgorithm { + final override string getAlgorithmName() { result = "PKCS12KDF" } + + abstract HashAlgorithm getHashAlgorithm(); + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + edgeName = "digest" and result = this.getHashAlgorithm() + } + } + + /** + * Elliptic curve algorithm + */ + abstract class EllipticCurve extends Algorithm { + abstract string getVersion(Location location); + + abstract string getKeySize(Location location); + + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + key = "version" and + if exists(this.getVersion(location)) + then value = this.getVersion(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + or + key = "key_size" and + if exists(this.getKeySize(location)) + then value = this.getKeySize(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + } + } + + /** + * An encryption operation that processes plaintext to generate a ciphertext. + * This operation takes an input message (plaintext) of arbitrary content and length and produces a ciphertext as the output using a specified encryption algorithm (with a mode and padding). + */ + abstract class EncryptionOperation extends Operation { + abstract override Algorithm getAlgorithm(); + + override string getOperationName() { result = "ENCRYPTION" } + } + } + \ No newline at end of file diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll new file mode 100644 index 000000000000..bef648d290a1 --- /dev/null +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -0,0 +1,105 @@ +import java +import semmle.code.java.dataflow.DataFlow + +module JCAModel { + import Language + + abstract class EncryptionOperation extends Crypto::EncryptionOperation { } + + //TODO PBEWith can have suffixes. how to do? enumerate? or match a pattern? +predicate cipher_names(string algo) { algo = ["AES", "AESWrap", "AESWrapPad", "ARCFOUR", "Blowfish", "ChaCha20", "ChaCha20-Poly1305", "DES", "DESede", "DESedeWrap", "ECIES", "PBEWith", "RC2", "RC4", "RC5", "RSA"] } +//TODO solve the fact that x is an int of various values. same as above... enumerate? +predicate cipher_modes(string mode) {mode = ["NONE", "CBC", "CCM", "CFB", "CFBx", "CTR", "CTS", "ECB", "GCM", "KW", "KWP", "OFB", "OFBx", "PCBC"]} +//todo same as above, OAEPWith has asuffix type +predicate cipher_padding(string padding) {padding = ["NoPadding", "ISO10126Padding", "OAEPPadding", "OAEPWith", "PKCS1Padding", "PKCS5Padding", "SSL3Padding"]} + + /** + * Symmetric algorithms + */ + abstract class SymmetricAlgorithm extends Crypto::Algorithm { + + + //TODO figure out how to get this from the Cipher interface, is it explicit? + //abstract string getKeySize(Location location); + + // override predicate properties(string key, string value, Location location) { + // super.properties(key, value, location) + // or + // key = "key_size" and + // if exists(this.getKeySize(location)) + // then value = this.getKeySize(location) + // else ( + // value instanceof Crypto::UnknownPropertyValue and location instanceof UnknownLocation + // ) + // // other properties, like field type are possible, but not modeled until considered necessary + // } + + abstract override string getAlgorithmName(); +} + +////cipher specifics ---------------------------------------- + +class CipherInstance extends Call { + CipherInstance() { this.getCallee().hasQualifiedName("javax.crypto","Cipher", "getInstance") } + + Expr getAlgorithmArg() { result = this.getArgument(0) } + } + +class CipherAlgorithmStringLiteral extends Crypto::NodeBase instanceof StringLiteral { + CipherAlgorithmStringLiteral() { cipher_names(this.getValue().splitAt("/"))} + + override string toString() { result = this.(StringLiteral).toString() } + + string getValue() { result = this.(StringLiteral).getValue() } + } + + class CipherAlgorithmModeStringLiteral extends Crypto::NodeBase instanceof StringLiteral { + CipherAlgorithmModeStringLiteral() { cipher_modes(this.getValue().splitAt("/"))} + + override string toString() { result = this.(StringLiteral).toString() } + + string getValue() { result = this.(StringLiteral).getValue() } + } + + class CipherAlgorithmPaddingStringLiteral extends Crypto::NodeBase instanceof StringLiteral { + CipherAlgorithmPaddingStringLiteral() { cipher_padding(this.getValue().splitAt("/"))} + + override string toString() { result = this.(StringLiteral).toString() } + + string getValue() { result = this.(StringLiteral).getValue() } + } + + private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof CipherAlgorithmStringLiteral } + + predicate isSink(DataFlow::Node sink) { + exists(CipherInstance call | sink.asExpr() = call.getAlgorithmArg()) + } + } + + module AlgorithmStringToFetchFlow = DataFlow::Global; + + predicate algorithmStringToCipherInstanceArgFlow(string name, CipherAlgorithmStringLiteral origin, Expr arg) { + exists(CipherInstance sinkCall | + origin.getValue().toUpperCase() = name and + arg = sinkCall.getAlgorithmArg() and + AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), DataFlow::exprNode(arg)) + ) + } + + class AES extends SymmetricAlgorithm instanceof Expr { + CipherAlgorithmStringLiteral origin; + + AES() { algorithmStringToCipherInstanceArgFlow("AES", origin, this) } + + override Crypto::LocatableElement getOrigin(string name) { + result = origin and name = origin.toString() + } + + override string getAlgorithmName(){ result = "AES"} + } + + + + +} \ No newline at end of file diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll new file mode 100644 index 000000000000..246f2b86367c --- /dev/null +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -0,0 +1,30 @@ +private import Base +private import java as Lang + +/** + * A dummy location which is used when something doesn't have a location in + * the source code but needs to have a `Location` associated with it. There + * may be several distinct kinds of unknown locations. For example: one for + * expressions, one for statements and one for other program elements. + */ +class UnknownLocation extends Location { + UnknownLocation() { this.getFile().getAbsolutePath() = "" } +} + +/** + * A dummy location which is used when something doesn't have a location in + * the source code but needs to have a `Location` associated with it. + */ +class UnknownDefaultLocation extends UnknownLocation { + UnknownDefaultLocation() { locations_default(this, _, 0, 0, 0, 0) } +} + +module CryptoInput implements InputSig { + class LocatableElement = Lang::Element; + + class UnknownLocation = UnknownDefaultLocation; +} + +module Crypto = CryptographyBase; + +import JCA diff --git a/java/ql/src/experimental/Quantum/Test.ql b/java/ql/src/experimental/Quantum/Test.ql new file mode 100644 index 000000000000..672ad14e5dfa --- /dev/null +++ b/java/ql/src/experimental/Quantum/Test.ql @@ -0,0 +1,13 @@ +/** + * @name "PQC Test" + */ + + import experimental.Quantum.Language + //import java + + from Crypto::NodeBase node + select node + +// from Class t +// where t.hasQualifiedName("javax.crypto", "CipherSpi") +// select t, t.getADescendant*() \ No newline at end of file From 86e51dad8a4d2ead6638f1d5cfb0f54309bf81fa Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Wed, 5 Feb 2025 13:39:48 -0500 Subject: [PATCH 010/336] Improve JCA aes alg model, add test --- java/ql/lib/experimental/Quantum/JCA.qll | 58 ++++++++++++++++++------ java/ql/src/experimental/Quantum/Test.ql | 9 +--- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index bef648d290a1..fae5c4f806e9 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -13,6 +13,18 @@ predicate cipher_modes(string mode) {mode = ["NONE", "CBC", "CCM", "CFB", "CFBx" //todo same as above, OAEPWith has asuffix type predicate cipher_padding(string padding) {padding = ["NoPadding", "ISO10126Padding", "OAEPPadding", "OAEPWith", "PKCS1Padding", "PKCS5Padding", "SSL3Padding"]} + +abstract class BlockCiper extends Crypto::Algorithm { + CipherAlgorithmStringLiteral alg; + CipherAlgorithmMode mode; + CipherAlgorithmPadding padding; + + + CipherAlgorithmStringLiteral getAlg() {result = alg } + CipherAlgorithmMode getMode() {result = mode } + + CipherAlgorithmPadding getPadding() {result =padding} +} /** * Symmetric algorithms */ @@ -45,6 +57,9 @@ class CipherInstance extends Call { Expr getAlgorithmArg() { result = this.getArgument(0) } } + /** + * this may be specified either in the ALG/MODE/PADDING or just ALG format + */ class CipherAlgorithmStringLiteral extends Crypto::NodeBase instanceof StringLiteral { CipherAlgorithmStringLiteral() { cipher_names(this.getValue().splitAt("/"))} @@ -53,20 +68,28 @@ class CipherAlgorithmStringLiteral extends Crypto::NodeBase instanceof StringLit string getValue() { result = this.(StringLiteral).getValue() } } - class CipherAlgorithmModeStringLiteral extends Crypto::NodeBase instanceof StringLiteral { - CipherAlgorithmModeStringLiteral() { cipher_modes(this.getValue().splitAt("/"))} +abstract class CipherAlgorithmMode extends Crypto::NodeBase { + string getValue() {result = ""} +} + + class CipherAlgorithmModeStringLiteral extends CipherAlgorithmMode instanceof StringLiteral { + CipherAlgorithmModeStringLiteral() { cipher_modes(this.(StringLiteral).getValue().splitAt("/"))} override string toString() { result = this.(StringLiteral).toString() } - string getValue() { result = this.(StringLiteral).getValue() } + override string getValue() { result = this.(StringLiteral).getValue().regexpCapture(".*/(.*)/.*",1) } } - class CipherAlgorithmPaddingStringLiteral extends Crypto::NodeBase instanceof StringLiteral { - CipherAlgorithmPaddingStringLiteral() { cipher_padding(this.getValue().splitAt("/"))} + abstract class CipherAlgorithmPadding extends Crypto::NodeBase { + string getValue() {result = ""} + } + + class CipherAlgorithmPaddingStringLiteral extends CipherAlgorithmPadding instanceof StringLiteral { + CipherAlgorithmPaddingStringLiteral() { cipher_padding(this.(StringLiteral).getValue().splitAt("/"))} override string toString() { result = this.(StringLiteral).toString() } - string getValue() { result = this.(StringLiteral).getValue() } + override string getValue() { result = this.(StringLiteral).getValue().regexpCapture(".*/.*/(.*)",1) } } private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { @@ -79,27 +102,32 @@ class CipherAlgorithmStringLiteral extends Crypto::NodeBase instanceof StringLit module AlgorithmStringToFetchFlow = DataFlow::Global; - predicate algorithmStringToCipherInstanceArgFlow(string name, CipherAlgorithmStringLiteral origin, Expr arg) { + predicate algorithmStringToCipherInstanceArgFlow(string name, CipherAlgorithmStringLiteral origin, CipherAlgorithmModeStringLiteral mode, CipherAlgorithmPaddingStringLiteral padding, Expr arg) { exists(CipherInstance sinkCall | - origin.getValue().toUpperCase() = name and + origin.getValue().splitAt("/") = name and + origin = mode and + origin = padding and arg = sinkCall.getAlgorithmArg() and AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), DataFlow::exprNode(arg)) ) } - class AES extends SymmetricAlgorithm instanceof Expr { - CipherAlgorithmStringLiteral origin; + /** + * A class to represent when AES is used AND it has literal mode and padding provided + * this does not capture the use without + */ + class AESLiteral extends SymmetricAlgorithm, BlockCiper instanceof Expr { - AES() { algorithmStringToCipherInstanceArgFlow("AES", origin, this) } + + AESLiteral() { algorithmStringToCipherInstanceArgFlow("AES", alg, mode, padding, this) +} override Crypto::LocatableElement getOrigin(string name) { - result = origin and name = origin.toString() + result = alg and name = alg.toString() } - override string getAlgorithmName(){ result = "AES"} + override string getAlgorithmName(){ result = this.getAlgorithmName()} } - - } \ No newline at end of file diff --git a/java/ql/src/experimental/Quantum/Test.ql b/java/ql/src/experimental/Quantum/Test.ql index 672ad14e5dfa..f35336a846f2 100644 --- a/java/ql/src/experimental/Quantum/Test.ql +++ b/java/ql/src/experimental/Quantum/Test.ql @@ -3,11 +3,6 @@ */ import experimental.Quantum.Language - //import java - from Crypto::NodeBase node - select node - -// from Class t -// where t.hasQualifiedName("javax.crypto", "CipherSpi") -// select t, t.getADescendant*() \ No newline at end of file +from JCAModel::AESLiteral l +select l, l.getAlg(), l.getMode().getValue(), l.getPadding().getValue() \ No newline at end of file From efcf7eab0cad504376e19ea96145007df3d929a5 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Wed, 5 Feb 2025 17:24:25 -0500 Subject: [PATCH 011/336] Add broken crypto query --- java/ql/lib/experimental/Quantum/JCA.qll | 2 +- .../src/experimental/Quantum/BrokenCrypto.ql | 77 +++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 java/ql/src/experimental/Quantum/BrokenCrypto.ql diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index fae5c4f806e9..8a613b66d022 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -126,7 +126,7 @@ abstract class CipherAlgorithmMode extends Crypto::NodeBase { result = alg and name = alg.toString() } - override string getAlgorithmName(){ result = this.getAlgorithmName()} + override string getAlgorithmName(){ result = alg.getValue()} } diff --git a/java/ql/src/experimental/Quantum/BrokenCrypto.ql b/java/ql/src/experimental/Quantum/BrokenCrypto.ql new file mode 100644 index 000000000000..020ac1b8925a --- /dev/null +++ b/java/ql/src/experimental/Quantum/BrokenCrypto.ql @@ -0,0 +1,77 @@ +/** +* @name Use of a broken or risky cryptographic algorithm +* @description Using broken or weak cryptographic algorithms can allow an attacker to compromise security. +* @kind problem +* @problem.severity warning +* @security-severity 7.5 +* @precision high +* @id java/weak-cryptographic-algorithm-new-model +* @tags security +* external/cwe/cwe-327 +* external/cwe/cwe-328 +*/ + + + +//THIS QUERY IS A REPLICA OF: https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql +//but uses the **NEW MODELLING** +import experimental.Quantum.Language + + +/** + * Gets the name of an algorithm that is known to be insecure. + */ +string getAnInsecureAlgorithmName() { + result = + [ + "DES", "RC2", "RC4", "RC5", + // ARCFOUR is a variant of RC4 + "ARCFOUR", + // Encryption mode ECB like AES/ECB/NoPadding is vulnerable to replay and other attacks + "ECB", + // CBC mode of operation with PKCS#5 or PKCS#7 padding is vulnerable to padding oracle attacks + "AES/CBC/PKCS[57]Padding" + ] + } + + private string rankedInsecureAlgorithm(int i) { + result = rank[i](string s | s = getAnInsecureAlgorithmName()) + } + + private string insecureAlgorithmString(int i) { + i = 1 and result = rankedInsecureAlgorithm(i) + or + result = rankedInsecureAlgorithm(i) + "|" + insecureAlgorithmString(i - 1) + } + + /** + * Gets the regular expression used for matching strings that look like they + * contain an algorithm that is known to be insecure. + */ + string getInsecureAlgorithmRegex() { + result = algorithmRegex(insecureAlgorithmString(max(int i | exists(rankedInsecureAlgorithm(i))))) + } + + bindingset[algorithmString] +private string algorithmRegex(string algorithmString) { + // Algorithms usually appear in names surrounded by characters that are not + // alphabetical characters in the same case. This handles the upper and lower + // case cases. + result = + "((^|.*[^A-Z])(" + algorithmString + ")([^A-Z].*|$))" + + // or... + "|" + + // For lowercase, we want to be careful to avoid being confused by camelCase + // hence we require two preceding uppercase letters to be sure of a case switch, + // or a preceding non-alphabetic character + "((^|.*[A-Z]{2}|.*[^a-zA-Z])(" + algorithmString.toLowerCase() + ")([^a-z].*|$))" +} + +from Crypto::Algorithm alg +where alg.getAlgorithmName().regexpMatch(getInsecureAlgorithmRegex()) and +// Exclude RSA/ECB/.* ciphers. +not alg.getAlgorithmName().regexpMatch("RSA/ECB.*") and +// Exclude German and French sentences. +not alg.getAlgorithmName().regexpMatch(".*\\p{IsLowercase} des \\p{IsLetter}.*") +select alg, "Cryptographic algorithm $@ is weak and should not be used.", alg, +alg.getAlgorithmName() From 3dc28c2d17d95c9bdbf2e7127d365e3673770363 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 6 Feb 2025 21:54:18 +0100 Subject: [PATCH 012/336] Move language-agnostic model to shared library --- cpp/ql/lib/experimental/Quantum/Language.qll | 2 +- cpp/ql/lib/experimental/Quantum/OpenSSL.qll | 4 ++ cpp/ql/lib/qlpack.yml | 1 + .../scripts/cryptography}/cbom.sh | 2 +- .../scripts/cryptography}/generate_cbom.py | 0 .../codeql/cryptography/Model.qll | 44 +++++++++---------- shared/cryptography/qlpack.yml | 7 +++ 7 files changed, 34 insertions(+), 26 deletions(-) rename {cpp/ql/src/experimental/Quantum => misc/scripts/cryptography}/cbom.sh (79%) rename {cpp/ql/src/experimental/Quantum => misc/scripts/cryptography}/generate_cbom.py (100%) rename cpp/ql/lib/experimental/Quantum/Base.qll => shared/cryptography/codeql/cryptography/Model.qll (93%) create mode 100644 shared/cryptography/qlpack.yml diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index c9398c9e3245..8f400858f07c 100644 --- a/cpp/ql/lib/experimental/Quantum/Language.qll +++ b/cpp/ql/lib/experimental/Quantum/Language.qll @@ -1,4 +1,4 @@ -private import Base +private import codeql.cryptography.Model private import cpp as Lang module CryptoInput implements InputSig { diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll index 18feda6c8c6c..bf38e5c0ab5d 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll @@ -77,6 +77,8 @@ module OpenSSLModel { HKDF() { algorithmStringToKDFFetchArgFlow("HKDF", origin, this) } + override string getRawAlgorithmName() { result = origin.getValue() } + override Crypto::HashAlgorithm getHashAlgorithm() { none() } override Crypto::LocatableElement getOrigin(string name) { @@ -89,6 +91,8 @@ module OpenSSLModel { PKCS12KDF() { algorithmStringToKDFFetchArgFlow("PKCS12KDF", origin, this) } + override string getRawAlgorithmName() { result = origin.getValue() } + override Crypto::HashAlgorithm getHashAlgorithm() { none() } override Crypto::NodeBase getOrigin(string name) { diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index 6ffc77714d47..489de9f6cef4 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -6,6 +6,7 @@ extractor: cpp library: true upgrades: upgrades dependencies: + codeql/cryptography: ${workspace} codeql/dataflow: ${workspace} codeql/mad: ${workspace} codeql/rangeanalysis: ${workspace} diff --git a/cpp/ql/src/experimental/Quantum/cbom.sh b/misc/scripts/cryptography/cbom.sh similarity index 79% rename from cpp/ql/src/experimental/Quantum/cbom.sh rename to misc/scripts/cryptography/cbom.sh index df1c58b1efb8..9cbef951bbf4 100755 --- a/cpp/ql/src/experimental/Quantum/cbom.sh +++ b/misc/scripts/cryptography/cbom.sh @@ -2,7 +2,7 @@ CODEQL_PATH="/Users/nicolaswill/Library/Application Support/Code/User/globalStorage/github.vscode-codeql/distribution5/codeql/codeql" DATABASE_PATH="/Users/nicolaswill/openssl_codeql/openssl/openssl_db" -QUERY_FILE="CBOMGraph.ql" +QUERY_FILE="/Users/nicolaswill/pqc/codeql/cpp/ql/src/experimental/Quantum/CBOMGraph.ql" OUTPUT_DIR="graph_output" python3 generate_cbom.py -c "$CODEQL_PATH" -d "$DATABASE_PATH" -q "$QUERY_FILE" -o "$OUTPUT_DIR" diff --git a/cpp/ql/src/experimental/Quantum/generate_cbom.py b/misc/scripts/cryptography/generate_cbom.py similarity index 100% rename from cpp/ql/src/experimental/Quantum/generate_cbom.py rename to misc/scripts/cryptography/generate_cbom.py diff --git a/cpp/ql/lib/experimental/Quantum/Base.qll b/shared/cryptography/codeql/cryptography/Model.qll similarity index 93% rename from cpp/ql/lib/experimental/Quantum/Base.qll rename to shared/cryptography/codeql/cryptography/Model.qll index 68b3bc08cf70..eba25db60d24 100644 --- a/cpp/ql/lib/experimental/Quantum/Base.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -94,7 +94,7 @@ module CryptographyBase Input> { */ abstract string getAlgorithmName(); - /** + /** * Gets the raw name of this algorithm from source (no parsing or formatting) */ abstract string getRawAlgorithmName(); @@ -151,7 +151,6 @@ module CryptographyBase Input> { abstract THashType getHashType(); override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashType(), result) } - } /** @@ -199,26 +198,23 @@ module CryptographyBase Input> { } newtype TEllipticCurveFamilyType = - // We're saying by this that all of these have an identical interface / properties / edges - NIST() or - SEC() or - NUMS() or - PRIME() or - BRAINPOOL() or - CURVE25519() or - CURVE448() or - C2() or - SM2() or - ES() or - OtherEllipticCurveFamilyType() - + // We're saying by this that all of these have an identical interface / properties / edges + NIST() or + SEC() or + NUMS() or + PRIME() or + BRAINPOOL() or + CURVE25519() or + CURVE448() or + C2() or + SM2() or + ES() or + OtherEllipticCurveFamilyType() /** * Elliptic curve algorithm */ abstract class EllipticCurve extends Algorithm { - - abstract string getKeySize(Location location); abstract TEllipticCurveFamilyType getCurveFamilyType(); @@ -235,18 +231,18 @@ module CryptographyBase Input> { // other properties, like field type are possible, but not modeled until considered necessary } - override string getAlgorithmName() { result = this.getRawAlgorithmName().toUpperCase()} + override string getAlgorithmName() { result = this.getRawAlgorithmName().toUpperCase() } /** * Mandating that for Elliptic Curves specifically, users are responsible - * for providing as the 'raw' name, the official name of the algorithm. - * Casing doesn't matter, we will enforce further naming restrictions on - * `getAlgorithmName` by default. + * for providing as the 'raw' name, the official name of the algorithm. + * Casing doesn't matter, we will enforce further naming restrictions on + * `getAlgorithmName` by default. * Rationale: elliptic curve names can have a lot of variation in their components * (e.g., "secp256r1" vs "P-256"), trying to produce generalized set of properties - * is possible to capture all cases, but such modeling is likely not necessary. - * if all properties need to be captured, we can reassess how names are generated. + * is possible to capture all cases, but such modeling is likely not necessary. + * if all properties need to be captured, we can reassess how names are generated. */ - override abstract string getRawAlgorithmName(); + abstract override string getRawAlgorithmName(); } } diff --git a/shared/cryptography/qlpack.yml b/shared/cryptography/qlpack.yml new file mode 100644 index 000000000000..768c64a0704e --- /dev/null +++ b/shared/cryptography/qlpack.yml @@ -0,0 +1,7 @@ +name: codeql/cryptography +version: 0.0.0-dev +groups: shared +library: true +dependencies: + codeql/util: ${workspace} +warnOnImplicitThis: true \ No newline at end of file From 60d931af9f98ffda9185ed17bc17e9ad870887ab Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Fri, 7 Feb 2025 15:46:13 -0500 Subject: [PATCH 013/336] Update progress on JCA --- java/ql/lib/experimental/Quantum/Base.qll | 94 +++++++++++++++++++- java/ql/lib/experimental/Quantum/JCA.qll | 100 ++++++++++------------ 2 files changed, 136 insertions(+), 58 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/Base.qll b/java/ql/lib/experimental/Quantum/Base.qll index bbcd60ee891a..a14f3b6836ad 100644 --- a/java/ql/lib/experimental/Quantum/Base.qll +++ b/java/ql/lib/experimental/Quantum/Base.qll @@ -11,6 +11,8 @@ } class UnknownLocation instanceof Location; + + } module CryptographyBase Input> { @@ -91,6 +93,11 @@ * Gets the name of this algorithm, e.g., "AES" or "SHA". */ abstract string getAlgorithmName(); + + /** + * Gets the raw name of this algorithm from source (no parsing or formatting) + */ + abstract string getRawAlgorithmName(); final override string toString() { result = this.getAlgorithmName() } } @@ -148,7 +155,7 @@ /** * Gets the raw name of this hash algorithm from source. */ - abstract string getRawAlgorithmName(); + override abstract string getRawAlgorithmName(); } /** @@ -231,5 +238,90 @@ override string getOperationName() { result = "ENCRYPTION" } } + +// newtype TBlockCipherFamilyType = +// // We're saying by this that all of these have an identical interface / properties / edges +// CBC() or ECB() + + +// abstract class BlockCiper extends Algorithm { + +// abstract string getKeySize(Location location); + +// abstract TBlockCipherFamilyType getBlockCipherFamilyType(); + +// override predicate properties(string key, string value, Location location) { +// super.properties(key, value, location) +// or +// key = "key_size" and +// if exists(this.getKeySize(location)) +// then value = this.getKeySize(location) +// else ( +// value instanceof UnknownPropertyValue and location instanceof UnknownLocation +// ) +// // other properties, like field type are possible, but not modeled until considered necessary +// } + +// override string getAlgorithmName() { result = this.getRawAlgorithmName().toUpperCase()} + +// override abstract string getRawAlgorithmName(); +// } + +newtype TModeOperation = +ECB() or OtherMode() + +abstract class ModeOfOperation extends Algorithm { + string getValue() {result = ""} + + final private predicate modeToNameMapping(TModeOperation type, string name) { + type instanceof ECB and name = "ECB" + or + type instanceof OtherMode and name = this.getRawAlgorithmName() + } + + abstract TModeOperation getModeType(); + + override string getAlgorithmName() { this.modeToNameMapping(this.getModeType(), result) } + +} + +newtype TCipherStructure = +Block() or Stream() + + newtype TSymmetricCipherFamilyType = +// We're saying by this that all of these have an identical interface / properties / edges +AES() + + /** + * Symmetric algorithms + */ + abstract class SymmetricAlgorithm extends Algorithm { + + + abstract TSymmetricCipherFamilyType getSymmetricCipherFamilyType(); + + abstract string getKeySize(Location location); + + abstract TCipherStructure getCipherType(); + + + //mode, padding scheme, keysize, block/stream, auth'd + //nodes = mode, padding scheme + //properties = keysize, block/stream, auth'd + //leave authd to lang specific + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + key = "key_size" and + if exists(this.getKeySize(location)) + then value = this.getKeySize(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + //add more keys to index props + } + + abstract ModeOfOperation getModeOfOperation(); +} } \ No newline at end of file diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 8a613b66d022..389235964b5f 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -14,41 +14,6 @@ predicate cipher_modes(string mode) {mode = ["NONE", "CBC", "CCM", "CFB", "CFBx" predicate cipher_padding(string padding) {padding = ["NoPadding", "ISO10126Padding", "OAEPPadding", "OAEPWith", "PKCS1Padding", "PKCS5Padding", "SSL3Padding"]} -abstract class BlockCiper extends Crypto::Algorithm { - CipherAlgorithmStringLiteral alg; - CipherAlgorithmMode mode; - CipherAlgorithmPadding padding; - - - CipherAlgorithmStringLiteral getAlg() {result = alg } - CipherAlgorithmMode getMode() {result = mode } - - CipherAlgorithmPadding getPadding() {result =padding} -} - /** - * Symmetric algorithms - */ - abstract class SymmetricAlgorithm extends Crypto::Algorithm { - - - //TODO figure out how to get this from the Cipher interface, is it explicit? - //abstract string getKeySize(Location location); - - // override predicate properties(string key, string value, Location location) { - // super.properties(key, value, location) - // or - // key = "key_size" and - // if exists(this.getKeySize(location)) - // then value = this.getKeySize(location) - // else ( - // value instanceof Crypto::UnknownPropertyValue and location instanceof UnknownLocation - // ) - // // other properties, like field type are possible, but not modeled until considered necessary - // } - - abstract override string getAlgorithmName(); -} - ////cipher specifics ---------------------------------------- class CipherInstance extends Call { @@ -60,24 +25,26 @@ class CipherInstance extends Call { /** * this may be specified either in the ALG/MODE/PADDING or just ALG format */ -class CipherAlgorithmStringLiteral extends Crypto::NodeBase instanceof StringLiteral { +class CipherAlgorithmStringLiteral extends StringLiteral { CipherAlgorithmStringLiteral() { cipher_names(this.getValue().splitAt("/"))} - - override string toString() { result = this.(StringLiteral).toString() } - - string getValue() { result = this.(StringLiteral).getValue() } } -abstract class CipherAlgorithmMode extends Crypto::NodeBase { - string getValue() {result = ""} -} - class CipherAlgorithmModeStringLiteral extends CipherAlgorithmMode instanceof StringLiteral { - CipherAlgorithmModeStringLiteral() { cipher_modes(this.(StringLiteral).getValue().splitAt("/"))} + class ModeOfOperationStringLiteral extends Crypto::ModeOfOperation instanceof StringLiteral { + ModeOfOperationStringLiteral() { cipher_modes(this.(StringLiteral).getValue().splitAt("/"))} - override string toString() { result = this.(StringLiteral).toString() } + override string getRawAlgorithmName() { result = this.(StringLiteral).getValue().regexpCapture(".*/(.*)/.*",1) } override string getValue() { result = this.(StringLiteral).getValue().regexpCapture(".*/(.*)/.*",1) } + + + predicate modeToNameMapping(Crypto::TModeOperation type, string name) { + name = "ECB" and type instanceof Crypto::ECB + } + + override Crypto::TModeOperation getModeType(){ + modeToNameMapping(result, this.getRawAlgorithmName()) + } } abstract class CipherAlgorithmPadding extends Crypto::NodeBase { @@ -102,32 +69,51 @@ abstract class CipherAlgorithmMode extends Crypto::NodeBase { module AlgorithmStringToFetchFlow = DataFlow::Global; - predicate algorithmStringToCipherInstanceArgFlow(string name, CipherAlgorithmStringLiteral origin, CipherAlgorithmModeStringLiteral mode, CipherAlgorithmPaddingStringLiteral padding, Expr arg) { + predicate algorithmStringToCipherInstanceArgFlow(string name, CipherAlgorithmStringLiteral origin, Expr arg) { exists(CipherInstance sinkCall | origin.getValue().splitAt("/") = name and - origin = mode and - origin = padding and arg = sinkCall.getAlgorithmArg() and AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), DataFlow::exprNode(arg)) ) } + + predicate modeStringToCipherInstanceArgFlow(string name, ModeOfOperationStringLiteral mode, Expr arg) { + exists(CipherInstance sinkCall | + mode.getRawAlgorithmName() = name and + arg = sinkCall.getAlgorithmArg() and + AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(mode), DataFlow::exprNode(arg)) + ) + } + /** * A class to represent when AES is used AND it has literal mode and padding provided * this does not capture the use without */ - class AESLiteral extends SymmetricAlgorithm, BlockCiper instanceof Expr { +// class AESLiteral extends Crypto::SymmetricAlgorithm instanceof Expr { +// CipherAlgorithmStringLiteral alg; +// AESLiteral() { algorithmStringToCipherInstanceArgFlow("AES", alg, this) +// } +// override Crypto::ModeOfOperation getModeOfOperation(){ modeStringToCipherInstanceArgFlow(result.getAlgorithmName(), result, this)} - AESLiteral() { algorithmStringToCipherInstanceArgFlow("AES", alg, mode, padding, this) -} +// override Crypto::LocatableElement getOrigin(string name) { +// result = alg and name = alg.toString() +// } - override Crypto::LocatableElement getOrigin(string name) { - result = alg and name = alg.toString() - } +// override string getAlgorithmName(){ result = "AES" } - override string getAlgorithmName(){ result = alg.getValue()} - } +// override string getRawAlgorithmName(){ result = alg.getValue()} + +// override Crypto::TSymmetricCipherFamilyType getSymmetricCipherFamilyType() { result instanceof Crypto::AES} + +// //temp hacks for testing +// override string getKeySize(Location location){ +// result = "" +// } + +// override Crypto::TCipherStructure getCipherType(){ none()} +// } } \ No newline at end of file From 6005437001c27e022d6f9d29c738f5fdb05ad481 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Mon, 10 Feb 2025 11:26:48 -0500 Subject: [PATCH 014/336] Update JCA model with flow to call as AESuse and format JCA model --- java/ql/lib/experimental/Quantum/JCA.qll | 132 ++++++++++++++--------- 1 file changed, 82 insertions(+), 50 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 389235964b5f..f75cfe7fd083 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -7,17 +7,35 @@ module JCAModel { abstract class EncryptionOperation extends Crypto::EncryptionOperation { } //TODO PBEWith can have suffixes. how to do? enumerate? or match a pattern? -predicate cipher_names(string algo) { algo = ["AES", "AESWrap", "AESWrapPad", "ARCFOUR", "Blowfish", "ChaCha20", "ChaCha20-Poly1305", "DES", "DESede", "DESedeWrap", "ECIES", "PBEWith", "RC2", "RC4", "RC5", "RSA"] } -//TODO solve the fact that x is an int of various values. same as above... enumerate? -predicate cipher_modes(string mode) {mode = ["NONE", "CBC", "CCM", "CFB", "CFBx", "CTR", "CTS", "ECB", "GCM", "KW", "KWP", "OFB", "OFBx", "PCBC"]} -//todo same as above, OAEPWith has asuffix type -predicate cipher_padding(string padding) {padding = ["NoPadding", "ISO10126Padding", "OAEPPadding", "OAEPWith", "PKCS1Padding", "PKCS5Padding", "SSL3Padding"]} + predicate cipher_names(string algo) { + algo = + [ + "AES", "AESWrap", "AESWrapPad", "ARCFOUR", "Blowfish", "ChaCha20", "ChaCha20-Poly1305", + "DES", "DESede", "DESedeWrap", "ECIES", "PBEWith", "RC2", "RC4", "RC5", "RSA" + ] + } + //TODO solve the fact that x is an int of various values. same as above... enumerate? + predicate cipher_modes(string mode) { + mode = + [ + "NONE", "CBC", "CCM", "CFB", "CFBx", "CTR", "CTS", "ECB", "GCM", "KW", "KWP", "OFB", "OFBx", + "PCBC" + ] + } -////cipher specifics ---------------------------------------- + //todo same as above, OAEPWith has asuffix type + predicate cipher_padding(string padding) { + padding = + [ + "NoPadding", "ISO10126Padding", "OAEPPadding", "OAEPWith", "PKCS1Padding", "PKCS5Padding", + "SSL3Padding" + ] + } -class CipherInstance extends Call { - CipherInstance() { this.getCallee().hasQualifiedName("javax.crypto","Cipher", "getInstance") } + ////cipher specifics ---------------------------------------- + class CipherInstance extends Call { + CipherInstance() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "getInstance") } Expr getAlgorithmArg() { result = this.getArgument(0) } } @@ -25,38 +43,44 @@ class CipherInstance extends Call { /** * this may be specified either in the ALG/MODE/PADDING or just ALG format */ -class CipherAlgorithmStringLiteral extends StringLiteral { - CipherAlgorithmStringLiteral() { cipher_names(this.getValue().splitAt("/"))} + class CipherAlgorithmStringLiteral extends StringLiteral { + CipherAlgorithmStringLiteral() { cipher_names(this.getValue().splitAt("/")) } } - class ModeOfOperationStringLiteral extends Crypto::ModeOfOperation instanceof StringLiteral { - ModeOfOperationStringLiteral() { cipher_modes(this.(StringLiteral).getValue().splitAt("/"))} + ModeOfOperationStringLiteral() { cipher_modes(this.(StringLiteral).getValue().splitAt("/")) } - override string getRawAlgorithmName() { result = this.(StringLiteral).getValue().regexpCapture(".*/(.*)/.*",1) } + override string getRawAlgorithmName() { + result = this.(StringLiteral).getValue().regexpCapture(".*/(.*)/.*", 1) + } - override string getValue() { result = this.(StringLiteral).getValue().regexpCapture(".*/(.*)/.*",1) } + override string getValue() { + result = this.(StringLiteral).getValue().regexpCapture(".*/(.*)/.*", 1) + } + predicate modeToNameMapping(Crypto::TModeOperation type, string name) { + name = "ECB" and type instanceof Crypto::ECB + } - predicate modeToNameMapping(Crypto::TModeOperation type, string name) { - name = "ECB" and type instanceof Crypto::ECB - } - - override Crypto::TModeOperation getModeType(){ + override Crypto::TModeOperation getModeType() { modeToNameMapping(result, this.getRawAlgorithmName()) } } abstract class CipherAlgorithmPadding extends Crypto::NodeBase { - string getValue() {result = ""} + string getValue() { result = "" } } class CipherAlgorithmPaddingStringLiteral extends CipherAlgorithmPadding instanceof StringLiteral { - CipherAlgorithmPaddingStringLiteral() { cipher_padding(this.(StringLiteral).getValue().splitAt("/"))} + CipherAlgorithmPaddingStringLiteral() { + cipher_padding(this.(StringLiteral).getValue().splitAt("/")) + } override string toString() { result = this.(StringLiteral).toString() } - override string getValue() { result = this.(StringLiteral).getValue().regexpCapture(".*/.*/(.*)",1) } + override string getValue() { + result = this.(StringLiteral).getValue().regexpCapture(".*/.*/(.*)", 1) + } } private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { @@ -69,51 +93,59 @@ class CipherAlgorithmStringLiteral extends StringLiteral { module AlgorithmStringToFetchFlow = DataFlow::Global; - predicate algorithmStringToCipherInstanceArgFlow(string name, CipherAlgorithmStringLiteral origin, Expr arg) { + predicate algorithmStringToCipherInstanceArgFlow( + string name, CipherAlgorithmStringLiteral origin, Expr arg + ) { exists(CipherInstance sinkCall | origin.getValue().splitAt("/") = name and - arg = sinkCall.getAlgorithmArg() and - AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), DataFlow::exprNode(arg)) + arg = sinkCall and + AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), + DataFlow::exprNode(sinkCall.getAlgorithmArg())) ) } - - predicate modeStringToCipherInstanceArgFlow(string name, ModeOfOperationStringLiteral mode, Expr arg) { + predicate modeStringToCipherInstanceArgFlow( + string name, ModeOfOperationStringLiteral mode, Expr arg + ) { exists(CipherInstance sinkCall | mode.getRawAlgorithmName() = name and - arg = sinkCall.getAlgorithmArg() and - AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(mode), DataFlow::exprNode(arg)) + arg = sinkCall and + AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(mode), + DataFlow::exprNode(sinkCall.getAlgorithmArg())) ) } /** - * A class to represent when AES is used AND it has literal mode and padding provided - * this does not capture the use without + * A class to represent when AES is used + * AND currently it has literal mode and padding provided + * + * this currently does not capture the use without a literal + * though should be extended to */ -// class AESLiteral extends Crypto::SymmetricAlgorithm instanceof Expr { -// CipherAlgorithmStringLiteral alg; -// AESLiteral() { algorithmStringToCipherInstanceArgFlow("AES", alg, this) -// } + class AESAlgo extends Crypto::SymmetricAlgorithm instanceof Expr { + CipherAlgorithmStringLiteral alg; -// override Crypto::ModeOfOperation getModeOfOperation(){ modeStringToCipherInstanceArgFlow(result.getAlgorithmName(), result, this)} + AESAlgo() { algorithmStringToCipherInstanceArgFlow("AES", alg, this) } -// override Crypto::LocatableElement getOrigin(string name) { -// result = alg and name = alg.toString() -// } + override Crypto::ModeOfOperation getModeOfOperation() { + modeStringToCipherInstanceArgFlow(result.getAlgorithmName(), result, this) + } -// override string getAlgorithmName(){ result = "AES" } + override Crypto::LocatableElement getOrigin(string name) { + result = alg and name = alg.toString() + } -// override string getRawAlgorithmName(){ result = alg.getValue()} + override string getAlgorithmName() { result = "AES" } -// override Crypto::TSymmetricCipherFamilyType getSymmetricCipherFamilyType() { result instanceof Crypto::AES} + override string getRawAlgorithmName() { result = alg.getValue() } -// //temp hacks for testing -// override string getKeySize(Location location){ -// result = "" -// } + override Crypto::TSymmetricCipherFamilyType getSymmetricCipherFamilyType() { + result instanceof Crypto::AES + } -// override Crypto::TCipherStructure getCipherType(){ none()} -// } + //temp hacks for testing + override string getKeySize(Location location) { result = "" } - -} \ No newline at end of file + override Crypto::TCipherStructure getCipherType() { none() } + } +} From 59208bdb85adb0b5fb14c7b2d9bf94d393ff11ea Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Mon, 10 Feb 2025 12:22:22 -0500 Subject: [PATCH 015/336] Update JCA model to use shared lib --- java/ql/lib/experimental/Quantum/Base.qll | 327 ------------------ java/ql/lib/experimental/Quantum/Language.qll | 2 +- java/ql/lib/qlpack.yml | 1 + .../codeql/cryptography/Model.qll | 65 ++++ 4 files changed, 67 insertions(+), 328 deletions(-) delete mode 100644 java/ql/lib/experimental/Quantum/Base.qll diff --git a/java/ql/lib/experimental/Quantum/Base.qll b/java/ql/lib/experimental/Quantum/Base.qll deleted file mode 100644 index a14f3b6836ad..000000000000 --- a/java/ql/lib/experimental/Quantum/Base.qll +++ /dev/null @@ -1,327 +0,0 @@ -/** - * A language-independent library for reasoning about cryptography. - */ - - import codeql.util.Location - import codeql.util.Option - - signature module InputSig { - class LocatableElement { - Location getLocation(); - } - - class UnknownLocation instanceof Location; - - - } - - module CryptographyBase Input> { - final class LocatableElement = Input::LocatableElement; - - final class UnknownLocation = Input::UnknownLocation; - - final class UnknownPropertyValue extends string { - UnknownPropertyValue() { this = "" } - } - - abstract class NodeBase instanceof LocatableElement { - /** - * Returns a string representation of this node, usually the name of the operation/algorithm/property. - */ - abstract string toString(); - - /** - * Returns the location of this node in the code. - */ - Location getLocation() { result = super.getLocation() } - - /** - * Gets the origin of this node, e.g., a string literal in source describing it. - */ - LocatableElement getOrigin(string value) { none() } - - /** - * Returns the child of this node with the given edge name. - * - * This predicate is used by derived classes to construct the graph of cryptographic operations. - */ - NodeBase getChild(string edgeName) { none() } - - /** - * Defines properties of this node by name and either a value or location or both. - * - * This predicate is used by derived classes to construct the graph of cryptographic operations. - */ - predicate properties(string key, string value, Location location) { - key = "origin" and location = this.getOrigin(value).getLocation() - } - - /** - * Returns the parent of this node. - */ - final NodeBase getAParent() { result.getChild(_) = this } - } - - class Asset = NodeBase; - - /** - * A cryptographic operation, such as hashing or encryption. - */ - abstract class Operation extends Asset { - /** - * Gets the algorithm associated with this operation. - */ - abstract Algorithm getAlgorithm(); - - /** - * Gets the name of this operation, e.g., "hash" or "encrypt". - */ - abstract string getOperationName(); - - final override string toString() { result = this.getOperationName() } - - override NodeBase getChild(string edgeName) { - result = super.getChild(edgeName) - or - edgeName = "uses" and - if exists(this.getAlgorithm()) then result = this.getAlgorithm() else result = this - } - } - - abstract class Algorithm extends Asset { - /** - * Gets the name of this algorithm, e.g., "AES" or "SHA". - */ - abstract string getAlgorithmName(); - - /** - * Gets the raw name of this algorithm from source (no parsing or formatting) - */ - abstract string getRawAlgorithmName(); - - final override string toString() { result = this.getAlgorithmName() } - } - - /** - * A hashing operation that processes data to generate a hash value. - * This operation takes an input message of arbitrary content and length and produces a fixed-size - * hash value as the output using a specified hashing algorithm. - */ - abstract class HashOperation extends Operation { - abstract override HashAlgorithm getAlgorithm(); - - override string getOperationName() { result = "HASH" } - } - - // Rule: no newtype representing a type of algorithm should be modelled with multiple interfaces - // - // Example: HKDF and PKCS12KDF are both key derivation algorithms. - // However, PKCS12KDF also has a property: the iteration count. - // - // If we have HKDF and PKCS12KDF under TKeyDerivationType, - // someone modelling a library might try to make a generic identification of both of those algorithms. - // - // They will therefore not use the specialized type for PKCS12KDF, - // meaning "from PKCS12KDF algo select algo" will have no results. - // - newtype THashType = - // We're saying by this that all of these have an identical interface / properties / edges - MD5() or - SHA1() or - SHA256() or - SHA512() or - OtherHashType() - - /** - * A hashing algorithm that transforms variable-length input into a fixed-size hash value. - */ - abstract class HashAlgorithm extends Algorithm { - final predicate hashTypeToNameMapping(THashType type, string name) { - type instanceof MD5 and name = "MD5" - or - type instanceof SHA1 and name = "SHA-1" - or - type instanceof SHA256 and name = "SHA-256" - or - type instanceof SHA512 and name = "SHA-512" - or - type instanceof OtherHashType and name = this.getRawAlgorithmName() - } - - abstract THashType getHashType(); - - override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashType(), result) } - - /** - * Gets the raw name of this hash algorithm from source. - */ - override abstract string getRawAlgorithmName(); - } - - /** - * An operation that derives one or more keys from an input value. - */ - abstract class KeyDerivationOperation extends Operation { - override string getOperationName() { result = "KEY_DERIVATION" } - } - - /** - * An algorithm that derives one or more keys from an input value. - */ - abstract class KeyDerivationAlgorithm extends Algorithm { - abstract override string getAlgorithmName(); - } - - /** - * HKDF key derivation function - */ - abstract class HKDF extends KeyDerivationAlgorithm { - final override string getAlgorithmName() { result = "HKDF" } - - abstract HashAlgorithm getHashAlgorithm(); - - override NodeBase getChild(string edgeName) { - result = super.getChild(edgeName) - or - edgeName = "digest" and result = this.getHashAlgorithm() - } - } - - /** - * PKCS #12 key derivation function - */ - abstract class PKCS12KDF extends KeyDerivationAlgorithm { - final override string getAlgorithmName() { result = "PKCS12KDF" } - - abstract HashAlgorithm getHashAlgorithm(); - - override NodeBase getChild(string edgeName) { - result = super.getChild(edgeName) - or - edgeName = "digest" and result = this.getHashAlgorithm() - } - } - - /** - * Elliptic curve algorithm - */ - abstract class EllipticCurve extends Algorithm { - abstract string getVersion(Location location); - - abstract string getKeySize(Location location); - - override predicate properties(string key, string value, Location location) { - super.properties(key, value, location) - or - key = "version" and - if exists(this.getVersion(location)) - then value = this.getVersion(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - or - key = "key_size" and - if exists(this.getKeySize(location)) - then value = this.getKeySize(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - } - } - - /** - * An encryption operation that processes plaintext to generate a ciphertext. - * This operation takes an input message (plaintext) of arbitrary content and length and produces a ciphertext as the output using a specified encryption algorithm (with a mode and padding). - */ - abstract class EncryptionOperation extends Operation { - abstract override Algorithm getAlgorithm(); - - override string getOperationName() { result = "ENCRYPTION" } - } - -// newtype TBlockCipherFamilyType = -// // We're saying by this that all of these have an identical interface / properties / edges -// CBC() or ECB() - - -// abstract class BlockCiper extends Algorithm { - -// abstract string getKeySize(Location location); - -// abstract TBlockCipherFamilyType getBlockCipherFamilyType(); - -// override predicate properties(string key, string value, Location location) { -// super.properties(key, value, location) -// or -// key = "key_size" and -// if exists(this.getKeySize(location)) -// then value = this.getKeySize(location) -// else ( -// value instanceof UnknownPropertyValue and location instanceof UnknownLocation -// ) -// // other properties, like field type are possible, but not modeled until considered necessary -// } - -// override string getAlgorithmName() { result = this.getRawAlgorithmName().toUpperCase()} - -// override abstract string getRawAlgorithmName(); -// } - -newtype TModeOperation = -ECB() or OtherMode() - -abstract class ModeOfOperation extends Algorithm { - string getValue() {result = ""} - - final private predicate modeToNameMapping(TModeOperation type, string name) { - type instanceof ECB and name = "ECB" - or - type instanceof OtherMode and name = this.getRawAlgorithmName() - } - - abstract TModeOperation getModeType(); - - override string getAlgorithmName() { this.modeToNameMapping(this.getModeType(), result) } - -} - -newtype TCipherStructure = -Block() or Stream() - - newtype TSymmetricCipherFamilyType = -// We're saying by this that all of these have an identical interface / properties / edges -AES() - - /** - * Symmetric algorithms - */ - abstract class SymmetricAlgorithm extends Algorithm { - - - abstract TSymmetricCipherFamilyType getSymmetricCipherFamilyType(); - - abstract string getKeySize(Location location); - - abstract TCipherStructure getCipherType(); - - - //mode, padding scheme, keysize, block/stream, auth'd - //nodes = mode, padding scheme - //properties = keysize, block/stream, auth'd - //leave authd to lang specific - override predicate properties(string key, string value, Location location) { - super.properties(key, value, location) - or - key = "key_size" and - if exists(this.getKeySize(location)) - then value = this.getKeySize(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - //add more keys to index props - } - - abstract ModeOfOperation getModeOfOperation(); -} - } - \ No newline at end of file diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 246f2b86367c..485b3e716e69 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -1,4 +1,4 @@ -private import Base +private import codeql.cryptography.Model private import java as Lang /** diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index 18b74a919dd2..ae7f13ad7ab3 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -6,6 +6,7 @@ extractor: java library: true upgrades: upgrades dependencies: + codeql/cryptography: ${workspace} codeql/dataflow: ${workspace} codeql/mad: ${workspace} codeql/rangeanalysis: ${workspace} diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index eba25db60d24..aa626066684b 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -245,4 +245,69 @@ module CryptographyBase Input> { */ abstract override string getRawAlgorithmName(); } + + /** + * An encryption operation that processes plaintext to generate a ciphertext. + * This operation takes an input message (plaintext) of arbitrary content and length and produces a ciphertext as the output using a specified encryption algorithm (with a mode and padding). + */ + abstract class EncryptionOperation extends Operation { + abstract override Algorithm getAlgorithm(); + + override string getOperationName() { result = "ENCRYPTION" } + } + + newtype TModeOperation = + ECB() or + OtherMode() + + abstract class ModeOfOperation extends Algorithm { + string getValue() { result = "" } + + final private predicate modeToNameMapping(TModeOperation type, string name) { + type instanceof ECB and name = "ECB" + or + type instanceof OtherMode and name = this.getRawAlgorithmName() + } + + abstract TModeOperation getModeType(); + + override string getAlgorithmName() { this.modeToNameMapping(this.getModeType(), result) } + } + + newtype TCipherStructure = + Block() or + Stream() + + newtype TSymmetricCipherFamilyType = + // We're saying by this that all of these have an identical interface / properties / edges + AES() + + /** + * Symmetric algorithms + */ + abstract class SymmetricAlgorithm extends Algorithm { + abstract TSymmetricCipherFamilyType getSymmetricCipherFamilyType(); + + abstract string getKeySize(Location location); + + abstract TCipherStructure getCipherType(); + + //mode, padding scheme, keysize, block/stream, auth'd + //nodes = mode, padding scheme + //properties = keysize, block/stream, auth'd + //leave authd to lang specific + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + key = "key_size" and + if exists(this.getKeySize(location)) + then value = this.getKeySize(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + //add more keys to index props + } + + abstract ModeOfOperation getModeOfOperation(); + } } From 1a12fb309902fa6111c443051ab56359d6867f48 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Mon, 10 Feb 2025 13:49:32 -0500 Subject: [PATCH 016/336] Update JCA model, refactor modes --- java/ql/lib/experimental/Quantum/JCA.qll | 47 +++++++++++-------- .../codeql/cryptography/Model.qll | 1 + 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index f75cfe7fd083..4443ce85159c 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -47,16 +47,18 @@ module JCAModel { CipherAlgorithmStringLiteral() { cipher_names(this.getValue().splitAt("/")) } } - class ModeOfOperationStringLiteral extends Crypto::ModeOfOperation instanceof StringLiteral { + class ModeOfOperationStringLiteral extends StringLiteral { ModeOfOperationStringLiteral() { cipher_modes(this.(StringLiteral).getValue().splitAt("/")) } - override string getRawAlgorithmName() { - result = this.(StringLiteral).getValue().regexpCapture(".*/(.*)/.*", 1) - } + string getRawAlgorithmName() { result = this.getValue().regexpCapture(".*/(.*)/.*", 1) } + } - override string getValue() { - result = this.(StringLiteral).getValue().regexpCapture(".*/(.*)/.*", 1) - } + class ECBMode extends Crypto::ModeOfOperation { + ModeOfOperationStringLiteral mode; + + ECBMode() { modeStringToCipherInstanceArgFlow("ECB", mode, this) } + + override string getRawAlgorithmName() { result = mode.getRawAlgorithmName() } predicate modeToNameMapping(Crypto::TModeOperation type, string name) { name = "ECB" and type instanceof Crypto::ECB @@ -65,24 +67,26 @@ module JCAModel { override Crypto::TModeOperation getModeType() { modeToNameMapping(result, this.getRawAlgorithmName()) } + + override Crypto::LocatableElement getOrigin(string name) { + result = mode and name = mode.toString() + } } abstract class CipherAlgorithmPadding extends Crypto::NodeBase { string getValue() { result = "" } } - class CipherAlgorithmPaddingStringLiteral extends CipherAlgorithmPadding instanceof StringLiteral { - CipherAlgorithmPaddingStringLiteral() { - cipher_padding(this.(StringLiteral).getValue().splitAt("/")) - } - - override string toString() { result = this.(StringLiteral).toString() } - - override string getValue() { - result = this.(StringLiteral).getValue().regexpCapture(".*/.*/(.*)", 1) - } - } - + //todo refactor + // class CipherAlgorithmPaddingStringLiteral extends CipherAlgorithmPadding instanceof StringLiteral { + // CipherAlgorithmPaddingStringLiteral() { + // cipher_padding(this.(StringLiteral).getValue().splitAt("/")) + // } + // override string toString() { result = this.(StringLiteral).toString() } + // override string getValue() { + // result = this.(StringLiteral).getValue().regexpCapture(".*/.*/(.*)", 1) + // } + // } private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof CipherAlgorithmStringLiteral } @@ -108,6 +112,7 @@ module JCAModel { string name, ModeOfOperationStringLiteral mode, Expr arg ) { exists(CipherInstance sinkCall | + //consider if this should be a more specific predicate mode.getRawAlgorithmName() = name and arg = sinkCall and AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(mode), @@ -127,8 +132,10 @@ module JCAModel { AESAlgo() { algorithmStringToCipherInstanceArgFlow("AES", alg, this) } + //todo this is really not correct yet override Crypto::ModeOfOperation getModeOfOperation() { - modeStringToCipherInstanceArgFlow(result.getAlgorithmName(), result, this) + none() + //exists(Crypto::ModeOfOperation mode | mode = this and result = this) } override Crypto::LocatableElement getOrigin(string name) { diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index aa626066684b..2b2919b6d3f8 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -258,6 +258,7 @@ module CryptographyBase Input> { newtype TModeOperation = ECB() or + CBC() or OtherMode() abstract class ModeOfOperation extends Algorithm { From 4d447559457edacc18dad249417e2855e2b7269d Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Tue, 11 Feb 2025 15:37:15 +0100 Subject: [PATCH 017/336] Refactor Model and CBOM print queries --- cpp/ql/src/experimental/Quantum/CBOMGraph.ql | 48 --------- .../experimental/Quantum/PrintCBOMGraph.ql | 21 ++++ java/ql/lib/experimental/Quantum/JCA.qll | 27 ++--- .../experimental/Quantum/PrintCBOMGraph.ql | 21 ++++ .../codeql/cryptography/Model.qll | 101 +++++++++++++----- 5 files changed, 134 insertions(+), 84 deletions(-) delete mode 100644 cpp/ql/src/experimental/Quantum/CBOMGraph.ql create mode 100644 cpp/ql/src/experimental/Quantum/PrintCBOMGraph.ql create mode 100644 java/ql/src/experimental/Quantum/PrintCBOMGraph.ql diff --git a/cpp/ql/src/experimental/Quantum/CBOMGraph.ql b/cpp/ql/src/experimental/Quantum/CBOMGraph.ql deleted file mode 100644 index edcc40aca6a4..000000000000 --- a/cpp/ql/src/experimental/Quantum/CBOMGraph.ql +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @name "Print CBOM Graph" - * @description "Outputs a graph representation of the cryptographic bill of materials." - * @kind graph - * @id cbomgraph - */ - -import experimental.Quantum.Language - -string getPropertyString(Crypto::NodeBase node, string key) { - result = - strictconcat(any(string value, Location location, string parsed | - node.properties(key, value, location) and - parsed = "(" + value + "," + location.toString() + ")" - | - parsed - ), "," - ) -} - -string getLabel(Crypto::NodeBase node) { result = node.toString() } - -query predicate nodes(Crypto::NodeBase node, string key, string value) { - key = "semmle.label" and - value = getLabel(node) - or - // CodeQL's DGML output does not include a location - key = "Location" and - value = node.getLocation().toString() - or - // Known unknown edges should be reported as properties rather than edges - node = node.getChild(key) and - value = "" - or - // Report properties - value = getPropertyString(node, key) -} - -query predicate edges(Crypto::NodeBase source, Crypto::NodeBase target, string key, string value) { - key = "semmle.label" and - target = source.getChild(value) and - // Known unknowns are reported as properties rather than edges - not source = target -} - -query predicate graphProperties(string key, string value) { - key = "semmle.graphKind" and value = "graph" -} diff --git a/cpp/ql/src/experimental/Quantum/PrintCBOMGraph.ql b/cpp/ql/src/experimental/Quantum/PrintCBOMGraph.ql new file mode 100644 index 000000000000..d9658105aebf --- /dev/null +++ b/cpp/ql/src/experimental/Quantum/PrintCBOMGraph.ql @@ -0,0 +1,21 @@ +/** + * @name Print CBOM Graph + * @description Outputs a graph representation of the cryptographic bill of materials. + * This query only supports DGML output, as CodeQL DOT output omits properties. + * @kind graph + * @id cpp/print-cbom-graph + */ + +import experimental.Quantum.Language + +query predicate nodes(Crypto::NodeBase node, string key, string value) { + Crypto::nodes_graph_impl(node, key, value) +} + +query predicate edges(Crypto::NodeBase source, Crypto::NodeBase target, string key, string value) { + Crypto::edges_graph_impl(source, target, key, value) +} + +query predicate graphProperties(string key, string value) { + key = "semmle.graphKind" and value = "graph" +} diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 4443ce85159c..44a753bb7db2 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -7,12 +7,14 @@ module JCAModel { abstract class EncryptionOperation extends Crypto::EncryptionOperation { } //TODO PBEWith can have suffixes. how to do? enumerate? or match a pattern? + bindingset[algo] predicate cipher_names(string algo) { - algo = - [ - "AES", "AESWrap", "AESWrapPad", "ARCFOUR", "Blowfish", "ChaCha20", "ChaCha20-Poly1305", - "DES", "DESede", "DESedeWrap", "ECIES", "PBEWith", "RC2", "RC4", "RC5", "RSA" - ] + // "Standard names are not case-sensitive." + algo.toUpperCase() + .matches([ + "AES", "AESWrap", "AESWrapPad", "ARCFOUR", "Blowfish", "ChaCha20", "ChaCha20-Poly1305", + "DES", "DESede", "DESedeWrap", "ECIES", "PBEWith%", "RC2", "RC4", "RC5", "RSA" + ].toUpperCase()) } //TODO solve the fact that x is an int of various values. same as above... enumerate? @@ -33,9 +35,10 @@ module JCAModel { ] } - ////cipher specifics ---------------------------------------- - class CipherInstance extends Call { - CipherInstance() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "getInstance") } + class CipherGetInstanceCall extends Call { + CipherGetInstanceCall() { + this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "getInstance") + } Expr getAlgorithmArg() { result = this.getArgument(0) } } @@ -65,7 +68,7 @@ module JCAModel { } override Crypto::TModeOperation getModeType() { - modeToNameMapping(result, this.getRawAlgorithmName()) + this.modeToNameMapping(result, this.getRawAlgorithmName()) } override Crypto::LocatableElement getOrigin(string name) { @@ -91,7 +94,7 @@ module JCAModel { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof CipherAlgorithmStringLiteral } predicate isSink(DataFlow::Node sink) { - exists(CipherInstance call | sink.asExpr() = call.getAlgorithmArg()) + exists(CipherGetInstanceCall call | sink.asExpr() = call.getAlgorithmArg()) } } @@ -100,7 +103,7 @@ module JCAModel { predicate algorithmStringToCipherInstanceArgFlow( string name, CipherAlgorithmStringLiteral origin, Expr arg ) { - exists(CipherInstance sinkCall | + exists(CipherGetInstanceCall sinkCall | origin.getValue().splitAt("/") = name and arg = sinkCall and AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), @@ -111,7 +114,7 @@ module JCAModel { predicate modeStringToCipherInstanceArgFlow( string name, ModeOfOperationStringLiteral mode, Expr arg ) { - exists(CipherInstance sinkCall | + exists(CipherGetInstanceCall sinkCall | //consider if this should be a more specific predicate mode.getRawAlgorithmName() = name and arg = sinkCall and diff --git a/java/ql/src/experimental/Quantum/PrintCBOMGraph.ql b/java/ql/src/experimental/Quantum/PrintCBOMGraph.ql new file mode 100644 index 000000000000..063cda564b60 --- /dev/null +++ b/java/ql/src/experimental/Quantum/PrintCBOMGraph.ql @@ -0,0 +1,21 @@ +/** + * @name Print CBOM Graph + * @description Outputs a graph representation of the cryptographic bill of materials. + * This query only supports DGML output, as CodeQL DOT output omits properties. + * @kind graph + * @id java/print-cbom-graph + */ + +import experimental.Quantum.Language + +query predicate nodes(Crypto::NodeBase node, string key, string value) { + Crypto::nodes_graph_impl(node, key, value) +} + +query predicate edges(Crypto::NodeBase source, Crypto::NodeBase target, string key, string value) { + Crypto::edges_graph_impl(source, target, key, value) +} + +query predicate graphProperties(string key, string value) { + key = "semmle.graphKind" and value = "graph" +} diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 2b2919b6d3f8..ad117674dffe 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -22,6 +22,45 @@ module CryptographyBase Input> { UnknownPropertyValue() { this = "" } } + private string getPropertyAsGraphString(NodeBase node, string key) { + result = + strictconcat(any(string value, Location location, string parsed | + node.properties(key, value, location) and + parsed = "(" + value + "," + location.toString() + ")" + | + parsed + ), "," + ) + } + + predicate nodes_graph_impl(NodeBase node, string key, string value) { + key = "semmle.label" and + value = node.toString() + or + // CodeQL's DGML output does not include a location + key = "Location" and + value = node.getLocation().toString() + or + // Known unknown edges should be reported as properties rather than edges + node = node.getChild(key) and + value = "" + or + // Report properties + value = getPropertyAsGraphString(node, key) + } + + predicate edges_graph_impl(NodeBase source, NodeBase target, string key, string value) { + key = "semmle.label" and + target = source.getChild(value) and + // Known unknowns are reported as properties rather than edges + not source = target + } + + /** + * The base class for all cryptographic assets, such as operations and algorithms. + * + * Each `NodeBase` is a node in a graph of cryptographic operations, where the edges are the relationships between the nodes. + */ abstract class NodeBase instanceof LocatableElement { /** * Returns a string representation of this node, usually the name of the operation/algorithm/property. @@ -104,6 +143,7 @@ module CryptographyBase Input> { /** * A hashing operation that processes data to generate a hash value. + * * This operation takes an input message of arbitrary content and length and produces a fixed-size * hash value as the output using a specified hashing algorithm. */ @@ -113,19 +153,7 @@ module CryptographyBase Input> { override string getOperationName() { result = "HASH" } } - // Rule: no newtype representing a type of algorithm should be modelled with multiple interfaces - // - // Example: HKDF and PKCS12KDF are both key derivation algorithms. - // However, PKCS12KDF also has a property: the iteration count. - // - // If we have HKDF and PKCS12KDF under TKeyDerivationType, - // someone modelling a library might try to make a generic identification of both of those algorithms. - // - // They will therefore not use the specialized type for PKCS12KDF, - // meaning "from PKCS12KDF algo select algo" will have no results. - // newtype THashType = - // We're saying by this that all of these have an identical interface / properties / edges MD5() or SHA1() or SHA256() or @@ -197,8 +225,28 @@ module CryptographyBase Input> { } } - newtype TEllipticCurveFamilyType = - // We're saying by this that all of these have an identical interface / properties / edges + /* + * TODO: + * + * Rule: No newtype representing a type of algorithm should be modelled with multiple interfaces + * + * Example 1: HKDF and PKCS12KDF are both key derivation algorithms. + * However, PKCS12KDF also has a property: the iteration count. + * + * If we have HKDF and PKCS12KDF under TKeyDerivationType, + * someone modelling a library might try to make a generic identification of both of those algorithms. + * + * They will therefore not use the specialized type for PKCS12KDF, + * meaning "from PKCS12KDF algo select algo" will have no results. + * + * Example 2: Each type below represents a common family of elliptic curves, with a shared interface, i.e., + * predicates for library modellers to implement as well as the properties and edges reported. + */ + + /** + * Elliptic curve algorithms + */ + newtype TEllipticCurveFamily = NIST() or SEC() or NUMS() or @@ -211,13 +259,10 @@ module CryptographyBase Input> { ES() or OtherEllipticCurveFamilyType() - /** - * Elliptic curve algorithm - */ abstract class EllipticCurve extends Algorithm { abstract string getKeySize(Location location); - abstract TEllipticCurveFamilyType getCurveFamilyType(); + abstract TEllipticCurveFamily getCurveFamilyType(); override predicate properties(string key, string value, Location location) { super.properties(key, value, location) @@ -236,8 +281,10 @@ module CryptographyBase Input> { /** * Mandating that for Elliptic Curves specifically, users are responsible * for providing as the 'raw' name, the official name of the algorithm. + * * Casing doesn't matter, we will enforce further naming restrictions on * `getAlgorithmName` by default. + * * Rationale: elliptic curve names can have a lot of variation in their components * (e.g., "secp256r1" vs "P-256"), trying to produce generalized set of properties * is possible to capture all cases, but such modeling is likely not necessary. @@ -256,17 +303,20 @@ module CryptographyBase Input> { override string getOperationName() { result = "ENCRYPTION" } } + /** + * Block cipher modes of operation algorithms + */ newtype TModeOperation = ECB() or CBC() or OtherMode() abstract class ModeOfOperation extends Algorithm { - string getValue() { result = "" } - final private predicate modeToNameMapping(TModeOperation type, string name) { type instanceof ECB and name = "ECB" or + type instanceof CBC and name = "CBC" + or type instanceof OtherMode and name = this.getRawAlgorithmName() } @@ -275,17 +325,20 @@ module CryptographyBase Input> { override string getAlgorithmName() { this.modeToNameMapping(this.getModeType(), result) } } + /** + * A helper type for distinguishing between block and stream ciphers. + */ newtype TCipherStructure = Block() or Stream() - newtype TSymmetricCipherFamilyType = - // We're saying by this that all of these have an identical interface / properties / edges - AES() - /** * Symmetric algorithms */ + newtype TSymmetricCipherFamilyType = + AES() or + OtherSymmetricCipherFamilyType() + abstract class SymmetricAlgorithm extends Algorithm { abstract TSymmetricCipherFamilyType getSymmetricCipherFamilyType(); From 874e3b5e063bdd403264eea80e367d6a2f4eccdc Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Wed, 12 Feb 2025 17:58:15 +0100 Subject: [PATCH 018/336] Modify model to use newtypes, expand modeling --- cpp/ql/lib/experimental/Quantum/OpenSSL.qll | 204 ++++++-- java/ql/lib/experimental/Quantum/JCA.qll | 143 +++--- java/ql/src/experimental/Quantum/Test.ql | 7 +- .../codeql/cryptography/Model.qll | 467 ++++++++++++++++-- 4 files changed, 665 insertions(+), 156 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll index bf38e5c0ab5d..cb19092f3fd7 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll @@ -4,78 +4,172 @@ import semmle.code.cpp.dataflow.new.DataFlow module OpenSSLModel { import Language - abstract class KeyDerivationOperation extends Crypto::KeyDerivationOperation { } + class FunctionCallOrMacroAccess extends Element { + FunctionCallOrMacroAccess() { this instanceof FunctionCall or this instanceof MacroAccess } + + string getTargetName() { + result = this.(FunctionCall).getTarget().getName() + or + result = this.(MacroAccess).getMacroName() + } + } + + /** + * Hash function references in OpenSSL. + */ + predicate hash_ref_type_mapping_known(string name, Crypto::THashType algo) { + // `ma` name has an LN_ or SN_ prefix, which we want to ignore + // capture any name after the _ prefix using regex matching + name = ["sha1", "sha160"] and algo instanceof Crypto::SHA1 + or + name = ["sha224", "sha256", "sha384", "sha512"] and algo instanceof Crypto::SHA2 + or + name = ["sha3-224", "sha3-256", "sha3-384", "sha3-512"] and algo instanceof Crypto::SHA3 + or + name = "md2" and algo instanceof Crypto::MD2 + or + name = "md4" and algo instanceof Crypto::MD4 + or + name = "md5" and algo instanceof Crypto::MD5 + or + name = "ripemd160" and algo instanceof Crypto::RIPEMD160 + or + name = "whirlpool" and algo instanceof Crypto::WHIRLPOOL + } + + predicate hash_ref_type_mapping(FunctionCallOrMacroAccess ref, string name, Crypto::THashType algo) { + name = ref.getTargetName().regexpCapture("(?:SN_|LN_|EVP_)([a-z0-9]+)", 1) and + hash_ref_type_mapping_known(name, algo) + } + + class HashAlgorithmRef extends Crypto::HashAlgorithm { + FunctionCallOrMacroAccess instance; + + HashAlgorithmRef() { + this = Crypto::THashAlgorithm(instance) and + hash_ref_type_mapping(instance, _, _) + } + + override string getSHA2OrSHA3DigestSize(Location location) { + ( + this.getHashType() instanceof Crypto::SHA2 or + this.getHashType() instanceof Crypto::SHA3 + ) and + exists(string name | + hash_ref_type_mapping(instance, name, this.getHashType()) and + result = name.regexpFind("\\d{3}", 0, _) and + location = instance.getLocation() + ) + } - class SHA1Algo extends Crypto::HashAlgorithm instanceof MacroAccess { - SHA1Algo() { this.getMacro().getName() = "SN_sha1" } + override string getRawAlgorithmName() { result = instance.getTargetName() } - override string getRawAlgorithmName() { result = "SN_sha1" } + override Crypto::THashType getHashType() { hash_ref_type_mapping(instance, _, result) } - override Crypto::THashType getHashType() { result instanceof Crypto::SHA1 } + Element getInstance() { result = instance } + + override Location getLocation() { result = instance.getLocation() } } + /** + * Data-flow configuration for key derivation algorithm flow to EVP_KDF_derive. + */ module AlgorithmToEVPKeyDeriveConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source.asExpr() instanceof KeyDerivationAlgorithm } + predicate isSource(DataFlow::Node source) { + source.asExpr() = any(KeyDerivationAlgorithm a).getInstance() + } predicate isSink(DataFlow::Node sink) { - exists(EVP_KDF_derive kdo | sink.asExpr() = kdo.getAlgorithmArg()) + exists(EVP_KDF_derive kdo | + sink.asExpr() = kdo.getAlgorithmArg() + or + sink.asExpr() = kdo.getContextArg() // via `EVP_KDF_CTX_set_params` + ) + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + none() // TODO } } module AlgorithmToEVPKeyDeriveFlow = DataFlow::Global; - predicate algorithm_to_EVP_KDF_derive(Crypto::Algorithm algo, EVP_KDF_derive derive) { - algo.(Expr).getEnclosingFunction() = derive.(Expr).getEnclosingFunction() + predicate algorithm_to_EVP_KDF_derive(KeyDerivationAlgorithm algo, EVP_KDF_derive derive) { + none() } - class EVP_KDF_derive extends KeyDerivationOperation instanceof FunctionCall { - EVP_KDF_derive() { this.getTarget().getName() = "EVP_KDF_derive" } + /** + * Key derivation operation (e.g., `EVP_KDF_derive`) + */ + abstract class KeyDerivationOperation extends Crypto::KeyDerivationOperation { } + + class EVP_KDF_derive extends KeyDerivationOperation { + FunctionCall instance; + + EVP_KDF_derive() { + this = Crypto::TKeyDerivationOperation(instance) and + instance.getTarget().getName() = "EVP_KDF_derive" + } override Crypto::Algorithm getAlgorithm() { algorithm_to_EVP_KDF_derive(result, this) } - Expr getAlgorithmArg() { result = this.(FunctionCall).getArgument(3) } + Expr getAlgorithmArg() { result = instance.getArgument(3) } + + Expr getContextArg() { result = instance.getArgument(0) } } - abstract class KeyDerivationAlgorithm extends Crypto::KeyDerivationAlgorithm { } + /** + * Key derivation algorithm nodes + */ + abstract class KeyDerivationAlgorithm extends Crypto::KeyDerivationAlgorithm { + abstract Expr getInstance(); + } + /** + * `EVP_KDF_fetch` returns a key derivation algorithm. + */ class EVP_KDF_fetch_Call extends FunctionCall { EVP_KDF_fetch_Call() { this.getTarget().getName() = "EVP_KDF_fetch" } Expr getAlgorithmArg() { result = this.getArgument(1) } } - predicate kdf_names(string algo) { algo = ["HKDF", "PKCS12KDF"] } - - class KDFAlgorithmStringLiteral extends Crypto::NodeBase instanceof StringLiteral { - KDFAlgorithmStringLiteral() { kdf_names(this.getValue().toUpperCase()) } + class EVP_KDF_fetch_AlgorithmArg extends Expr { + EVP_KDF_fetch_AlgorithmArg() { exists(EVP_KDF_fetch_Call call | this = call.getAlgorithmArg()) } + } - override string toString() { result = this.(StringLiteral).toString() } + predicate kdf_names(string algo) { algo = ["HKDF", "PKCS12KDF", "PBKDF2"] } - string getValue() { result = this.(StringLiteral).getValue() } + class KDFAlgorithmStringLiteral extends StringLiteral { + KDFAlgorithmStringLiteral() { kdf_names(this.getValue().toUpperCase()) } } private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof KDFAlgorithmStringLiteral } - predicate isSink(DataFlow::Node sink) { - exists(EVP_KDF_fetch_Call call | sink.asExpr() = call.getAlgorithmArg()) - } + predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof EVP_KDF_fetch_AlgorithmArg } } module AlgorithmStringToFetchFlow = DataFlow::Global; - predicate algorithmStringToKDFFetchArgFlow(string name, KDFAlgorithmStringLiteral origin, Expr arg) { - exists(EVP_KDF_fetch_Call sinkCall | - origin.getValue().toUpperCase() = name and - arg = sinkCall.getAlgorithmArg() and - AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), DataFlow::exprNode(arg)) - ) + predicate algorithmStringToKDFFetchArgFlow( + string name, KDFAlgorithmStringLiteral origin, EVP_KDF_fetch_AlgorithmArg arg + ) { + origin.getValue().toUpperCase() = name and + AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), DataFlow::exprNode(arg)) } - class HKDF extends KeyDerivationAlgorithm, Crypto::HKDF instanceof Expr { + /** + * HKDF key derivation algorithm. + */ + class HKDF extends KeyDerivationAlgorithm, Crypto::HKDF { KDFAlgorithmStringLiteral origin; + EVP_KDF_fetch_AlgorithmArg instance; - HKDF() { algorithmStringToKDFFetchArgFlow("HKDF", origin, this) } + HKDF() { + this = Crypto::TKeyDerivationAlgorithm(instance) and + algorithmStringToKDFFetchArgFlow("HKDF", origin, instance) + } override string getRawAlgorithmName() { result = origin.getValue() } @@ -84,19 +178,61 @@ module OpenSSLModel { override Crypto::LocatableElement getOrigin(string name) { result = origin and name = origin.toString() } + + override Expr getInstance() { result = origin } } - class PKCS12KDF extends KeyDerivationAlgorithm, Crypto::PKCS12KDF instanceof Expr { + /** + * PBKDF2 key derivation algorithm. + */ + class PBKDF2 extends KeyDerivationAlgorithm, Crypto::PBKDF2 { KDFAlgorithmStringLiteral origin; + EVP_KDF_fetch_AlgorithmArg instance; - PKCS12KDF() { algorithmStringToKDFFetchArgFlow("PKCS12KDF", origin, this) } + PBKDF2() { + this = Crypto::TKeyDerivationAlgorithm(instance) and + algorithmStringToKDFFetchArgFlow("PBKDF2", origin, instance) + } override string getRawAlgorithmName() { result = origin.getValue() } - override Crypto::HashAlgorithm getHashAlgorithm() { none() } + override string getIterationCount(Location location) { none() } // TODO + + override string getKeyLength(Location location) { none() } // TODO + + override Crypto::HashAlgorithm getHashAlgorithm() { none() } // TODO + + override Crypto::LocatableElement getOrigin(string name) { + result = origin and name = origin.toString() + } - override Crypto::NodeBase getOrigin(string name) { + override Expr getInstance() { result = instance } + } + + /** + * PKCS12KDF key derivation algorithm. + */ + class PKCS12KDF extends KeyDerivationAlgorithm, Crypto::PKCS12KDF { + KDFAlgorithmStringLiteral origin; + EVP_KDF_fetch_AlgorithmArg instance; + + PKCS12KDF() { + this = Crypto::TKeyDerivationAlgorithm(instance) and + algorithmStringToKDFFetchArgFlow("PKCS12KDF", origin, instance) + } + + override string getRawAlgorithmName() { result = origin.getValue() } + + override string getIterationCount(Location location) { none() } // TODO + + override string getIDByte(Location location) { none() } // TODO + + override Crypto::HashAlgorithm getHashAlgorithm() { none() } // TODO + + override Crypto::LocatableElement getOrigin(string name) { result = origin and name = origin.toString() } + + override Expr getInstance() { result = instance } } } diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 44a753bb7db2..807dec96ba40 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -35,6 +35,19 @@ module JCAModel { ] } + /** + * this may be specified either in the ALG/MODE/PADDING or just ALG format + */ + class CipherStringLiteral extends StringLiteral { + CipherStringLiteral() { cipher_names(this.getValue().splitAt("/")) } + + string getAlgorithmName() { result = this.getValue().splitAt("/", 0) } + + string getMode() { result = this.getValue().splitAt("/", 1) } + + string getPadding() { result = this.getValue().splitAt("/", 2) } + } + class CipherGetInstanceCall extends Call { CipherGetInstanceCall() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "getInstance") @@ -43,41 +56,48 @@ module JCAModel { Expr getAlgorithmArg() { result = this.getArgument(0) } } - /** - * this may be specified either in the ALG/MODE/PADDING or just ALG format - */ - class CipherAlgorithmStringLiteral extends StringLiteral { - CipherAlgorithmStringLiteral() { cipher_names(this.getValue().splitAt("/")) } + private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof CipherStringLiteral } + + predicate isSink(DataFlow::Node sink) { + exists(CipherGetInstanceCall call | sink.asExpr() = call.getAlgorithmArg()) + } } - class ModeOfOperationStringLiteral extends StringLiteral { - ModeOfOperationStringLiteral() { cipher_modes(this.(StringLiteral).getValue().splitAt("/")) } + module AlgorithmStringToFetchFlow = DataFlow::Global; - string getRawAlgorithmName() { result = this.getValue().regexpCapture(".*/(.*)/.*", 1) } + class CipherGetInstanceAlgorithmArg extends Expr { + CipherGetInstanceAlgorithmArg() { + exists(CipherGetInstanceCall call | this = call.getArgument(0)) + } + + StringLiteral getOrigin() { + AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(result), DataFlow::exprNode(this)) + } } - class ECBMode extends Crypto::ModeOfOperation { - ModeOfOperationStringLiteral mode; + class ModeStringLiteral extends Crypto::ModeOfOperation { + CipherStringLiteral instance; - ECBMode() { modeStringToCipherInstanceArgFlow("ECB", mode, this) } + ModeStringLiteral() { + this = Crypto::TModeOfOperationAlgorithm(instance) and + exists(instance.getMode()) and + instance = any(CipherGetInstanceAlgorithmArg call).getOrigin() + } - override string getRawAlgorithmName() { result = mode.getRawAlgorithmName() } + override Location getLocation() { result = instance.getLocation() } - predicate modeToNameMapping(Crypto::TModeOperation type, string name) { - name = "ECB" and type instanceof Crypto::ECB - } + override string getRawAlgorithmName() { result = instance.getMode() } - override Crypto::TModeOperation getModeType() { - this.modeToNameMapping(result, this.getRawAlgorithmName()) + predicate modeToNameMapping(Crypto::TModeOperationType type, string name) { + super.modeToNameMapping(type, name) } - override Crypto::LocatableElement getOrigin(string name) { - result = mode and name = mode.toString() + override Crypto::TModeOperationType getModeType() { + this.modeToNameMapping(result, instance.getMode().toUpperCase()) } - } - abstract class CipherAlgorithmPadding extends Crypto::NodeBase { - string getValue() { result = "" } + CipherStringLiteral getInstance() { result = instance } } //todo refactor @@ -90,39 +110,6 @@ module JCAModel { // result = this.(StringLiteral).getValue().regexpCapture(".*/.*/(.*)", 1) // } // } - private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { src.asExpr() instanceof CipherAlgorithmStringLiteral } - - predicate isSink(DataFlow::Node sink) { - exists(CipherGetInstanceCall call | sink.asExpr() = call.getAlgorithmArg()) - } - } - - module AlgorithmStringToFetchFlow = DataFlow::Global; - - predicate algorithmStringToCipherInstanceArgFlow( - string name, CipherAlgorithmStringLiteral origin, Expr arg - ) { - exists(CipherGetInstanceCall sinkCall | - origin.getValue().splitAt("/") = name and - arg = sinkCall and - AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), - DataFlow::exprNode(sinkCall.getAlgorithmArg())) - ) - } - - predicate modeStringToCipherInstanceArgFlow( - string name, ModeOfOperationStringLiteral mode, Expr arg - ) { - exists(CipherGetInstanceCall sinkCall | - //consider if this should be a more specific predicate - mode.getRawAlgorithmName() = name and - arg = sinkCall and - AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(mode), - DataFlow::exprNode(sinkCall.getAlgorithmArg())) - ) - } - /** * A class to represent when AES is used * AND currently it has literal mode and padding provided @@ -130,32 +117,48 @@ module JCAModel { * this currently does not capture the use without a literal * though should be extended to */ - class AESAlgo extends Crypto::SymmetricAlgorithm instanceof Expr { - CipherAlgorithmStringLiteral alg; + class CipherAlgorithm extends Crypto::SymmetricAlgorithm { + CipherStringLiteral origin; + CipherGetInstanceAlgorithmArg instance; + + CipherAlgorithm() { + this = Crypto::TSymmetricAlgorithm(instance) and + instance.getOrigin() = origin + } - AESAlgo() { algorithmStringToCipherInstanceArgFlow("AES", alg, this) } + override Location getLocation() { result = instance.getLocation() } - //todo this is really not correct yet override Crypto::ModeOfOperation getModeOfOperation() { - none() - //exists(Crypto::ModeOfOperation mode | mode = this and result = this) + result.(ModeStringLiteral).getInstance() = origin } override Crypto::LocatableElement getOrigin(string name) { - result = alg and name = alg.toString() + result = origin and name = origin.toString() } - override string getAlgorithmName() { result = "AES" } - - override string getRawAlgorithmName() { result = alg.getValue() } + override string getRawAlgorithmName() { result = origin.getValue() } - override Crypto::TSymmetricCipherFamilyType getSymmetricCipherFamilyType() { - result instanceof Crypto::AES + override Crypto::TSymmetricCipherType getCipherFamily() { + this.cipherNameMapping(result, origin.getAlgorithmName()) } - //temp hacks for testing - override string getKeySize(Location location) { result = "" } + override string getKeySize(Location location) { none() } - override Crypto::TCipherStructure getCipherType() { none() } + bindingset[name] + private predicate cipherNameMappingKnown(Crypto::TSymmetricCipherType type, string name) { + name = "AES" and + type instanceof Crypto::AES + or + name = "RC4" and + type instanceof Crypto::RC4 + } + + bindingset[name] + predicate cipherNameMapping(Crypto::TSymmetricCipherType type, string name) { + this.cipherNameMappingKnown(type, name) + or + not this.cipherNameMappingKnown(_, name) and + type instanceof Crypto::OtherSymmetricCipherType + } } } diff --git a/java/ql/src/experimental/Quantum/Test.ql b/java/ql/src/experimental/Quantum/Test.ql index f35336a846f2..f3ae23a2ccac 100644 --- a/java/ql/src/experimental/Quantum/Test.ql +++ b/java/ql/src/experimental/Quantum/Test.ql @@ -2,7 +2,8 @@ * @name "PQC Test" */ - import experimental.Quantum.Language +import experimental.Quantum.Language -from JCAModel::AESLiteral l -select l, l.getAlg(), l.getMode().getValue(), l.getPadding().getValue() \ No newline at end of file +from Crypto::SymmetricAlgorithm a, Crypto::ModeOfOperation mode +where a.getModeOfOperation() = mode +select a, a.getAlgorithmName(), a.getRawAlgorithmName(), mode, mode.getAlgorithmName() diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index ad117674dffe..dd570a89ef6e 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -56,12 +56,22 @@ module CryptographyBase Input> { not source = target } + newtype TNode = + THashOperation(LocatableElement e) or + THashAlgorithm(LocatableElement e) or + TKeyDerivationOperation(LocatableElement e) or + TKeyDerivationAlgorithm(LocatableElement e) or + TEncryptionOperation(LocatableElement e) or + TSymmetricAlgorithm(LocatableElement e) or + TEllipticCurveAlgorithm(LocatableElement e) or + TModeOfOperationAlgorithm(LocatableElement e) + /** * The base class for all cryptographic assets, such as operations and algorithms. * * Each `NodeBase` is a node in a graph of cryptographic operations, where the edges are the relationships between the nodes. */ - abstract class NodeBase instanceof LocatableElement { + abstract class NodeBase extends TNode { /** * Returns a string representation of this node, usually the name of the operation/algorithm/property. */ @@ -70,7 +80,7 @@ module CryptographyBase Input> { /** * Returns the location of this node in the code. */ - Location getLocation() { result = super.getLocation() } + abstract Location getLocation(); /** * Gets the origin of this node, e.g., a string literal in source describing it. @@ -128,6 +138,8 @@ module CryptographyBase Input> { } abstract class Algorithm extends Asset { + final override string toString() { result = this.getAlgorithmType() } + /** * Gets the name of this algorithm, e.g., "AES" or "SHA". */ @@ -138,7 +150,20 @@ module CryptographyBase Input> { */ abstract string getRawAlgorithmName(); - final override string toString() { result = this.getAlgorithmName() } + /** + * Gets the type of this algorithm, e.g., "hash" or "key derivation". + */ + abstract string getAlgorithmType(); + + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + // [ONLY_KNOWN] + key = "name" and value = this.getAlgorithmName() and location = this.getLocation() + or + // [ONLY_KNOWN] + key = "raw_name" and value = this.getRawAlgorithmName() and location = this.getLocation() + } } /** @@ -147,81 +172,318 @@ module CryptographyBase Input> { * This operation takes an input message of arbitrary content and length and produces a fixed-size * hash value as the output using a specified hashing algorithm. */ - abstract class HashOperation extends Operation { + abstract class HashOperation extends Operation, THashOperation { abstract override HashAlgorithm getAlgorithm(); - override string getOperationName() { result = "HASH" } + override string getOperationName() { result = "HashOperation" } } newtype THashType = + MD2() or + MD4() or MD5() or SHA1() or - SHA256() or - SHA512() or + SHA2() or + SHA3() or + RIPEMD160() or + WHIRLPOOL() or OtherHashType() /** * A hashing algorithm that transforms variable-length input into a fixed-size hash value. */ - abstract class HashAlgorithm extends Algorithm { + abstract class HashAlgorithm extends Algorithm, THashAlgorithm { + override string getAlgorithmType() { result = "HashAlgorithm" } + final predicate hashTypeToNameMapping(THashType type, string name) { + type instanceof MD2 and name = "MD2" + or + type instanceof MD4 and name = "MD4" + or type instanceof MD5 and name = "MD5" or - type instanceof SHA1 and name = "SHA-1" + type instanceof SHA1 and name = "SHA1" + or + type instanceof SHA2 and name = "SHA2" or - type instanceof SHA256 and name = "SHA-256" + type instanceof SHA3 and name = "SHA3" or - type instanceof SHA512 and name = "SHA-512" + type instanceof RIPEMD160 and name = "RIPEMD160" + or + type instanceof WHIRLPOOL and name = "WHIRLPOOL" or type instanceof OtherHashType and name = this.getRawAlgorithmName() } + /** + * Gets the type of this hashing algorithm, e.g., MD5 or SHA. + * + * When modeling a new hashing algorithm, use this predicate to specify the type of the algorithm. + */ abstract THashType getHashType(); override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashType(), result) } + + /** + * Gets the digest size of SHA2 or SHA3 algorithms. + * + * This predicate does not need to hold for other algorithms, + * as the digest size is already known based on the algorithm itself. + * + * For `OtherHashType` algorithms where a digest size should be reported, `THashType` + * should be extended to explicitly model that algorithm. If the algorithm has variable + * or multiple digest size variants, a similar predicate to this one must be defined + * for that algorithm to report the digest size. + */ + abstract string getSHA2OrSHA3DigestSize(Location location); + + bindingset[type] + private string getDigestSize(THashType type, Location location) { + type instanceof MD2 and result = "128" + or + type instanceof MD4 and result = "128" + or + type instanceof MD5 and result = "128" + or + type instanceof SHA1 and result = "160" + or + type instanceof SHA2 and result = this.getSHA2OrSHA3DigestSize(location) + or + type instanceof SHA3 and result = this.getSHA2OrSHA3DigestSize(location) + or + type instanceof RIPEMD160 and result = "160" + or + type instanceof WHIRLPOOL and result = "512" + } + + final override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + // [KNOWN_OR_UNKNOWN] + key = "digest_size" and + if exists(this.getDigestSize(this.getHashType(), location)) + then value = this.getDigestSize(this.getHashType(), location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + } } /** * An operation that derives one or more keys from an input value. */ - abstract class KeyDerivationOperation extends Operation { - override string getOperationName() { result = "KEY_DERIVATION" } + abstract class KeyDerivationOperation extends Operation, TKeyDerivationOperation { + final override Location getLocation() { + exists(LocatableElement le | this = TKeyDerivationOperation(le) and result = le.getLocation()) + } + + override string getOperationName() { result = "KeyDerivationOperation" } } /** * An algorithm that derives one or more keys from an input value. + * + * Only use this class to model UNKNOWN key derivation algorithms. + * + * For known algorithms, use the specialized classes, e.g., `HKDF` and `PKCS12KDF`. */ - abstract class KeyDerivationAlgorithm extends Algorithm { - abstract override string getAlgorithmName(); + abstract class KeyDerivationAlgorithm extends Algorithm, TKeyDerivationAlgorithm { + final override Location getLocation() { + exists(LocatableElement le | this = TKeyDerivationAlgorithm(le) and result = le.getLocation()) + } + + override string getAlgorithmType() { result = "KeyDerivationAlgorithm" } + + override string getAlgorithmName() { result = this.getRawAlgorithmName() } } /** - * HKDF key derivation function + * An algorithm that derives one or more keys from an input value, using a configurable digest algorithm. */ - abstract class HKDF extends KeyDerivationAlgorithm { - final override string getAlgorithmName() { result = "HKDF" } - + abstract private class KeyDerivationWithDigestParameter extends KeyDerivationAlgorithm { abstract HashAlgorithm getHashAlgorithm(); override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) or - edgeName = "digest" and result = this.getHashAlgorithm() + ( + // [KNOWN_OR_UNKNOWN] + edgeName = "uses" and + if exists(this.getHashAlgorithm()) then result = this.getHashAlgorithm() else result = this + ) } } /** - * PKCS #12 key derivation function + * HKDF key derivation function */ - abstract class PKCS12KDF extends KeyDerivationAlgorithm { - final override string getAlgorithmName() { result = "PKCS12KDF" } + abstract class HKDF extends KeyDerivationWithDigestParameter { + final override string getAlgorithmName() { result = "HKDF" } + } - abstract HashAlgorithm getHashAlgorithm(); + /** + * PBKDF2 key derivation function + */ + abstract class PBKDF2 extends KeyDerivationWithDigestParameter { + final override string getAlgorithmName() { result = "PBKDF2" } - override NodeBase getChild(string edgeName) { - result = super.getChild(edgeName) + /** + * Gets the iteration count of this key derivation algorithm. + */ + abstract string getIterationCount(Location location); + + /** + * Gets the bit-length of the derived key. + */ + abstract string getKeyLength(Location location); + + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) or - edgeName = "digest" and result = this.getHashAlgorithm() + ( + // [KNOWN_OR_UNKNOWN] + key = "iterations" and + if exists(this.getIterationCount(location)) + then value = this.getIterationCount(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + ) + or + ( + // [KNOWN_OR_UNKNOWN] + key = "key_len" and + if exists(this.getKeyLength(location)) + then value = this.getKeyLength(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + ) + } + } + + /** + * PKCS12KDF key derivation function + */ + abstract class PKCS12KDF extends KeyDerivationWithDigestParameter { + override string getAlgorithmName() { result = "PKCS12KDF" } + + /** + * Gets the iteration count of this key derivation algorithm. + */ + abstract string getIterationCount(Location location); + + /** + * Gets the raw ID argument specifying the intended use of the derived key. + * + * The intended use is defined in RFC 7292, appendix B.3, as follows: + * + * This standard specifies 3 different values for the ID byte mentioned above: + * + * 1. If ID=1, then the pseudorandom bits being produced are to be used + * as key material for performing encryption or decryption. + * + * 2. If ID=2, then the pseudorandom bits being produced are to be used + * as an IV (Initial Value) for encryption or decryption. + * + * 3. If ID=3, then the pseudorandom bits being produced are to be used + * as an integrity key for MACing. + */ + abstract string getIDByte(Location location); + + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + ( + // [KNOWN_OR_UNKNOWN] + key = "iterations" and + if exists(this.getIterationCount(location)) + then value = this.getIterationCount(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + ) + or + ( + // [KNOWN_OR_UNKNOWN] + key = "id_byte" and + if exists(this.getIDByte(location)) + then value = this.getIDByte(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + ) + } + } + + /** + * scrypt key derivation function + */ + abstract class SCRYPT extends KeyDerivationAlgorithm { + final override string getAlgorithmName() { result = "scrypt" } + + /** + * Gets the iteration count (`N`) argument + */ + abstract string get_N(Location location); + + /** + * Gets the block size (`r`) argument + */ + abstract string get_r(Location location); + + /** + * Gets the parallelization factor (`p`) argument + */ + abstract string get_p(Location location); + + /** + * Gets the derived key length argument + */ + abstract string getDerivedKeyLength(Location location); + + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + ( + // [KNOWN_OR_UNKNOWN] + key = "N" and + if exists(this.get_N(location)) + then value = this.get_N(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + ) + or + ( + // [KNOWN_OR_UNKNOWN] + key = "r" and + if exists(this.get_r(location)) + then value = this.get_r(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + ) + or + ( + // [KNOWN_OR_UNKNOWN] + key = "p" and + if exists(this.get_p(location)) + then value = this.get_p(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + ) + or + ( + // [KNOWN_OR_UNKNOWN] + key = "key_len" and + if exists(this.getDerivedKeyLength(location)) + then value = this.getDerivedKeyLength(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + ) } } @@ -246,7 +508,7 @@ module CryptographyBase Input> { /** * Elliptic curve algorithms */ - newtype TEllipticCurveFamily = + newtype TEllipticCurveType = NIST() or SEC() or NUMS() or @@ -257,16 +519,17 @@ module CryptographyBase Input> { C2() or SM2() or ES() or - OtherEllipticCurveFamilyType() + OtherEllipticCurveType() - abstract class EllipticCurve extends Algorithm { + abstract class EllipticCurve extends Algorithm, TEllipticCurveAlgorithm { abstract string getKeySize(Location location); - abstract TEllipticCurveFamily getCurveFamilyType(); + abstract TEllipticCurveType getCurveFamily(); override predicate properties(string key, string value, Location location) { super.properties(key, value, location) or + // [KNOWN_OR_UNKNOWN] key = "key_size" and if exists(this.getKeySize(location)) then value = this.getKeySize(location) @@ -306,62 +569,168 @@ module CryptographyBase Input> { /** * Block cipher modes of operation algorithms */ - newtype TModeOperation = + newtype TModeOperationType = ECB() or CBC() or + CFB() or + OFB() or + CTR() or + GCM() or + CCM() or + XTS() or OtherMode() abstract class ModeOfOperation extends Algorithm { - final private predicate modeToNameMapping(TModeOperation type, string name) { + override string getAlgorithmType() { result = "ModeOfOperation" } + + /** + * Gets the type of this mode of operation, e.g., "ECB" or "CBC". + * + * When modeling a new mode of operation, use this predicate to specify the type of the mode. + */ + abstract TModeOperationType getModeType(); + + bindingset[type] + final predicate modeToNameMapping(TModeOperationType type, string name) { type instanceof ECB and name = "ECB" or type instanceof CBC and name = "CBC" or + type instanceof CFB and name = "CFB" + or + type instanceof OFB and name = "OFB" + or + type instanceof CTR and name = "CTR" + or + type instanceof GCM and name = "GCM" + or + type instanceof CCM and name = "CCM" + or + type instanceof XTS and name = "XTS" + or type instanceof OtherMode and name = this.getRawAlgorithmName() } - abstract TModeOperation getModeType(); - override string getAlgorithmName() { this.modeToNameMapping(this.getModeType(), result) } } /** * A helper type for distinguishing between block and stream ciphers. */ - newtype TCipherStructure = + newtype TCipherStructureType = Block() or - Stream() + Stream() or + UnknownCipherStructureType() + + private string getCipherStructureTypeString(TCipherStructureType type) { + type instanceof Block and result = "Block" + or + type instanceof Stream and result = "Stream" + or + type instanceof UnknownCipherStructureType and result instanceof UnknownPropertyValue + } /** * Symmetric algorithms */ - newtype TSymmetricCipherFamilyType = + newtype TSymmetricCipherType = AES() or - OtherSymmetricCipherFamilyType() + Camellia() or + DES() or + TripleDES() or + IDEA() or + CAST5() or + ChaCha20() or + RC4() or + RC5() or + OtherSymmetricCipherType() abstract class SymmetricAlgorithm extends Algorithm { - abstract TSymmetricCipherFamilyType getSymmetricCipherFamilyType(); + final TCipherStructureType getCipherStructure() { + this.cipherFamilyToNameAndStructure(this.getCipherFamily(), _, result) + } + + final override string getAlgorithmName() { + this.cipherFamilyToNameAndStructure(this.getCipherFamily(), result, _) + } + final override string getAlgorithmType() { result = "SymmetricAlgorithm" } + + /** + * Gets the key size of this symmetric cipher, e.g., "128" or "256". + */ abstract string getKeySize(Location location); - abstract TCipherStructure getCipherType(); + /** + * Gets the type of this symmetric cipher, e.g., "AES" or "ChaCha20". + */ + abstract TSymmetricCipherType getCipherFamily(); + + /** + * Gets the mode of operation of this symmetric cipher, e.g., "GCM" or "CBC". + */ + abstract ModeOfOperation getModeOfOperation(); + + bindingset[type] + final private predicate cipherFamilyToNameAndStructure( + TSymmetricCipherType type, string name, TCipherStructureType s + ) { + type instanceof AES and name = "AES" and s = Block() + or + type instanceof Camellia and name = "Camellia" and s = Block() + or + type instanceof DES and name = "DES" and s = Block() + or + type instanceof TripleDES and name = "TripleDES" and s = Block() + or + type instanceof IDEA and name = "IDEA" and s = Block() + or + type instanceof CAST5 and name = "CAST5" and s = Block() + or + type instanceof ChaCha20 and name = "ChaCha20" and s = Stream() + or + type instanceof RC4 and name = "RC4" and s = Stream() + or + type instanceof RC5 and name = "RC5" and s = Block() + or + type instanceof OtherSymmetricCipherType and + name = this.getRawAlgorithmName() and + s = UnknownCipherStructureType() + } //mode, padding scheme, keysize, block/stream, auth'd //nodes = mode, padding scheme //properties = keysize, block/stream, auth'd //leave authd to lang specific + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + ( + // [KNOWN_OR_UNKNOWN] + edgeName = "mode" and + if exists(this.getModeOfOperation()) + then result = this.getModeOfOperation() + else result = this + ) + } + override predicate properties(string key, string value, Location location) { super.properties(key, value, location) or - key = "key_size" and - if exists(this.getKeySize(location)) - then value = this.getKeySize(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation + // [ALWAYS_KNOWN]: unknown case is handled in `getCipherStructureTypeString` + key = "structure" and + getCipherStructureTypeString(this.getCipherStructure()) = value and + location instanceof UnknownLocation + or + ( + // [KNOWN_OR_UNKNOWN] + key = "key_size" and + if exists(this.getKeySize(location)) + then value = this.getKeySize(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) ) - //add more keys to index props } - - abstract ModeOfOperation getModeOfOperation(); } } From b777a22d3578a057e58082310b2ab9e7a01b522e Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Fri, 14 Feb 2025 23:43:07 +0100 Subject: [PATCH 019/336] Expand model and specialize newtype relations --- cpp/ql/lib/experimental/Quantum/OpenSSL.qll | 62 ++++---- java/ql/lib/experimental/Quantum/JCA.qll | 116 ++++++++------- java/ql/src/experimental/Quantum/Test.ql | 2 +- .../codeql/cryptography/Model.qll | 135 ++++++++++++++---- 4 files changed, 203 insertions(+), 112 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll index cb19092f3fd7..821fc0aec8ff 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll @@ -4,16 +4,6 @@ import semmle.code.cpp.dataflow.new.DataFlow module OpenSSLModel { import Language - class FunctionCallOrMacroAccess extends Element { - FunctionCallOrMacroAccess() { this instanceof FunctionCall or this instanceof MacroAccess } - - string getTargetName() { - result = this.(FunctionCall).getTarget().getName() - or - result = this.(MacroAccess).getMacroName() - } - } - /** * Hash function references in OpenSSL. */ @@ -42,13 +32,27 @@ module OpenSSLModel { hash_ref_type_mapping_known(name, algo) } - class HashAlgorithmRef extends Crypto::HashAlgorithm { - FunctionCallOrMacroAccess instance; + class FunctionCallOrMacroAccess extends Element { + FunctionCallOrMacroAccess() { this instanceof FunctionCall or this instanceof MacroAccess } - HashAlgorithmRef() { - this = Crypto::THashAlgorithm(instance) and - hash_ref_type_mapping(instance, _, _) + string getTargetName() { + result = this.(FunctionCall).getTarget().getName() + or + result = this.(MacroAccess).getMacroName() } + } + + class HashAlgorithmCallOrMacro extends Crypto::HashAlgorithmInstance instanceof FunctionCallOrMacroAccess + { + HashAlgorithmCallOrMacro() { hash_ref_type_mapping(this, _, _) } + + string getTargetName() { result = this.(FunctionCallOrMacroAccess).getTargetName() } + } + + class HashAlgorithm extends Crypto::HashAlgorithm { + HashAlgorithmCallOrMacro instance; + + HashAlgorithm() { this = Crypto::THashAlgorithm(instance) } override string getSHA2OrSHA3DigestSize(Location location) { ( @@ -81,9 +85,9 @@ module OpenSSLModel { predicate isSink(DataFlow::Node sink) { exists(EVP_KDF_derive kdo | - sink.asExpr() = kdo.getAlgorithmArg() + sink.asExpr() = kdo.getCall().getAlgorithmArg() or - sink.asExpr() = kdo.getContextArg() // via `EVP_KDF_CTX_set_params` + sink.asExpr() = kdo.getCall().getContextArg() // via `EVP_KDF_CTX_set_params` ) } @@ -101,21 +105,23 @@ module OpenSSLModel { /** * Key derivation operation (e.g., `EVP_KDF_derive`) */ - abstract class KeyDerivationOperation extends Crypto::KeyDerivationOperation { } + class EVP_KDF_derive_FunctionCall extends Crypto::KeyDerivationOperationInstance instanceof FunctionCall + { + EVP_KDF_derive_FunctionCall() { this.getTarget().getName() = "EVP_KDF_derive" } - class EVP_KDF_derive extends KeyDerivationOperation { - FunctionCall instance; + Expr getAlgorithmArg() { result = super.getArgument(3) } - EVP_KDF_derive() { - this = Crypto::TKeyDerivationOperation(instance) and - instance.getTarget().getName() = "EVP_KDF_derive" - } + Expr getContextArg() { result = super.getArgument(0) } + } - override Crypto::Algorithm getAlgorithm() { algorithm_to_EVP_KDF_derive(result, this) } + class EVP_KDF_derive extends Crypto::KeyDerivationOperation { + EVP_KDF_derive_FunctionCall instance; + + EVP_KDF_derive() { this = Crypto::TKeyDerivationOperation(instance) } - Expr getAlgorithmArg() { result = instance.getArgument(3) } + override Crypto::Algorithm getAlgorithm() { algorithm_to_EVP_KDF_derive(result, this) } - Expr getContextArg() { result = instance.getArgument(0) } + EVP_KDF_derive_FunctionCall getCall() { result = instance } } /** @@ -134,7 +140,7 @@ module OpenSSLModel { Expr getAlgorithmArg() { result = this.getArgument(1) } } - class EVP_KDF_fetch_AlgorithmArg extends Expr { + class EVP_KDF_fetch_AlgorithmArg extends Crypto::KeyDerivationAlgorithmInstance instanceof Expr { EVP_KDF_fetch_AlgorithmArg() { exists(EVP_KDF_fetch_Call call | this = call.getAlgorithmArg()) } } diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 807dec96ba40..299d9558ee10 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -4,12 +4,9 @@ import semmle.code.java.dataflow.DataFlow module JCAModel { import Language - abstract class EncryptionOperation extends Crypto::EncryptionOperation { } - - //TODO PBEWith can have suffixes. how to do? enumerate? or match a pattern? + // TODO: Verify that the PBEWith% case works correctly bindingset[algo] predicate cipher_names(string algo) { - // "Standard names are not case-sensitive." algo.toUpperCase() .matches([ "AES", "AESWrap", "AESWrapPad", "ARCFOUR", "Blowfish", "ChaCha20", "ChaCha20-Poly1305", @@ -17,26 +14,29 @@ module JCAModel { ].toUpperCase()) } - //TODO solve the fact that x is an int of various values. same as above... enumerate? + // TODO: Verify that the CFB% case works correctly + bindingset[mode] predicate cipher_modes(string mode) { - mode = - [ - "NONE", "CBC", "CCM", "CFB", "CFBx", "CTR", "CTS", "ECB", "GCM", "KW", "KWP", "OFB", "OFBx", - "PCBC" - ] + mode.toUpperCase() + .matches([ + "NONE", "CBC", "CCM", "CFB", "CFB%", "CTR", "CTS", "ECB", "GCM", "KW", "KWP", "OFB", + "OFB%", "PCBC" + ].toUpperCase()) } - //todo same as above, OAEPWith has asuffix type + // TODO: Verify that the OAEPWith% case works correctly + bindingset[padding] predicate cipher_padding(string padding) { - padding = - [ - "NoPadding", "ISO10126Padding", "OAEPPadding", "OAEPWith", "PKCS1Padding", "PKCS5Padding", - "SSL3Padding" - ] + padding + .toUpperCase() + .matches([ + "NoPadding", "ISO10126Padding", "OAEPPadding", "OAEPWith%", "PKCS1Padding", + "PKCS5Padding", "SSL3Padding" + ].toUpperCase()) } /** - * this may be specified either in the ALG/MODE/PADDING or just ALG format + * A `StringLiteral` in the `"ALG/MODE/PADDING"` or `"ALG"` format */ class CipherStringLiteral extends StringLiteral { CipherStringLiteral() { cipher_names(this.getValue().splitAt("/")) } @@ -56,6 +56,9 @@ module JCAModel { Expr getAlgorithmArg() { result = this.getArgument(0) } } + /** + * Data-flow configuration modelling flow from a cipher string literal to a `CipherGetInstanceCall` argument. + */ private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof CipherStringLiteral } @@ -66,70 +69,77 @@ module JCAModel { module AlgorithmStringToFetchFlow = DataFlow::Global; - class CipherGetInstanceAlgorithmArg extends Expr { + /** + * The cipher algorithm argument to a `CipherGetInstanceCall`. + * + * For example, in `Cipher.getInstance(algorithm)`, this class represents `algorithm`. + */ + class CipherGetInstanceAlgorithmArg extends Crypto::EncryptionAlgorithmInstance, + Crypto::ModeOfOperationAlgorithmInstance instanceof Expr + { CipherGetInstanceAlgorithmArg() { exists(CipherGetInstanceCall call | this = call.getArgument(0)) } - StringLiteral getOrigin() { - AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(result), DataFlow::exprNode(this)) + /** + * Returns the `StringLiteral` from which this argument is derived, if known. + */ + CipherStringLiteral getOrigin() { + AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(result), + DataFlow::exprNode(this.(Expr).getAChildExpr*())) } } - class ModeStringLiteral extends Crypto::ModeOfOperation { - CipherStringLiteral instance; + /** + * A block cipher mode of operation, where the mode is specified in the ALG or ALG/MODE/PADDING format. + * + * This class will only exist when the mode (*and its type*) is determinable. + * This is because the mode will always be specified alongside the algorithm and never independently. + * Therefore, we can always assume that a determinable algorithm will have a determinable mode. + * + * In the case that only an algorithm is specified, e.g., "AES", the provider provides a default mode. + * + * TODO: Model the case of relying on a provider default, but alert on it as a bad practice. + */ + class ModeOfOperation extends Crypto::ModeOfOperationAlgorithm { + CipherGetInstanceAlgorithmArg instance; - ModeStringLiteral() { + ModeOfOperation() { this = Crypto::TModeOfOperationAlgorithm(instance) and - exists(instance.getMode()) and - instance = any(CipherGetInstanceAlgorithmArg call).getOrigin() + // TODO: this currently only holds for explicitly defined modes in a string literal. + // Cases with defaults, e.g., "AES", are not yet modelled. + // For these cases, in a CBOM, the AES node would have an unknown edge to its mode child. + exists(instance.getOrigin().getMode()) } override Location getLocation() { result = instance.getLocation() } - override string getRawAlgorithmName() { result = instance.getMode() } + override string getRawAlgorithmName() { result = instance.getOrigin().getValue() } predicate modeToNameMapping(Crypto::TModeOperationType type, string name) { super.modeToNameMapping(type, name) } override Crypto::TModeOperationType getModeType() { - this.modeToNameMapping(result, instance.getMode().toUpperCase()) + this.modeToNameMapping(result, instance.getOrigin().getMode()) } CipherStringLiteral getInstance() { result = instance } } - //todo refactor - // class CipherAlgorithmPaddingStringLiteral extends CipherAlgorithmPadding instanceof StringLiteral { - // CipherAlgorithmPaddingStringLiteral() { - // cipher_padding(this.(StringLiteral).getValue().splitAt("/")) - // } - // override string toString() { result = this.(StringLiteral).toString() } - // override string getValue() { - // result = this.(StringLiteral).getValue().regexpCapture(".*/.*/(.*)", 1) - // } - // } - /** - * A class to represent when AES is used - * AND currently it has literal mode and padding provided - * - * this currently does not capture the use without a literal - * though should be extended to - */ - class CipherAlgorithm extends Crypto::SymmetricAlgorithm { + class EncryptionAlgorithm extends Crypto::EncryptionAlgorithm { CipherStringLiteral origin; CipherGetInstanceAlgorithmArg instance; - CipherAlgorithm() { - this = Crypto::TSymmetricAlgorithm(instance) and + EncryptionAlgorithm() { + this = Crypto::TEncryptionAlgorithm(instance) and instance.getOrigin() = origin } override Location getLocation() { result = instance.getLocation() } - override Crypto::ModeOfOperation getModeOfOperation() { - result.(ModeStringLiteral).getInstance() = origin + override Crypto::ModeOfOperationAlgorithm getModeOfOperation() { + result.(ModeOfOperation).getInstance() = origin } override Crypto::LocatableElement getOrigin(string name) { @@ -138,23 +148,25 @@ module JCAModel { override string getRawAlgorithmName() { result = origin.getValue() } - override Crypto::TSymmetricCipherType getCipherFamily() { + override Crypto::TCipherType getCipherFamily() { this.cipherNameMapping(result, origin.getAlgorithmName()) } override string getKeySize(Location location) { none() } bindingset[name] - private predicate cipherNameMappingKnown(Crypto::TSymmetricCipherType type, string name) { + private predicate cipherNameMappingKnown(Crypto::TCipherType type, string name) { name = "AES" and type instanceof Crypto::AES or name = "RC4" and type instanceof Crypto::RC4 + // or + // TODO } bindingset[name] - predicate cipherNameMapping(Crypto::TSymmetricCipherType type, string name) { + predicate cipherNameMapping(Crypto::TCipherType type, string name) { this.cipherNameMappingKnown(type, name) or not this.cipherNameMappingKnown(_, name) and diff --git a/java/ql/src/experimental/Quantum/Test.ql b/java/ql/src/experimental/Quantum/Test.ql index f3ae23a2ccac..5496e5a70cf9 100644 --- a/java/ql/src/experimental/Quantum/Test.ql +++ b/java/ql/src/experimental/Quantum/Test.ql @@ -4,6 +4,6 @@ import experimental.Quantum.Language -from Crypto::SymmetricAlgorithm a, Crypto::ModeOfOperation mode +from Crypto::EncryptionAlgorithm a, Crypto::ModeOfOperationAlgorithm mode where a.getModeOfOperation() = mode select a, a.getAlgorithmName(), a.getRawAlgorithmName(), mode, mode.getAlgorithmName() diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index dd570a89ef6e..38ea6e475c05 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -8,6 +8,8 @@ import codeql.util.Option signature module InputSig { class LocatableElement { Location getLocation(); + + string toString(); } class UnknownLocation instanceof Location; @@ -56,15 +58,67 @@ module CryptographyBase Input> { not source = target } + /** + * All elements in the database that are mapped to nodes must extend the following classes + */ + abstract class HashOperationInstance extends LocatableElement { } + + abstract class HashAlgorithmInstance extends LocatableElement { } + + abstract class KeyDerivationOperationInstance extends LocatableElement { } + + abstract class KeyDerivationAlgorithmInstance extends LocatableElement { } + + abstract class EncryptionOperationInstance extends LocatableElement { } + + abstract class EncryptionAlgorithmInstance extends LocatableElement { } + + abstract class KeyEncapsulationOperationInstance extends LocatableElement { } + + abstract class KeyEncapsulationAlgorithmInstance extends LocatableElement { } + + abstract class EllipticCurveAlgorithmInstance extends LocatableElement { } + + // Non-standalone algorithms + abstract class ModeOfOperationAlgorithmInstance extends LocatableElement { } + + abstract class PaddingAlgorithmInstance extends LocatableElement { } + + // Artifacts + abstract class DigestArtifactInstance extends LocatableElement { } + + abstract class KeyArtifactInstance extends LocatableElement { } + + abstract class InitializationVectorArtifactInstance extends LocatableElement { } + + abstract class NonceArtifactInstance extends LocatableElement { } + newtype TNode = - THashOperation(LocatableElement e) or - THashAlgorithm(LocatableElement e) or - TKeyDerivationOperation(LocatableElement e) or - TKeyDerivationAlgorithm(LocatableElement e) or - TEncryptionOperation(LocatableElement e) or - TSymmetricAlgorithm(LocatableElement e) or - TEllipticCurveAlgorithm(LocatableElement e) or - TModeOfOperationAlgorithm(LocatableElement e) + // Artifacts (data that is not an operation or algorithm, e.g., a key) + TDigest(DigestArtifactInstance e) or + TKey(KeyArtifactInstance e) or + TInitializationVector(InitializationVectorArtifactInstance e) or + TNonce(NonceArtifactInstance e) or + // Operations (e.g., hashing, encryption) + THashOperation(HashOperationInstance e) or + TKeyDerivationOperation(KeyDerivationOperationInstance e) or + TEncryptionOperation(EncryptionOperationInstance e) or + TKeyEncapsulationOperation(KeyEncapsulationOperationInstance e) or + // Algorithms (e.g., SHA-256, AES) + TEncryptionAlgorithm(EncryptionAlgorithmInstance e) or + TEllipticCurveAlgorithm(EllipticCurveAlgorithmInstance e) or + THashAlgorithm(HashAlgorithmInstance e) or + TKeyDerivationAlgorithm(KeyDerivationAlgorithmInstance e) or + TKeyEncapsulationAlgorithm(KeyEncapsulationAlgorithmInstance e) or + // Non-standalone Algorithms (e.g., Mode, Padding) + TModeOfOperationAlgorithm(ModeOfOperationAlgorithmInstance e) or + TPaddingAlgorithm(PaddingAlgorithmInstance e) or + // Composite and hybrid cryptosystems (e.g., RSA-OAEP used with AES, post-quantum hybrid cryptosystems) + // These nodes are always parent nodes and are not modeled but rather defined via library-agnostic patterns. + TKemDemHybridCryptosystem(EncryptionAlgorithmInstance dem) or + TKeyAgreementHybridCryptosystem(EncryptionAlgorithmInstance ka) or + TAsymmetricEncryptionMacHybridCryptosystem(EncryptionAlgorithmInstance enc) or + TPostQuantumHybridCryptosystem(EncryptionAlgorithmInstance enc) /** * The base class for all cryptographic assets, such as operations and algorithms. @@ -90,14 +144,14 @@ module CryptographyBase Input> { /** * Returns the child of this node with the given edge name. * - * This predicate is used by derived classes to construct the graph of cryptographic operations. + * This predicate is overriden by derived classes to construct the graph of cryptographic operations. */ NodeBase getChild(string edgeName) { none() } /** * Defines properties of this node by name and either a value or location or both. * - * This predicate is used by derived classes to construct the graph of cryptographic operations. + * This predicate is overriden by derived classes to construct the graph of cryptographic operations. */ predicate properties(string key, string value, Location location) { key = "origin" and @@ -113,6 +167,8 @@ module CryptographyBase Input> { class Asset = NodeBase; + class Artifact = NodeBase; + /** * A cryptographic operation, such as hashing or encryption. */ @@ -125,9 +181,9 @@ module CryptographyBase Input> { /** * Gets the name of this operation, e.g., "hash" or "encrypt". */ - abstract string getOperationName(); + abstract string getOperationType(); - final override string toString() { result = this.getOperationName() } + final override string toString() { result = this.getOperationType() } override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) @@ -175,7 +231,7 @@ module CryptographyBase Input> { abstract class HashOperation extends Operation, THashOperation { abstract override HashAlgorithm getAlgorithm(); - override string getOperationName() { result = "HashOperation" } + override string getOperationType() { result = "HashOperation" } } newtype THashType = @@ -238,7 +294,7 @@ module CryptographyBase Input> { abstract string getSHA2OrSHA3DigestSize(Location location); bindingset[type] - private string getDigestSize(THashType type, Location location) { + private string type_to_digest_size_fixed(THashType type) { type instanceof MD2 and result = "128" or type instanceof MD4 and result = "128" @@ -247,15 +303,20 @@ module CryptographyBase Input> { or type instanceof SHA1 and result = "160" or - type instanceof SHA2 and result = this.getSHA2OrSHA3DigestSize(location) - or - type instanceof SHA3 and result = this.getSHA2OrSHA3DigestSize(location) - or type instanceof RIPEMD160 and result = "160" or type instanceof WHIRLPOOL and result = "512" } + bindingset[type] + private string getDigestSize(THashType type, Location location) { + result = this.type_to_digest_size_fixed(type) and location = this.getLocation() + or + type instanceof SHA2 and result = this.getSHA2OrSHA3DigestSize(location) + or + type instanceof SHA3 and result = this.getSHA2OrSHA3DigestSize(location) + } + final override predicate properties(string key, string value, Location location) { super.properties(key, value, location) or @@ -277,7 +338,7 @@ module CryptographyBase Input> { exists(LocatableElement le | this = TKeyDerivationOperation(le) and result = le.getLocation()) } - override string getOperationName() { result = "KeyDerivationOperation" } + override string getOperationType() { result = "KeyDerivationOperation" } } /** @@ -560,10 +621,10 @@ module CryptographyBase Input> { * An encryption operation that processes plaintext to generate a ciphertext. * This operation takes an input message (plaintext) of arbitrary content and length and produces a ciphertext as the output using a specified encryption algorithm (with a mode and padding). */ - abstract class EncryptionOperation extends Operation { + abstract class EncryptionOperation extends Operation, TEncryptionOperation { abstract override Algorithm getAlgorithm(); - override string getOperationName() { result = "ENCRYPTION" } + override string getOperationType() { result = "EncryptionOperation" } } /** @@ -578,15 +639,18 @@ module CryptographyBase Input> { GCM() or CCM() or XTS() or + OAEP() or OtherMode() - abstract class ModeOfOperation extends Algorithm { + abstract class ModeOfOperationAlgorithm extends Algorithm, TModeOfOperationAlgorithm { override string getAlgorithmType() { result = "ModeOfOperation" } /** * Gets the type of this mode of operation, e.g., "ECB" or "CBC". * * When modeling a new mode of operation, use this predicate to specify the type of the mode. + * + * If a type cannot be determined, the result is `OtherMode`. */ abstract TModeOperationType getModeType(); @@ -633,7 +697,7 @@ module CryptographyBase Input> { /** * Symmetric algorithms */ - newtype TSymmetricCipherType = + newtype TCipherType = AES() or Camellia() or DES() or @@ -643,9 +707,12 @@ module CryptographyBase Input> { ChaCha20() or RC4() or RC5() or + RSA() or OtherSymmetricCipherType() - abstract class SymmetricAlgorithm extends Algorithm { + abstract class EncryptionAlgorithm extends Algorithm, TEncryptionAlgorithm { + final LocatableElement getInstance() { this = TEncryptionAlgorithm(result) } + final TCipherStructureType getCipherStructure() { this.cipherFamilyToNameAndStructure(this.getCipherFamily(), _, result) } @@ -654,26 +721,26 @@ module CryptographyBase Input> { this.cipherFamilyToNameAndStructure(this.getCipherFamily(), result, _) } - final override string getAlgorithmType() { result = "SymmetricAlgorithm" } + final override string getAlgorithmType() { result = "EncryptionAlgorithm" } /** - * Gets the key size of this symmetric cipher, e.g., "128" or "256". + * Gets the key size of this cipher, e.g., "128" or "256". */ abstract string getKeySize(Location location); /** - * Gets the type of this symmetric cipher, e.g., "AES" or "ChaCha20". + * Gets the type of this cipher, e.g., "AES" or "ChaCha20". */ - abstract TSymmetricCipherType getCipherFamily(); + abstract TCipherType getCipherFamily(); /** - * Gets the mode of operation of this symmetric cipher, e.g., "GCM" or "CBC". + * Gets the mode of operation of this cipher, e.g., "GCM" or "CBC". */ - abstract ModeOfOperation getModeOfOperation(); + abstract ModeOfOperationAlgorithm getModeOfOperation(); bindingset[type] final private predicate cipherFamilyToNameAndStructure( - TSymmetricCipherType type, string name, TCipherStructureType s + TCipherType type, string name, TCipherStructureType s ) { type instanceof AES and name = "AES" and s = Block() or @@ -693,6 +760,8 @@ module CryptographyBase Input> { or type instanceof RC5 and name = "RC5" and s = Block() or + type instanceof RSA and name = "RSA" and s = Block() + or type instanceof OtherSymmetricCipherType and name = this.getRawAlgorithmName() and s = UnknownCipherStructureType() @@ -733,4 +802,8 @@ module CryptographyBase Input> { ) } } + + abstract class KEMAlgorithm extends TKeyEncapsulationAlgorithm, Algorithm { + final override string getAlgorithmType() { result = "KeyEncapsulationAlgorithm" } + } } From df01fa7a9cd6a3b8c750c47d658ec4f6e37cd3c6 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Mon, 17 Feb 2025 00:16:08 +0100 Subject: [PATCH 020/336] Expand model and JCA modeling --- java/ql/lib/experimental/Quantum/JCA.qll | 149 ++++++++++++++++-- java/ql/src/experimental/Quantum/Test.ql | 6 +- .../codeql/cryptography/Model.qll | 124 ++++++++++++--- 3 files changed, 237 insertions(+), 42 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 299d9558ee10..5a30e96b13ca 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -54,6 +54,8 @@ module JCAModel { } Expr getAlgorithmArg() { result = this.getArgument(0) } + + Expr getProviderArg() { result = this.getArgument(1) } } /** @@ -75,7 +77,7 @@ module JCAModel { * For example, in `Cipher.getInstance(algorithm)`, this class represents `algorithm`. */ class CipherGetInstanceAlgorithmArg extends Crypto::EncryptionAlgorithmInstance, - Crypto::ModeOfOperationAlgorithmInstance instanceof Expr + Crypto::ModeOfOperationAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof Expr { CipherGetInstanceAlgorithmArg() { exists(CipherGetInstanceCall call | this = call.getArgument(0)) @@ -114,14 +116,62 @@ module JCAModel { override Location getLocation() { result = instance.getLocation() } - override string getRawAlgorithmName() { result = instance.getOrigin().getValue() } + // In this case, the raw name is still only the /MODE/ part. + // TODO: handle defaults + override string getRawAlgorithmName() { result = instance.getOrigin().getMode() } - predicate modeToNameMapping(Crypto::TModeOperationType type, string name) { - super.modeToNameMapping(type, name) + private predicate modeToNameMappingKnown(Crypto::TModeOperationType type, string name) { + type instanceof Crypto::ECB and name = "ECB" + or + type instanceof Crypto::CBC and name = "CBC" + or + type instanceof Crypto::GCM and name = "GCM" + or + type instanceof Crypto::CTR and name = "CTR" + or + type instanceof Crypto::XTS and name = "XTS" + or + type instanceof Crypto::CCM and name = "CCM" + or + type instanceof Crypto::SIV and name = "SIV" + or + type instanceof Crypto::OCB and name = "OCB" } override Crypto::TModeOperationType getModeType() { - this.modeToNameMapping(result, instance.getOrigin().getMode()) + if this.modeToNameMappingKnown(_, instance.getOrigin().getMode()) + then this.modeToNameMappingKnown(result, instance.getOrigin().getMode()) + else result instanceof Crypto::OtherMode + } + + CipherStringLiteral getInstance() { result = instance } + } + + class PaddingAlgorithm extends Crypto::PaddingAlgorithm { + CipherGetInstanceAlgorithmArg instance; + + PaddingAlgorithm() { + this = Crypto::TPaddingAlgorithm(instance) and + exists(instance.getOrigin().getPadding()) + } + + override Location getLocation() { result = instance.getLocation() } + + override string getRawAlgorithmName() { result = instance.getOrigin().getPadding() } + + bindingset[name] + private predicate paddingToNameMappingKnown(Crypto::TPaddingType type, string name) { + type instanceof Crypto::NoPadding and name = "NOPADDING" + or + type instanceof Crypto::PKCS7 and name = ["PKCS5Padding", "PKCS7Padding"] // TODO: misnomer in the JCA? + or + type instanceof Crypto::OAEP and name.matches("OAEP%") // TODO: handle OAEPWith% + } + + override Crypto::TPaddingType getPaddingType() { + if this.paddingToNameMappingKnown(_, instance.getOrigin().getPadding()) + then this.paddingToNameMappingKnown(result, instance.getOrigin().getPadding()) + else result instanceof Crypto::OtherPadding } CipherStringLiteral getInstance() { result = instance } @@ -142,6 +192,10 @@ module JCAModel { result.(ModeOfOperation).getInstance() = origin } + override Crypto::PaddingAlgorithm getPadding() { + result.(PaddingAlgorithm).getInstance() = origin + } + override Crypto::LocatableElement getOrigin(string name) { result = origin and name = origin.toString() } @@ -149,7 +203,9 @@ module JCAModel { override string getRawAlgorithmName() { result = origin.getValue() } override Crypto::TCipherType getCipherFamily() { - this.cipherNameMapping(result, origin.getAlgorithmName()) + if this.cipherNameMappingKnown(_, origin.getAlgorithmName()) + then this.cipherNameMappingKnown(result, origin.getAlgorithmName()) + else result instanceof Crypto::OtherSymmetricCipherType } override string getKeySize(Location location) { none() } @@ -159,18 +215,83 @@ module JCAModel { name = "AES" and type instanceof Crypto::AES or + name = "DES" and + type instanceof Crypto::DES + or + name = "TripleDES" and + type instanceof Crypto::TripleDES + or + name = "IDEA" and + type instanceof Crypto::IDEA + or + name = "CAST5" and + type instanceof Crypto::CAST5 + or + name = "ChaCha20" and + type instanceof Crypto::ChaCha20 + or name = "RC4" and type instanceof Crypto::RC4 - // or - // TODO + or + name = "RC5" and + type instanceof Crypto::RC5 + or + name = "RSA" and + type instanceof Crypto::RSA } + } - bindingset[name] - predicate cipherNameMapping(Crypto::TCipherType type, string name) { - this.cipherNameMappingKnown(type, name) - or - not this.cipherNameMappingKnown(_, name) and - type instanceof Crypto::OtherSymmetricCipherType + /** + * Initialiation vectors + */ + abstract class IVParameterInstantiation extends ClassInstanceExpr { + abstract Expr getIV(); + } + + class IvParameterSpecInstance extends IVParameterInstantiation { + IvParameterSpecInstance() { + this.getConstructedType().hasQualifiedName("javax.crypto.spec", "IvParameterSpec") + } + + override Expr getIV() { result = super.getArgument(0) } + } + + class GCMParameterSpecInstance extends IVParameterInstantiation { + GCMParameterSpecInstance() { + this.getConstructedType().hasQualifiedName("javax.crypto.spec", "GCMParameterSpec") } + + override Expr getIV() { result = super.getArgument(1) } + } + + class CipherInitCall extends MethodCall { + CipherInitCall() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "init") } + + Expr getModeArg() { result = this.getArgument(0) } + + Expr getKey() { + result = this.getArgument(1) and this.getMethod().getParameterType(1).hasName("Key") + } + + Expr getIV() { + result = this.getArgument(2) and + this.getMethod().getParameterType(2).hasName("AlgorithmParameterSpec") + } + } + + // TODO: cipher.getParameters().getParameterSpec(GCMParameterSpec.class); + class InitializationVectorExpr extends Crypto::InitializationVectorArtifactInstance instanceof Expr + { + CipherInitCall call; // TODO: add origin to known sources (e.g. RNG, etc.) + + InitializationVectorExpr() { this = call.getIV() } + } + + class InitializationVector extends Crypto::InitializationVector { + InitializationVectorExpr instance; + + InitializationVector() { this = Crypto::TInitializationVector(instance) } + + override Location getLocation() { result = instance.getLocation() } } } diff --git a/java/ql/src/experimental/Quantum/Test.ql b/java/ql/src/experimental/Quantum/Test.ql index 5496e5a70cf9..ba76213132c3 100644 --- a/java/ql/src/experimental/Quantum/Test.ql +++ b/java/ql/src/experimental/Quantum/Test.ql @@ -4,6 +4,6 @@ import experimental.Quantum.Language -from Crypto::EncryptionAlgorithm a, Crypto::ModeOfOperationAlgorithm mode -where a.getModeOfOperation() = mode -select a, a.getAlgorithmName(), a.getRawAlgorithmName(), mode, mode.getAlgorithmName() +from Crypto::EncryptionAlgorithm a, Crypto::ModeOfOperationAlgorithm m, Crypto::PaddingAlgorithm p +where m = a.getModeOfOperation() and p = a.getPadding() +select a, a.getRawAlgorithmName(), m, m.getRawAlgorithmName(), p, p.getRawAlgorithmName() diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 38ea6e475c05..9814f1519950 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -115,7 +115,7 @@ module CryptographyBase Input> { TPaddingAlgorithm(PaddingAlgorithmInstance e) or // Composite and hybrid cryptosystems (e.g., RSA-OAEP used with AES, post-quantum hybrid cryptosystems) // These nodes are always parent nodes and are not modeled but rather defined via library-agnostic patterns. - TKemDemHybridCryptosystem(EncryptionAlgorithmInstance dem) or + TKemDemHybridCryptosystem(EncryptionAlgorithmInstance dem) or // TODO, change this relation and the below ones TKeyAgreementHybridCryptosystem(EncryptionAlgorithmInstance ka) or TAsymmetricEncryptionMacHybridCryptosystem(EncryptionAlgorithmInstance enc) or TPostQuantumHybridCryptosystem(EncryptionAlgorithmInstance enc) @@ -131,6 +131,11 @@ module CryptographyBase Input> { */ abstract string toString(); + /** + * Returns a string representation of the internal type of this node, usually the name of the class. + */ + abstract string getInternalType(); + /** * Returns the location of this node in the code. */ @@ -169,6 +174,15 @@ module CryptographyBase Input> { class Artifact = NodeBase; + /** + * An initialization vector + */ + abstract class InitializationVector extends Asset, TInitializationVector { + final override string getInternalType() { result = "InitializationVector" } + + final override string toString() { result = this.getInternalType() } + } + /** * A cryptographic operation, such as hashing or encryption. */ @@ -185,6 +199,8 @@ module CryptographyBase Input> { final override string toString() { result = this.getOperationType() } + final override string getInternalType() { result = this.getOperationType() } + override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) or @@ -196,6 +212,8 @@ module CryptographyBase Input> { abstract class Algorithm extends Asset { final override string toString() { result = this.getAlgorithmType() } + final override string getInternalType() { result = this.getAlgorithmType() } + /** * Gets the name of this algorithm, e.g., "AES" or "SHA". */ @@ -294,7 +312,7 @@ module CryptographyBase Input> { abstract string getSHA2OrSHA3DigestSize(Location location); bindingset[type] - private string type_to_digest_size_fixed(THashType type) { + private string getTypeDigestSizeFixed(THashType type) { type instanceof MD2 and result = "128" or type instanceof MD4 and result = "128" @@ -309,21 +327,25 @@ module CryptographyBase Input> { } bindingset[type] - private string getDigestSize(THashType type, Location location) { - result = this.type_to_digest_size_fixed(type) and location = this.getLocation() + private string getTypeDigestSize(THashType type, Location location) { + result = this.getTypeDigestSizeFixed(type) and location = this.getLocation() or type instanceof SHA2 and result = this.getSHA2OrSHA3DigestSize(location) or type instanceof SHA3 and result = this.getSHA2OrSHA3DigestSize(location) } + string getDigestSize(Location location) { + result = this.getTypeDigestSize(this.getHashType(), location) + } + final override predicate properties(string key, string value, Location location) { super.properties(key, value, location) or // [KNOWN_OR_UNKNOWN] key = "digest_size" and - if exists(this.getDigestSize(this.getHashType(), location)) - then value = this.getDigestSize(this.getHashType(), location) + if exists(this.getDigestSize(location)) + then value = this.getDigestSize(location) else ( value instanceof UnknownPropertyValue and location instanceof UnknownLocation ) @@ -619,27 +641,33 @@ module CryptographyBase Input> { /** * An encryption operation that processes plaintext to generate a ciphertext. - * This operation takes an input message (plaintext) of arbitrary content and length and produces a ciphertext as the output using a specified encryption algorithm (with a mode and padding). + * This operation takes an input message (plaintext) of arbitrary content and length + * and produces a ciphertext as the output using a specified encryption algorithm (with a mode and padding). */ abstract class EncryptionOperation extends Operation, TEncryptionOperation { - abstract override Algorithm getAlgorithm(); - override string getOperationType() { result = "EncryptionOperation" } + + /** + * Gets the initialization vector associated with this encryption operation. + * + * This predicate does not need to hold for all encryption operations, + * as the initialization vector is not always required. + */ + abstract InitializationVector getInitializationVector(); } /** * Block cipher modes of operation algorithms */ newtype TModeOperationType = - ECB() or - CBC() or - CFB() or - OFB() or - CTR() or - GCM() or - CCM() or - XTS() or - OAEP() or + ECB() or // Not secure, widely used + CBC() or // Vulnerable to padding oracle attacks + GCM() or // Widely used AEAD mode (TLS 1.3, SSH, IPsec) + CTR() or // Fast stream-like encryption (SSH, disk encryption) + XTS() or // Standard for full-disk encryption (BitLocker, LUKS, FileVault) + CCM() or // Used in lightweight cryptography (IoT, WPA2) + SIV() or // Misuse-resistant encryption, used in secure storage + OCB() or // Efficient AEAD mode OtherMode() abstract class ModeOfOperationAlgorithm extends Algorithm, TModeOfOperationAlgorithm { @@ -655,22 +683,22 @@ module CryptographyBase Input> { abstract TModeOperationType getModeType(); bindingset[type] - final predicate modeToNameMapping(TModeOperationType type, string name) { + final private predicate modeToNameMapping(TModeOperationType type, string name) { type instanceof ECB and name = "ECB" or type instanceof CBC and name = "CBC" or - type instanceof CFB and name = "CFB" - or - type instanceof OFB and name = "OFB" + type instanceof GCM and name = "GCM" or type instanceof CTR and name = "CTR" or - type instanceof GCM and name = "GCM" + type instanceof XTS and name = "XTS" or type instanceof CCM and name = "CCM" or - type instanceof XTS and name = "XTS" + type instanceof SIV and name = "SIV" + or + type instanceof OCB and name = "OCB" or type instanceof OtherMode and name = this.getRawAlgorithmName() } @@ -678,12 +706,51 @@ module CryptographyBase Input> { override string getAlgorithmName() { this.modeToNameMapping(this.getModeType(), result) } } + newtype TPaddingType = + PKCS1_v1_5() or // RSA encryption/signing padding + PKCS7() or // Standard block cipher padding (PKCS5 for 8-byte blocks) + ANSI_X9_23() or // Zero-padding except last byte = padding length + NoPadding() or // Explicit no-padding + OAEP() or // RSA OAEP padding + OtherPadding() + + abstract class PaddingAlgorithm extends Algorithm, TPaddingAlgorithm { + override string getAlgorithmType() { result = "PaddingAlgorithm" } + + /** + * Gets the type of this padding algorithm, e.g., "PKCS7" or "OAEP". + * + * When modeling a new padding algorithm, use this predicate to specify the type of the padding. + * + * If a type cannot be determined, the result is `OtherPadding`. + */ + abstract TPaddingType getPaddingType(); + + bindingset[type] + final private predicate paddingToNameMapping(TPaddingType type, string name) { + type instanceof PKCS1_v1_5 and name = "PKCS1_v1_5" + or + type instanceof PKCS7 and name = "PKCS7" + or + type instanceof ANSI_X9_23 and name = "ANSI_X9_23" + or + type instanceof NoPadding and name = "NoPadding" + or + type instanceof OAEP and name = "OAEP" + or + type instanceof OtherPadding and name = this.getRawAlgorithmName() + } + + override string getAlgorithmName() { this.paddingToNameMapping(this.getPaddingType(), result) } + } + /** * A helper type for distinguishing between block and stream ciphers. */ newtype TCipherStructureType = Block() or Stream() or + Asymmetric() or UnknownCipherStructureType() private string getCipherStructureTypeString(TCipherStructureType type) { @@ -691,6 +758,8 @@ module CryptographyBase Input> { or type instanceof Stream and result = "Stream" or + type instanceof Asymmetric and result = "Asymmetric" + or type instanceof UnknownCipherStructureType and result instanceof UnknownPropertyValue } @@ -738,6 +807,11 @@ module CryptographyBase Input> { */ abstract ModeOfOperationAlgorithm getModeOfOperation(); + /** + * Gets the padding scheme of this cipher, e.g., "PKCS7" or "NoPadding". + */ + abstract PaddingAlgorithm getPadding(); + bindingset[type] final private predicate cipherFamilyToNameAndStructure( TCipherType type, string name, TCipherStructureType s @@ -760,7 +834,7 @@ module CryptographyBase Input> { or type instanceof RC5 and name = "RC5" and s = Block() or - type instanceof RSA and name = "RSA" and s = Block() + type instanceof RSA and name = "RSA" and s = Asymmetric() or type instanceof OtherSymmetricCipherType and name = this.getRawAlgorithmName() and From 8707e4d9a394aea6081fbcf52dffc0d29e0c6e8b Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Tue, 18 Feb 2025 18:35:49 +0100 Subject: [PATCH 021/336] Continue Artifact data-flow WIP --- java/ql/lib/experimental/Quantum/JCA.qll | 37 +++++---- java/ql/lib/experimental/Quantum/Language.qll | 76 ++++++++++++++++--- .../codeql/cryptography/Model.qll | 62 ++++++++++++--- 3 files changed, 141 insertions(+), 34 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 5a30e96b13ca..e961310334f9 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -244,24 +244,29 @@ module JCAModel { /** * Initialiation vectors */ - abstract class IVParameterInstantiation extends ClassInstanceExpr { - abstract Expr getIV(); + abstract class IVParameterInstantiation extends Crypto::InitializationVectorArtifactInstance instanceof ClassInstanceExpr + { + abstract Expr getInput(); } class IvParameterSpecInstance extends IVParameterInstantiation { IvParameterSpecInstance() { - this.getConstructedType().hasQualifiedName("javax.crypto.spec", "IvParameterSpec") + this.(ClassInstanceExpr) + .getConstructedType() + .hasQualifiedName("javax.crypto.spec", "IvParameterSpec") } - override Expr getIV() { result = super.getArgument(0) } + override Expr getInput() { result = this.(ClassInstanceExpr).getArgument(0) } } class GCMParameterSpecInstance extends IVParameterInstantiation { GCMParameterSpecInstance() { - this.getConstructedType().hasQualifiedName("javax.crypto.spec", "GCMParameterSpec") + this.(ClassInstanceExpr) + .getConstructedType() + .hasQualifiedName("javax.crypto.spec", "GCMParameterSpec") } - override Expr getIV() { result = super.getArgument(1) } + override Expr getInput() { result = this.(ClassInstanceExpr).getArgument(1) } } class CipherInitCall extends MethodCall { @@ -280,18 +285,24 @@ module JCAModel { } // TODO: cipher.getParameters().getParameterSpec(GCMParameterSpec.class); - class InitializationVectorExpr extends Crypto::InitializationVectorArtifactInstance instanceof Expr - { - CipherInitCall call; // TODO: add origin to known sources (e.g. RNG, etc.) - - InitializationVectorExpr() { this = call.getIV() } - } + /* + * class InitializationVectorArg extends Crypto::InitializationVectorArtifactInstance instanceof Expr + * { + * IVParameterInstantiation creation; + * + * InitializationVectorArg() { this = creation.getInput() } + * } + */ class InitializationVector extends Crypto::InitializationVector { - InitializationVectorExpr instance; + IVParameterInstantiation instance; InitializationVector() { this = Crypto::TInitializationVector(instance) } override Location getLocation() { result = instance.getLocation() } + + override Crypto::DataFlowNode asOutputData() { result.asExpr() = instance } + + override Crypto::DataFlowNode getInputData() { result.asExpr() = instance.getInput() } } } diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 485b3e716e69..5801815109b0 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -1,5 +1,11 @@ private import codeql.cryptography.Model -private import java as Lang +private import java as Language +private import semmle.code.java.security.InsecureRandomnessQuery +private import semmle.code.java.security.RandomQuery + +private class UnknownLocation extends Language::Location { + UnknownLocation() { this.getFile().getAbsolutePath() = "" } +} /** * A dummy location which is used when something doesn't have a location in @@ -7,24 +13,72 @@ private import java as Lang * may be several distinct kinds of unknown locations. For example: one for * expressions, one for statements and one for other program elements. */ -class UnknownLocation extends Location { - UnknownLocation() { this.getFile().getAbsolutePath() = "" } +private class UnknownDefaultLocation extends UnknownLocation { + UnknownDefaultLocation() { locations_default(this, _, 0, 0, 0, 0) } +} + +module CryptoInput implements InputSig { + class DataFlowNode = DataFlow::Node; + + class LocatableElement = Language::Element; + + class UnknownLocation = UnknownDefaultLocation; + + predicate rngToIvFlow(DataFlowNode rng, DataFlowNode iv) { none() } } /** - * A dummy location which is used when something doesn't have a location in - * the source code but needs to have a `Location` associated with it. + * Instantiate the model */ -class UnknownDefaultLocation extends UnknownLocation { - UnknownDefaultLocation() { locations_default(this, _, 0, 0, 0, 0) } +module Crypto = CryptographyBase; + +/** + * Random number generation, where each instance is modelled as the expression + * tied to an output node (i.e., the result of the source of randomness) + */ +abstract class RandomnessInstance extends Crypto::RandomNumberGenerationInstance { + abstract Crypto::RNGSourceSecurity getSourceSecurity(); + + Crypto::TRNGSeedSecurity getSeedSecurity(Location location) { none() } } -module CryptoInput implements InputSig { - class LocatableElement = Lang::Element; +class SecureRandomnessInstance extends RandomnessInstance { + SecureRandomnessInstance() { + exists(RandomDataSource s | this = s.getOutput() | + s.getSourceOfRandomness() instanceof SecureRandomNumberGenerator + ) + } - class UnknownLocation = UnknownDefaultLocation; + override Crypto::RNGSourceSecurity getSourceSecurity() { + result instanceof Crypto::RNGSourceSecure + } +} + +class InsecureRandomnessInstance extends RandomnessInstance { + InsecureRandomnessInstance() { exists(InsecureRandomnessSource node | this = node.asExpr()) } + + override Crypto::RNGSourceSecurity getSourceSecurity() { + result instanceof Crypto::RNGSourceInsecure + } } -module Crypto = CryptographyBase; +class RandomnessArtifact extends Crypto::RandomNumberGeneration { + RandomnessInstance instance; + + RandomnessArtifact() { this = Crypto::TRandomNumberGeneration(instance) } + + override Location getLocation() { result = instance.getLocation() } + + override Crypto::RNGSourceSecurity getSourceSecurity() { result = instance.getSourceSecurity() } + + override Crypto::TRNGSeedSecurity getSeedSecurity(Location location) { + result = instance.getSeedSecurity(location) + } + + override Crypto::DataFlowNode asOutputData() { result.asExpr() = instance } + + override Crypto::DataFlowNode getInputData() { none() } +} +// Import library-specific modeling import JCA diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 9814f1519950..205400e8a3ca 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -12,7 +12,15 @@ signature module InputSig { string toString(); } + class DataFlowNode { + Location getLocation(); + + string toString(); + } + class UnknownLocation instanceof Location; + + predicate rngToIvFlow(DataFlowNode rng, DataFlowNode iv); } module CryptographyBase Input> { @@ -20,6 +28,8 @@ module CryptographyBase Input> { final class UnknownLocation = Input::UnknownLocation; + final class DataFlowNode = Input::DataFlowNode; + final class UnknownPropertyValue extends string { UnknownPropertyValue() { this = "" } } @@ -93,12 +103,15 @@ module CryptographyBase Input> { abstract class NonceArtifactInstance extends LocatableElement { } + abstract class RandomNumberGenerationInstance extends LocatableElement { } + newtype TNode = // Artifacts (data that is not an operation or algorithm, e.g., a key) TDigest(DigestArtifactInstance e) or TKey(KeyArtifactInstance e) or TInitializationVector(InitializationVectorArtifactInstance e) or TNonce(NonceArtifactInstance e) or + TRandomNumberGeneration(RandomNumberGenerationInstance e) or // Operations (e.g., hashing, encryption) THashOperation(HashOperationInstance e) or TKeyDerivationOperation(KeyDerivationOperationInstance e) or @@ -115,7 +128,7 @@ module CryptographyBase Input> { TPaddingAlgorithm(PaddingAlgorithmInstance e) or // Composite and hybrid cryptosystems (e.g., RSA-OAEP used with AES, post-quantum hybrid cryptosystems) // These nodes are always parent nodes and are not modeled but rather defined via library-agnostic patterns. - TKemDemHybridCryptosystem(EncryptionAlgorithmInstance dem) or // TODO, change this relation and the below ones + TKemDemHybridCryptosystem(EncryptionAlgorithm dem) or // TODO, change this relation and the below ones TKeyAgreementHybridCryptosystem(EncryptionAlgorithmInstance ka) or TAsymmetricEncryptionMacHybridCryptosystem(EncryptionAlgorithmInstance enc) or TPostQuantumHybridCryptosystem(EncryptionAlgorithmInstance enc) @@ -127,9 +140,9 @@ module CryptographyBase Input> { */ abstract class NodeBase extends TNode { /** - * Returns a string representation of this node, usually the name of the operation/algorithm/property. + * Returns a string representation of this node. */ - abstract string toString(); + string toString() { result = this.getInternalType() } /** * Returns a string representation of the internal type of this node, usually the name of the class. @@ -172,15 +185,48 @@ module CryptographyBase Input> { class Asset = NodeBase; - class Artifact = NodeBase; + abstract class Artifact extends NodeBase { + abstract DataFlowNode asOutputData(); + + abstract DataFlowNode getInputData(); + } /** * An initialization vector */ - abstract class InitializationVector extends Asset, TInitializationVector { + abstract class InitializationVector extends Artifact, TInitializationVector { final override string getInternalType() { result = "InitializationVector" } - final override string toString() { result = this.getInternalType() } + RandomNumberGeneration getRNGSource() { + Input::rngToIvFlow(result.asOutputData(), this.getInputData()) + } + } + + newtype TRNGSourceSecurity = + RNGSourceSecure() or // Secure RNG source (unrelated to seed) + RNGSourceInsecure() // Insecure RNG source (unrelated to seed) + + class RNGSourceSecurity extends TRNGSourceSecurity { + string toString() { + this instanceof RNGSourceSecure and result = "Secure RNG Source" + or + this instanceof RNGSourceInsecure and result = "Insecure RNG Source" + } + } + + newtype TRNGSeedSecurity = + RNGSeedSecure() or + RNGSeedInsecure() + + /** + * A source of random number generation + */ + abstract class RandomNumberGeneration extends Artifact, TRandomNumberGeneration { + final override string getInternalType() { result = "RandomNumberGeneration" } + + abstract RNGSourceSecurity getSourceSecurity(); + + abstract TRNGSeedSecurity getSeedSecurity(Location location); } /** @@ -197,8 +243,6 @@ module CryptographyBase Input> { */ abstract string getOperationType(); - final override string toString() { result = this.getOperationType() } - final override string getInternalType() { result = this.getOperationType() } override NodeBase getChild(string edgeName) { @@ -210,8 +254,6 @@ module CryptographyBase Input> { } abstract class Algorithm extends Asset { - final override string toString() { result = this.getAlgorithmType() } - final override string getInternalType() { result = this.getAlgorithmType() } /** From 3871c6a33ed3e3c0399de39b389e6cb7712eea64 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 18 Feb 2025 16:09:00 -0500 Subject: [PATCH 022/336] Adding support for encryption operation detection. --- java/ql/lib/experimental/Quantum/JCA.qll | 57 +++++++++++++++++++ .../codeql/cryptography/Model.qll | 15 ++--- 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index e961310334f9..5b55090bd9e2 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -58,6 +58,10 @@ module JCAModel { Expr getProviderArg() { result = this.getArgument(1) } } + class CipherDoFinalCall extends Call { + CipherDoFinalCall() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "doFinal") } + } + /** * Data-flow configuration modelling flow from a cipher string literal to a `CipherGetInstanceCall` argument. */ @@ -92,6 +96,57 @@ module JCAModel { } } + // TODO: what if encrypt/decrypt mode isn't known + private module CipherGetInstanceToFinalizeConfig implements DataFlow::StateConfigSig { + class FlowState = string; + + predicate isSource(DataFlow::Node src, FlowState state) { + state = "UNKNOWN" and + src.asExpr() instanceof CipherGetInstanceCall + } + + predicate isSink(DataFlow::Node sink, FlowState state) { + state in ["ENCRYPT", "DECRYPT", "UNKNOWN"] and + exists(CipherDoFinalCall c | c.getQualifier() = sink.asExpr()) + } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 + ) { + state1 in ["UNKNOWN", "ENCRYPT", "DECRYPT"] and + exists(CipherInitCall c | + c.getQualifier() = node1.asExpr() and + // TODO: not taking into consideration if the mode traces to this arg + exists(FieldAccess fa | + c.getModeArg() = fa and + ( + fa.getField().getName() = "ENCRYPT_MODE" and + state2 = "ENCRYPT" + or + fa.getField().getName() = "DECRYPT_MODE" and + state2 = "DECRYPT" + ) + ) + ) and + node2 = node1 + } + } + + module CipherGetInstanceToFinalizeFlow = + DataFlow::GlobalWithState; + + // TODO: what if the mode is UNKNOWN? + class CipherEncryptionOperation extends Crypto::EncryptionOperationInstance instanceof Call { + CipherEncryptionOperation() { + exists(CipherGetInstanceToFinalizeFlow::PathNode sink, CipherDoFinalCall c | + CipherGetInstanceToFinalizeFlow::flowPath(_, sink) and + sink.getNode().asExpr() = c.getQualifier() and + sink.getState() = "ENCRYPT" and + this = c + ) + } + } + /** * A block cipher mode of operation, where the mode is specified in the ALG or ALG/MODE/PADDING format. * @@ -272,6 +327,8 @@ module JCAModel { class CipherInitCall extends MethodCall { CipherInitCall() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "init") } + // TODO: this doesn't account for tracing the mode to this arg if expending this arg to have + // the actual mode directly Expr getModeArg() { result = this.getArgument(0) } Expr getKey() { diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 205400e8a3ca..8a5011489a67 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -689,13 +689,14 @@ module CryptographyBase Input> { abstract class EncryptionOperation extends Operation, TEncryptionOperation { override string getOperationType() { result = "EncryptionOperation" } - /** - * Gets the initialization vector associated with this encryption operation. - * - * This predicate does not need to hold for all encryption operations, - * as the initialization vector is not always required. - */ - abstract InitializationVector getInitializationVector(); + abstract override EncryptionAlgorithm getAlgorithm(); + // /** + // * Gets the initialization vector associated with this encryption operation. + // * + // * This predicate does not need to hold for all encryption operations, + // * as the initialization vector is not always required. + // */ + // abstract InitializationVector getInitializationVector(); } /** From 9ee4a7a7b8798efb33b18271527e5dd167d9bc94 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Thu, 20 Feb 2025 10:37:40 -0500 Subject: [PATCH 023/336] Adding a sketch for a CipherOperation concept to model encryption/decryption operations. --- java/ql/lib/experimental/Quantum/JCA.qll | 51 +++++++++++++------ .../codeql/cryptography/Model.qll | 51 +++++++++++++------ 2 files changed, 70 insertions(+), 32 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 5b55090bd9e2..0f505e400a06 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -83,9 +83,9 @@ module JCAModel { class CipherGetInstanceAlgorithmArg extends Crypto::EncryptionAlgorithmInstance, Crypto::ModeOfOperationAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof Expr { - CipherGetInstanceAlgorithmArg() { - exists(CipherGetInstanceCall call | this = call.getArgument(0)) - } + CipherGetInstanceCall call; + + CipherGetInstanceAlgorithmArg() { this = call.getAlgorithmArg() } /** * Returns the `StringLiteral` from which this argument is derived, if known. @@ -94,26 +94,26 @@ module JCAModel { AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(result), DataFlow::exprNode(this.(Expr).getAChildExpr*())) } + + CipherGetInstanceCall getCall() { result = call } } // TODO: what if encrypt/decrypt mode isn't known private module CipherGetInstanceToFinalizeConfig implements DataFlow::StateConfigSig { - class FlowState = string; + class FlowState = Crypto::TCipherOperationMode; predicate isSource(DataFlow::Node src, FlowState state) { - state = "UNKNOWN" and + state = Crypto::UnknownCipherOperationMode() and src.asExpr() instanceof CipherGetInstanceCall } predicate isSink(DataFlow::Node sink, FlowState state) { - state in ["ENCRYPT", "DECRYPT", "UNKNOWN"] and exists(CipherDoFinalCall c | c.getQualifier() = sink.asExpr()) } predicate isAdditionalFlowStep( DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 ) { - state1 in ["UNKNOWN", "ENCRYPT", "DECRYPT"] and exists(CipherInitCall c | c.getQualifier() = node1.asExpr() and // TODO: not taking into consideration if the mode traces to this arg @@ -121,10 +121,16 @@ module JCAModel { c.getModeArg() = fa and ( fa.getField().getName() = "ENCRYPT_MODE" and - state2 = "ENCRYPT" + state2 = Crypto::EncryptionMode() or fa.getField().getName() = "DECRYPT_MODE" and - state2 = "DECRYPT" + state2 = Crypto::DecryptionMode() + or + fa.getField().getName() = "WRAP_MODE" and + state2 = Crypto::EncryptionMode() + or + fa.getField().getName() = "UNWRAP_MODE" and + state2 = Crypto::DecryptionMode() ) ) ) and @@ -135,16 +141,29 @@ module JCAModel { module CipherGetInstanceToFinalizeFlow = DataFlow::GlobalWithState; - // TODO: what if the mode is UNKNOWN? - class CipherEncryptionOperation extends Crypto::EncryptionOperationInstance instanceof Call { + class CipherEncryptionOperation extends Crypto::CipherOperationInstance instanceof Call { + Crypto::TCipherOperationMode mode; + Crypto::EncryptionAlgorithmInstance algorithm; + CipherEncryptionOperation() { - exists(CipherGetInstanceToFinalizeFlow::PathNode sink, CipherDoFinalCall c | - CipherGetInstanceToFinalizeFlow::flowPath(_, sink) and - sink.getNode().asExpr() = c.getQualifier() and - sink.getState() = "ENCRYPT" and - this = c + exists( + CipherGetInstanceToFinalizeFlow::PathNode sink, + CipherGetInstanceToFinalizeFlow::PathNode src, CipherGetInstanceCall getCipher, + CipherDoFinalCall doFinalize, CipherGetInstanceAlgorithmArg arg + | + CipherGetInstanceToFinalizeFlow::flowPath(src, sink) and + src.getNode().asExpr() = getCipher and + sink.getNode().asExpr() = doFinalize.getQualifier() and + sink.getState() = mode and + this = doFinalize and + arg.getCall() = getCipher and + algorithm = arg ) } + + override Crypto::EncryptionAlgorithmInstance getAlgorithm() { result = algorithm } + + override Crypto::TCipherOperationMode getCipherOperationMode() { result = mode } } /** diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 8a5011489a67..24e3d4f48ebd 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -79,7 +79,11 @@ module CryptographyBase Input> { abstract class KeyDerivationAlgorithmInstance extends LocatableElement { } - abstract class EncryptionOperationInstance extends LocatableElement { } + abstract class CipherOperationInstance extends LocatableElement { + abstract EncryptionAlgorithmInstance getAlgorithm(); + + abstract TCipherOperationMode getCipherOperationMode(); + } abstract class EncryptionAlgorithmInstance extends LocatableElement { } @@ -115,7 +119,7 @@ module CryptographyBase Input> { // Operations (e.g., hashing, encryption) THashOperation(HashOperationInstance e) or TKeyDerivationOperation(KeyDerivationOperationInstance e) or - TEncryptionOperation(EncryptionOperationInstance e) or + TCipherOperation(CipherOperationInstance e) or TKeyEncapsulationOperation(KeyEncapsulationOperationInstance e) or // Algorithms (e.g., SHA-256, AES) TEncryptionAlgorithm(EncryptionAlgorithmInstance e) or @@ -238,13 +242,14 @@ module CryptographyBase Input> { */ abstract Algorithm getAlgorithm(); - /** - * Gets the name of this operation, e.g., "hash" or "encrypt". - */ - abstract string getOperationType(); - - final override string getInternalType() { result = this.getOperationType() } - + // TODO: I only removed this because I want the operation type to be non-string + // since for CipherOperations the user will have to pick the right type, + // and I want to force them to use a type that is restricted. In this case to a TCipherOperationType + // /** + // * Gets the name of this operation, e.g., "hash" or "encrypt". + // */ + // abstract string getOperationType(); + // final override string getInternalType() { result = this.getOperationType() } override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) or @@ -290,8 +295,7 @@ module CryptographyBase Input> { */ abstract class HashOperation extends Operation, THashOperation { abstract override HashAlgorithm getAlgorithm(); - - override string getOperationType() { result = "HashOperation" } + //override string getOperationType() { result = "HashOperation" } } newtype THashType = @@ -401,8 +405,7 @@ module CryptographyBase Input> { final override Location getLocation() { exists(LocatableElement le | this = TKeyDerivationOperation(le) and result = le.getLocation()) } - - override string getOperationType() { result = "KeyDerivationOperation" } + //override string getOperationType() { result = "KeyDerivationOperation" } } /** @@ -681,15 +684,31 @@ module CryptographyBase Input> { abstract override string getRawAlgorithmName(); } + newtype TCipherOperationMode = + EncryptionMode() or + DecryptionMode() or + UnknownCipherOperationMode() + /** * An encryption operation that processes plaintext to generate a ciphertext. * This operation takes an input message (plaintext) of arbitrary content and length * and produces a ciphertext as the output using a specified encryption algorithm (with a mode and padding). */ - abstract class EncryptionOperation extends Operation, TEncryptionOperation { - override string getOperationType() { result = "EncryptionOperation" } + // NOTE FOR NICK: making this concrete here as I don't think users need to worry about making/extending these operations, just instances + class CipherOperation extends Operation, TCipherOperation { + CipherOperationInstance instance; + + CipherOperation() { this = TCipherOperation(instance) } + + override Location getLocation() { result = instance.getLocation() } + + final TCipherOperationMode getCipherOperationMode() { + result = instance.getCipherOperationMode() + } + + final override EncryptionAlgorithm getAlgorithm() { result = instance.getAlgorithm() } - abstract override EncryptionAlgorithm getAlgorithm(); + override string getInternalType() { result = "CipherOperation" } // /** // * Gets the initialization vector associated with this encryption operation. // * From 83dc5b99065f8d4482899bb05d8736e8d6e0d13d Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Thu, 20 Feb 2025 10:45:33 -0500 Subject: [PATCH 024/336] Fixing type bug --- shared/cryptography/codeql/cryptography/Model.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 24e3d4f48ebd..17834343e6d5 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -706,7 +706,7 @@ module CryptographyBase Input> { result = instance.getCipherOperationMode() } - final override EncryptionAlgorithm getAlgorithm() { result = instance.getAlgorithm() } + final override EncryptionAlgorithm getAlgorithm() { result.getInstance() = instance.getAlgorithm() } override string getInternalType() { result = "CipherOperation" } // /** From 011ed3fbfd11a6cd7ab5b8aa13c3945881a37faf Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Thu, 20 Feb 2025 11:10:24 -0500 Subject: [PATCH 025/336] Simplifying additional flow step logic. --- java/ql/lib/experimental/Quantum/JCA.qll | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 0f505e400a06..0a7903aa2722 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -120,17 +120,13 @@ module JCAModel { exists(FieldAccess fa | c.getModeArg() = fa and ( - fa.getField().getName() = "ENCRYPT_MODE" and - state2 = Crypto::EncryptionMode() - or - fa.getField().getName() = "DECRYPT_MODE" and - state2 = Crypto::DecryptionMode() - or - fa.getField().getName() = "WRAP_MODE" and - state2 = Crypto::EncryptionMode() - or - fa.getField().getName() = "UNWRAP_MODE" and - state2 = Crypto::DecryptionMode() + if fa.getField().getName() in ["ENCRYPT_MODE", "WRAP_MODE"] + then state2 = Crypto::EncryptionMode() + else ( + if fa.getField().getName() in ["DECRYPT_MODE", "UNWRAP_MODE"] + then state2 = Crypto::DecryptionMode() + else state2 = Crypto::UnknownCipherOperationMode() + ) ) ) ) and From 9ac9252f7548d1c6f59cd2b4f159ebe57db60aa8 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Thu, 20 Feb 2025 11:11:41 -0500 Subject: [PATCH 026/336] Adding a todo --- java/ql/lib/experimental/Quantum/JCA.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 0a7903aa2722..3c37d1d717e1 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -346,6 +346,8 @@ module JCAModel { // the actual mode directly Expr getModeArg() { result = this.getArgument(0) } + // TODO: need a getModeOrigin + Expr getKey() { result = this.getArgument(1) and this.getMethod().getParameterType(1).hasName("Key") } From 86cab46b8d7bd15213ce40d57cc1fa86b01d0e43 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Fri, 21 Feb 2025 12:53:35 -0500 Subject: [PATCH 027/336] Misc. updates to support all JCA cipher operations, including wrap, unwrap and doFinal calls. Corrected pathing for init tracing to detect what mode is being set along a path. Added support for tracing the init operation mode argument to source. Since this involved creating an Operation Mode, changes were also made to make cipher block modes (CBC) more explicit (previously just called mode, but now that term is used for various purposes). --- java/ql/lib/experimental/Quantum/JCA.qll | 193 ++++++++++++++---- .../codeql/cryptography/Model.qll | 41 +++- 2 files changed, 181 insertions(+), 53 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 3c37d1d717e1..acbe6c67888f 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -58,8 +58,12 @@ module JCAModel { Expr getProviderArg() { result = this.getArgument(1) } } - class CipherDoFinalCall extends Call { - CipherDoFinalCall() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "doFinal") } + private class JCACipherOperationCall extends Call { + JCACipherOperationCall() { + exists(string s | s in ["doFinal", "wrap", "unwrap"] | + this.getCallee().hasQualifiedName("javax.crypto", "Cipher", s) + ) + } } /** @@ -81,7 +85,7 @@ module JCAModel { * For example, in `Cipher.getInstance(algorithm)`, this class represents `algorithm`. */ class CipherGetInstanceAlgorithmArg extends Crypto::EncryptionAlgorithmInstance, - Crypto::ModeOfOperationAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof Expr + Crypto::BlockCipherModeOfOperationAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof Expr { CipherGetInstanceCall call; @@ -98,68 +102,136 @@ module JCAModel { CipherGetInstanceCall getCall() { result = call } } - // TODO: what if encrypt/decrypt mode isn't known - private module CipherGetInstanceToFinalizeConfig implements DataFlow::StateConfigSig { - class FlowState = Crypto::TCipherOperationMode; + /** + * An access to the `javax.crypto.Cipher` class. + */ + private class CipherAccess extends TypeAccess { + CipherAccess() { this.getType().(Class).hasQualifiedName("javax.crypto", "Cipher") } + } + + /** + * An access to a cipher mode field of the `javax.crypto.Cipher` class, + * specifically `ENCRYPT_MODE`, `DECRYPT_MODE`, `WRAP_MODE`, or `UNWRAP_MODE`. + */ + private class JavaxCryptoCipherOperationModeAccess extends FieldAccess { + JavaxCryptoCipherOperationModeAccess() { + this.getQualifier() instanceof CipherAccess and + this.getField().getName() in ["ENCRYPT_MODE", "DECRYPT_MODE", "WRAP_MODE", "UNWRAP_MODE"] + } + } + + private newtype TCipherModeFlowState = + TUninitializedCipherModeFlowState() or + TInitializedCipherModeFlowState(CipherInitCall call) + + abstract private class CipherModeFlowState extends TCipherModeFlowState { + string toString() { + this = TUninitializedCipherModeFlowState() and result = "uninitialized" + or + this = TInitializedCipherModeFlowState(_) and result = "initialized" + } + + abstract Crypto::CipherOperationMode getCipherOperationMode(); + } + + private class UninitializedCipherModeFlowState extends CipherModeFlowState, + TUninitializedCipherModeFlowState + { + override Crypto::CipherOperationMode getCipherOperationMode() { + result instanceof Crypto::UnknownCipherOperationMode + } + } + + private class InitializedCipherModeFlowState extends CipherModeFlowState, + TInitializedCipherModeFlowState + { + CipherInitCall call; + DataFlow::Node node1; + DataFlow::Node node2; + Crypto::CipherOperationMode mode; + + InitializedCipherModeFlowState() { + this = TInitializedCipherModeFlowState(call) and + DataFlow::localFlowStep(node1, node2) and + node2.asExpr() = call.getQualifier() and + // I would imagine this would make this predicate horribly horribly inefficient + // it now binds with anything + not node1.asExpr() = call.getQualifier() and + mode = call.getCipherOperationModeType() + } + + CipherInitCall getCall() { result = call } + + DataFlow::Node getFstNode() { result = node1 } + + /** + * Returns the node *to* which the state-changing step occurs + */ + DataFlow::Node getSndNode() { result = node2 } + + override Crypto::CipherOperationMode getCipherOperationMode() { result = mode } + } + + /** + * Trace to a cryptographic operation, + * specifically `Cipher.doFinal()`, `Cipher.wrap()`, or `Cipher.unwrap()`. + */ + private module CipherGetInstanceToCipherOperationConfig implements DataFlow::StateConfigSig { + class FlowState = TCipherModeFlowState; predicate isSource(DataFlow::Node src, FlowState state) { - state = Crypto::UnknownCipherOperationMode() and + state instanceof UninitializedCipherModeFlowState and src.asExpr() instanceof CipherGetInstanceCall } - predicate isSink(DataFlow::Node sink, FlowState state) { - exists(CipherDoFinalCall c | c.getQualifier() = sink.asExpr()) + predicate isSink(DataFlow::Node sink, FlowState state) { none() } + + predicate isSink(DataFlow::Node sink) { + exists(JCACipherOperationCall c | c.getQualifier() = sink.asExpr()) } predicate isAdditionalFlowStep( DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 ) { - exists(CipherInitCall c | - c.getQualifier() = node1.asExpr() and - // TODO: not taking into consideration if the mode traces to this arg - exists(FieldAccess fa | - c.getModeArg() = fa and - ( - if fa.getField().getName() in ["ENCRYPT_MODE", "WRAP_MODE"] - then state2 = Crypto::EncryptionMode() - else ( - if fa.getField().getName() in ["DECRYPT_MODE", "UNWRAP_MODE"] - then state2 = Crypto::DecryptionMode() - else state2 = Crypto::UnknownCipherOperationMode() - ) - ) - ) - ) and - node2 = node1 + node1 = state2.(InitializedCipherModeFlowState).getFstNode() and + node2 = state2.(InitializedCipherModeFlowState).getSndNode() + } + + predicate isBarrier(DataFlow::Node node, FlowState state) { + exists(CipherInitCall call | node.asExpr() = call.getQualifier() | + state instanceof UninitializedCipherModeFlowState + or + state.(InitializedCipherModeFlowState).getCall() != call + ) } } - module CipherGetInstanceToFinalizeFlow = - DataFlow::GlobalWithState; + module CipherGetInstanceToCipherOperationFlow = + DataFlow::GlobalWithState; class CipherEncryptionOperation extends Crypto::CipherOperationInstance instanceof Call { - Crypto::TCipherOperationMode mode; + Crypto::CipherOperationMode mode; Crypto::EncryptionAlgorithmInstance algorithm; CipherEncryptionOperation() { exists( - CipherGetInstanceToFinalizeFlow::PathNode sink, - CipherGetInstanceToFinalizeFlow::PathNode src, CipherGetInstanceCall getCipher, - CipherDoFinalCall doFinalize, CipherGetInstanceAlgorithmArg arg + CipherGetInstanceToCipherOperationFlow::PathNode sink, + CipherGetInstanceToCipherOperationFlow::PathNode src, CipherGetInstanceCall getCipher, + JCACipherOperationCall doFinalize, CipherGetInstanceAlgorithmArg arg | - CipherGetInstanceToFinalizeFlow::flowPath(src, sink) and + CipherGetInstanceToCipherOperationFlow::flowPath(src, sink) and src.getNode().asExpr() = getCipher and sink.getNode().asExpr() = doFinalize.getQualifier() and - sink.getState() = mode and + sink.getState().(CipherModeFlowState).getCipherOperationMode() = mode and this = doFinalize and - arg.getCall() = getCipher and + arg.getCall() = getCipher and algorithm = arg ) } override Crypto::EncryptionAlgorithmInstance getAlgorithm() { result = algorithm } - override Crypto::TCipherOperationMode getCipherOperationMode() { result = mode } + override Crypto::CipherOperationMode getCipherOperationMode() { result = mode } } /** @@ -177,7 +249,7 @@ module JCAModel { CipherGetInstanceAlgorithmArg instance; ModeOfOperation() { - this = Crypto::TModeOfOperationAlgorithm(instance) and + this = Crypto::TBlockCipherModeOfOperationAlgorithm(instance) and // TODO: this currently only holds for explicitly defined modes in a string literal. // Cases with defaults, e.g., "AES", are not yet modelled. // For these cases, in a CBOM, the AES node would have an unknown edge to its mode child. @@ -190,7 +262,7 @@ module JCAModel { // TODO: handle defaults override string getRawAlgorithmName() { result = instance.getOrigin().getMode() } - private predicate modeToNameMappingKnown(Crypto::TModeOperationType type, string name) { + private predicate modeToNameMappingKnown(Crypto::TBlockCipherModeOperationType type, string name) { type instanceof Crypto::ECB and name = "ECB" or type instanceof Crypto::CBC and name = "CBC" @@ -208,7 +280,7 @@ module JCAModel { type instanceof Crypto::OCB and name = "OCB" } - override Crypto::TModeOperationType getModeType() { + override Crypto::TBlockCipherModeOperationType getModeType() { if this.modeToNameMappingKnown(_, instance.getOrigin().getMode()) then this.modeToNameMappingKnown(result, instance.getOrigin().getMode()) else result instanceof Crypto::OtherMode @@ -339,14 +411,51 @@ module JCAModel { override Expr getInput() { result = this.(ClassInstanceExpr).getArgument(1) } } + private module JavaxCipherModeAccessToInitConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + src.asExpr() instanceof JavaxCryptoCipherOperationModeAccess + } + + predicate isSink(DataFlow::Node sink) { + exists(CipherInitCall c | c.getModeArg() = sink.asExpr()) + } + } + + module JavaxCipherModeAccessToInitFlow = DataFlow::Global; + class CipherInitCall extends MethodCall { CipherInitCall() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "init") } - // TODO: this doesn't account for tracing the mode to this arg if expending this arg to have - // the actual mode directly + /** + * Returns the mode argument to the `init` method + * that is used to determine the cipher operation mode. + * Note this is the raw expr and not necessarily a direct access + * of a mode. Use `getModeOrigin()` to get the field access origin + * flowing to this argument, if one exists (is known). + */ Expr getModeArg() { result = this.getArgument(0) } - // TODO: need a getModeOrigin + JavaxCryptoCipherOperationModeAccess getModeOrigin() { + exists(DataFlow::Node src, DataFlow::Node sink | + JavaxCipherModeAccessToInitFlow::flow(src, sink) and + src.asExpr() = result and + this.getModeArg() = sink.asExpr() + ) + } + + Crypto::CipherOperationMode getCipherOperationModeType() { + if not exists(this.getModeOrigin()) + then result instanceof Crypto::UnknownCipherOperationMode + else + if this.getModeOrigin().getField().getName() in ["ENCRYPT_MODE", "WRAP_MODE"] + then result instanceof Crypto::EncryptionMode + else + if this.getModeOrigin().getField().getName() in ["DECRYPT_MODE", "UNWRAP_MODE"] + then result instanceof Crypto::DecryptionMode + else + // TODO/Question: distinguish between unknown vs unspecified? (the field access is not recognized, vs no field access is found) + result instanceof Crypto::UnknownCipherOperationMode + } Expr getKey() { result = this.getArgument(1) and this.getMethod().getParameterType(1).hasName("Key") diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 17834343e6d5..a0f22d0229b6 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -82,7 +82,7 @@ module CryptographyBase Input> { abstract class CipherOperationInstance extends LocatableElement { abstract EncryptionAlgorithmInstance getAlgorithm(); - abstract TCipherOperationMode getCipherOperationMode(); + abstract CipherOperationMode getCipherOperationMode(); } abstract class EncryptionAlgorithmInstance extends LocatableElement { } @@ -94,7 +94,7 @@ module CryptographyBase Input> { abstract class EllipticCurveAlgorithmInstance extends LocatableElement { } // Non-standalone algorithms - abstract class ModeOfOperationAlgorithmInstance extends LocatableElement { } + abstract class BlockCipherModeOfOperationAlgorithmInstance extends LocatableElement { } abstract class PaddingAlgorithmInstance extends LocatableElement { } @@ -128,7 +128,8 @@ module CryptographyBase Input> { TKeyDerivationAlgorithm(KeyDerivationAlgorithmInstance e) or TKeyEncapsulationAlgorithm(KeyEncapsulationAlgorithmInstance e) or // Non-standalone Algorithms (e.g., Mode, Padding) - TModeOfOperationAlgorithm(ModeOfOperationAlgorithmInstance e) or + // TODO: need to rename this, as "mode" is getting reused in different contexts, be precise + TBlockCipherModeOfOperationAlgorithm(BlockCipherModeOfOperationAlgorithmInstance e) or TPaddingAlgorithm(PaddingAlgorithmInstance e) or // Composite and hybrid cryptosystems (e.g., RSA-OAEP used with AES, post-quantum hybrid cryptosystems) // These nodes are always parent nodes and are not modeled but rather defined via library-agnostic patterns. @@ -685,9 +686,25 @@ module CryptographyBase Input> { } newtype TCipherOperationMode = - EncryptionMode() or - DecryptionMode() or - UnknownCipherOperationMode() + TEncryptionMode() or + TDecryptionMode() or + TUnknownCipherOperationMode() + + abstract class CipherOperationMode extends TCipherOperationMode { + abstract string toString(); + } + + class EncryptionMode extends CipherOperationMode, TEncryptionMode { + override string toString() { result = "Encryption" } + } + + class DecryptionMode extends CipherOperationMode, TDecryptionMode { + override string toString() { result = "Decryption" } + } + + class UnknownCipherOperationMode extends CipherOperationMode, TUnknownCipherOperationMode { + override string toString() { result = "Unknown" } + } /** * An encryption operation that processes plaintext to generate a ciphertext. @@ -706,7 +723,9 @@ module CryptographyBase Input> { result = instance.getCipherOperationMode() } - final override EncryptionAlgorithm getAlgorithm() { result.getInstance() = instance.getAlgorithm() } + final override EncryptionAlgorithm getAlgorithm() { + result.getInstance() = instance.getAlgorithm() + } override string getInternalType() { result = "CipherOperation" } // /** @@ -721,7 +740,7 @@ module CryptographyBase Input> { /** * Block cipher modes of operation algorithms */ - newtype TModeOperationType = + newtype TBlockCipherModeOperationType = ECB() or // Not secure, widely used CBC() or // Vulnerable to padding oracle attacks GCM() or // Widely used AEAD mode (TLS 1.3, SSH, IPsec) @@ -732,7 +751,7 @@ module CryptographyBase Input> { OCB() or // Efficient AEAD mode OtherMode() - abstract class ModeOfOperationAlgorithm extends Algorithm, TModeOfOperationAlgorithm { + abstract class ModeOfOperationAlgorithm extends Algorithm, TBlockCipherModeOfOperationAlgorithm { override string getAlgorithmType() { result = "ModeOfOperation" } /** @@ -742,10 +761,10 @@ module CryptographyBase Input> { * * If a type cannot be determined, the result is `OtherMode`. */ - abstract TModeOperationType getModeType(); + abstract TBlockCipherModeOperationType getModeType(); bindingset[type] - final private predicate modeToNameMapping(TModeOperationType type, string name) { + final private predicate modeToNameMapping(TBlockCipherModeOperationType type, string name) { type instanceof ECB and name = "ECB" or type instanceof CBC and name = "CBC" From 2b0b927b0b14ad819f2e07588d2b75042cbd2545 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Mon, 24 Feb 2025 17:37:41 +0100 Subject: [PATCH 028/336] Add Nonce association to Operation, update graph --- java/ql/lib/experimental/Quantum/JCA.qll | 176 ++++++++----- java/ql/lib/experimental/Quantum/Language.qll | 32 +-- .../src/experimental/Quantum/ReusedNonce.ql | 23 ++ java/ql/src/experimental/Quantum/Test.ql | 9 - .../ql/src/experimental/Quantum/TestCipher.ql | 16 ++ misc/scripts/cryptography/cbom.sh | 6 +- misc/scripts/cryptography/generate_cbom.py | 10 +- .../codeql/cryptography/Model.qll | 233 ++++++++++-------- 8 files changed, 297 insertions(+), 208 deletions(-) create mode 100644 java/ql/src/experimental/Quantum/ReusedNonce.ql delete mode 100644 java/ql/src/experimental/Quantum/Test.ql create mode 100644 java/ql/src/experimental/Quantum/TestCipher.ql diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index acbe6c67888f..9892b445312a 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -1,5 +1,6 @@ import java import semmle.code.java.dataflow.DataFlow +import semmle.code.java.controlflow.Dominance module JCAModel { import Language @@ -64,6 +65,8 @@ module JCAModel { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", s) ) } + + DataFlow::Node getInputData() { result.asExpr() = this.getArgument(0) } } /** @@ -84,7 +87,7 @@ module JCAModel { * * For example, in `Cipher.getInstance(algorithm)`, this class represents `algorithm`. */ - class CipherGetInstanceAlgorithmArg extends Crypto::EncryptionAlgorithmInstance, + class CipherGetInstanceAlgorithmArg extends Crypto::CipherAlgorithmInstance, Crypto::BlockCipherModeOfOperationAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof Expr { CipherGetInstanceCall call; @@ -116,13 +119,22 @@ module JCAModel { private class JavaxCryptoCipherOperationModeAccess extends FieldAccess { JavaxCryptoCipherOperationModeAccess() { this.getQualifier() instanceof CipherAccess and - this.getField().getName() in ["ENCRYPT_MODE", "DECRYPT_MODE", "WRAP_MODE", "UNWRAP_MODE"] + this.getField().getName().toUpperCase() in [ + "ENCRYPT_MODE", "DECRYPT_MODE", "WRAP_MODE", "UNWRAP_MODE" + ] } } + class CipherUpdateCall extends MethodCall { + CipherUpdateCall() { this.getMethod().hasQualifiedName("javax.crypto", "Cipher", "update") } + + DataFlow::Node getInputData() { result.asExpr() = this.getArgument(0) } + } + private newtype TCipherModeFlowState = TUninitializedCipherModeFlowState() or - TInitializedCipherModeFlowState(CipherInitCall call) + TInitializedCipherModeFlowState(CipherInitCall call) or + TUsedCipherModeFlowState(CipherInitCall init, CipherUpdateCall update) abstract private class CipherModeFlowState extends TCipherModeFlowState { string toString() { @@ -131,13 +143,13 @@ module JCAModel { this = TInitializedCipherModeFlowState(_) and result = "initialized" } - abstract Crypto::CipherOperationMode getCipherOperationMode(); + abstract Crypto::CipherOperationSubtype getCipherOperationMode(); } private class UninitializedCipherModeFlowState extends CipherModeFlowState, TUninitializedCipherModeFlowState { - override Crypto::CipherOperationMode getCipherOperationMode() { + override Crypto::CipherOperationSubtype getCipherOperationMode() { result instanceof Crypto::UnknownCipherOperationMode } } @@ -148,19 +160,18 @@ module JCAModel { CipherInitCall call; DataFlow::Node node1; DataFlow::Node node2; - Crypto::CipherOperationMode mode; + Crypto::CipherOperationSubtype mode; InitializedCipherModeFlowState() { this = TInitializedCipherModeFlowState(call) and DataFlow::localFlowStep(node1, node2) and node2.asExpr() = call.getQualifier() and - // I would imagine this would make this predicate horribly horribly inefficient - // it now binds with anything + // TODO: does this make this predicate inefficient as it binds with anything? not node1.asExpr() = call.getQualifier() and mode = call.getCipherOperationModeType() } - CipherInitCall getCall() { result = call } + CipherInitCall getInitCall() { result = call } DataFlow::Node getFstNode() { result = node1 } @@ -169,12 +180,14 @@ module JCAModel { */ DataFlow::Node getSndNode() { result = node2 } - override Crypto::CipherOperationMode getCipherOperationMode() { result = mode } + override Crypto::CipherOperationSubtype getCipherOperationMode() { result = mode } } /** - * Trace to a cryptographic operation, + * Trace from cipher initialization to a cryptographic operation, * specifically `Cipher.doFinal()`, `Cipher.wrap()`, or `Cipher.unwrap()`. + * + * TODO: handle `Cipher.update()` */ private module CipherGetInstanceToCipherOperationConfig implements DataFlow::StateConfigSig { class FlowState = TCipherModeFlowState; @@ -201,7 +214,7 @@ module JCAModel { exists(CipherInitCall call | node.asExpr() = call.getQualifier() | state instanceof UninitializedCipherModeFlowState or - state.(InitializedCipherModeFlowState).getCall() != call + state.(InitializedCipherModeFlowState).getInitCall() != call ) } } @@ -209,15 +222,16 @@ module JCAModel { module CipherGetInstanceToCipherOperationFlow = DataFlow::GlobalWithState; - class CipherEncryptionOperation extends Crypto::CipherOperationInstance instanceof Call { - Crypto::CipherOperationMode mode; - Crypto::EncryptionAlgorithmInstance algorithm; + class CipherOperationInstance extends Crypto::CipherOperationInstance instanceof Call { + Crypto::CipherOperationSubtype mode; + Crypto::CipherAlgorithmInstance algorithm; + CipherGetInstanceToCipherOperationFlow::PathNode sink; + JCACipherOperationCall doFinalize; - CipherEncryptionOperation() { + CipherOperationInstance() { exists( - CipherGetInstanceToCipherOperationFlow::PathNode sink, CipherGetInstanceToCipherOperationFlow::PathNode src, CipherGetInstanceCall getCipher, - JCACipherOperationCall doFinalize, CipherGetInstanceAlgorithmArg arg + CipherGetInstanceAlgorithmArg arg | CipherGetInstanceToCipherOperationFlow::flowPath(src, sink) and src.getNode().asExpr() = getCipher and @@ -229,9 +243,19 @@ module JCAModel { ) } - override Crypto::EncryptionAlgorithmInstance getAlgorithm() { result = algorithm } + override Crypto::CipherAlgorithmInstance getAlgorithm() { result = algorithm } - override Crypto::CipherOperationMode getCipherOperationMode() { result = mode } + override Crypto::CipherOperationSubtype getCipherOperationSubtype() { result = mode } + + override Crypto::NonceArtifactInstance getNonce() { + NonceArtifactToCipherInitCallFlow::flow(result.asOutputData(), + DataFlow::exprNode(sink.getState() + .(InitializedCipherModeFlowState) + .getInitCall() + .getNonceArg())) + } + + override DataFlow::Node getInputData() { result = doFinalize.getInputData() } } /** @@ -319,12 +343,12 @@ module JCAModel { CipherStringLiteral getInstance() { result = instance } } - class EncryptionAlgorithm extends Crypto::EncryptionAlgorithm { + class EncryptionAlgorithm extends Crypto::CipherAlgorithm { CipherStringLiteral origin; CipherGetInstanceAlgorithmArg instance; EncryptionAlgorithm() { - this = Crypto::TEncryptionAlgorithm(instance) and + this = Crypto::TCipherAlgorithm(instance) and instance.getOrigin() = origin } @@ -347,7 +371,7 @@ module JCAModel { override Crypto::TCipherType getCipherFamily() { if this.cipherNameMappingKnown(_, origin.getAlgorithmName()) then this.cipherNameMappingKnown(result, origin.getAlgorithmName()) - else result instanceof Crypto::OtherSymmetricCipherType + else result instanceof Crypto::OtherCipherType } override string getKeySize(Location location) { none() } @@ -384,33 +408,71 @@ module JCAModel { } /** - * Initialiation vectors + * Initialization vectors and other nonce artifacts */ - abstract class IVParameterInstantiation extends Crypto::InitializationVectorArtifactInstance instanceof ClassInstanceExpr + abstract class NonceParameterInstantiation extends Crypto::NonceArtifactInstance instanceof ClassInstanceExpr { - abstract Expr getInput(); + override DataFlow::Node asOutputData() { result.asExpr() = this } } - class IvParameterSpecInstance extends IVParameterInstantiation { + class IvParameterSpecInstance extends NonceParameterInstantiation { IvParameterSpecInstance() { this.(ClassInstanceExpr) .getConstructedType() .hasQualifiedName("javax.crypto.spec", "IvParameterSpec") } - override Expr getInput() { result = this.(ClassInstanceExpr).getArgument(0) } + override DataFlow::Node getInput() { result.asExpr() = this.(ClassInstanceExpr).getArgument(0) } } - class GCMParameterSpecInstance extends IVParameterInstantiation { + // TODO: this also specifies the tag length for GCM + class GCMParameterSpecInstance extends NonceParameterInstantiation { GCMParameterSpecInstance() { this.(ClassInstanceExpr) .getConstructedType() .hasQualifiedName("javax.crypto.spec", "GCMParameterSpec") } - override Expr getInput() { result = this.(ClassInstanceExpr).getArgument(1) } + override DataFlow::Node getInput() { result.asExpr() = this.(ClassInstanceExpr).getArgument(1) } + } + + class IvParameterSpecGetIvCall extends MethodCall { + IvParameterSpecGetIvCall() { + this.getMethod().hasQualifiedName("javax.crypto.spec", "IvParameterSpec", "getIV") + } } + module NonceArtifactToCipherInitCallConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + exists(NonceParameterInstantiation n | + src = n.asOutputData() and + not exists(IvParameterSpecGetIvCall m | n.getInput().asExpr() = m) + ) + } + + predicate isSink(DataFlow::Node sink) { + exists(CipherInitCall c | c.getNonceArg() = sink.asExpr()) + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + exists(IvParameterSpecGetIvCall m | + node1.asExpr() = m.getQualifier() and + node2.asExpr() = m + ) + or + exists(NonceParameterInstantiation n | + node1 = n.getInput() and + node2.asExpr() = n + ) + } + } + + module NonceArtifactToCipherInitCallFlow = DataFlow::Global; + + /** + * A data-flow configuration to track flow from a mode field access to + * the mode argument of the `init` method of the `javax.crypto.Cipher` class. + */ private module JavaxCipherModeAccessToInitConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof JavaxCryptoCipherOperationModeAccess @@ -423,6 +485,18 @@ module JCAModel { module JavaxCipherModeAccessToInitFlow = DataFlow::Global; + private predicate cipher_mode_str_to_cipher_mode_known( + string mode, Crypto::CipherOperationSubtype cipher_mode + ) { + mode = "ENCRYPT_MODE" and cipher_mode instanceof Crypto::EncryptionMode + or + mode = "WRAP_MODE" and cipher_mode instanceof Crypto::WrapMode + or + mode = "DECRYPT_MODE" and cipher_mode instanceof Crypto::DecryptionMode + or + mode = "UNWRAP_MODE" and cipher_mode instanceof Crypto::UnwrapMode + } + class CipherInitCall extends MethodCall { CipherInitCall() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "init") } @@ -443,49 +517,19 @@ module JCAModel { ) } - Crypto::CipherOperationMode getCipherOperationModeType() { - if not exists(this.getModeOrigin()) - then result instanceof Crypto::UnknownCipherOperationMode - else - if this.getModeOrigin().getField().getName() in ["ENCRYPT_MODE", "WRAP_MODE"] - then result instanceof Crypto::EncryptionMode - else - if this.getModeOrigin().getField().getName() in ["DECRYPT_MODE", "UNWRAP_MODE"] - then result instanceof Crypto::DecryptionMode - else - // TODO/Question: distinguish between unknown vs unspecified? (the field access is not recognized, vs no field access is found) - result instanceof Crypto::UnknownCipherOperationMode + Crypto::CipherOperationSubtype getCipherOperationModeType() { + if cipher_mode_str_to_cipher_mode_known(this.getModeOrigin().getField().getName(), _) + then cipher_mode_str_to_cipher_mode_known(this.getModeOrigin().getField().getName(), result) + else result instanceof Crypto::UnknownCipherOperationMode } - Expr getKey() { + Expr getKeyArg() { result = this.getArgument(1) and this.getMethod().getParameterType(1).hasName("Key") } - Expr getIV() { + Expr getNonceArg() { result = this.getArgument(2) and this.getMethod().getParameterType(2).hasName("AlgorithmParameterSpec") } } - - // TODO: cipher.getParameters().getParameterSpec(GCMParameterSpec.class); - /* - * class InitializationVectorArg extends Crypto::InitializationVectorArtifactInstance instanceof Expr - * { - * IVParameterInstantiation creation; - * - * InitializationVectorArg() { this = creation.getInput() } - * } - */ - - class InitializationVector extends Crypto::InitializationVector { - IVParameterInstantiation instance; - - InitializationVector() { this = Crypto::TInitializationVector(instance) } - - override Location getLocation() { result = instance.getLocation() } - - override Crypto::DataFlowNode asOutputData() { result.asExpr() = instance } - - override Crypto::DataFlowNode getInputData() { result.asExpr() = instance.getInput() } - } } diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 5801815109b0..e88bce6d9959 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -23,8 +23,6 @@ module CryptoInput implements InputSig { class LocatableElement = Language::Element; class UnknownLocation = UnknownDefaultLocation; - - predicate rngToIvFlow(DataFlowNode rng, DataFlowNode iv) { none() } } /** @@ -37,9 +35,7 @@ module Crypto = CryptographyBase; * tied to an output node (i.e., the result of the source of randomness) */ abstract class RandomnessInstance extends Crypto::RandomNumberGenerationInstance { - abstract Crypto::RNGSourceSecurity getSourceSecurity(); - - Crypto::TRNGSeedSecurity getSeedSecurity(Location location) { none() } + override DataFlow::Node asOutputData() { result.asExpr() = this } } class SecureRandomnessInstance extends RandomnessInstance { @@ -48,36 +44,10 @@ class SecureRandomnessInstance extends RandomnessInstance { s.getSourceOfRandomness() instanceof SecureRandomNumberGenerator ) } - - override Crypto::RNGSourceSecurity getSourceSecurity() { - result instanceof Crypto::RNGSourceSecure - } } class InsecureRandomnessInstance extends RandomnessInstance { InsecureRandomnessInstance() { exists(InsecureRandomnessSource node | this = node.asExpr()) } - - override Crypto::RNGSourceSecurity getSourceSecurity() { - result instanceof Crypto::RNGSourceInsecure - } -} - -class RandomnessArtifact extends Crypto::RandomNumberGeneration { - RandomnessInstance instance; - - RandomnessArtifact() { this = Crypto::TRandomNumberGeneration(instance) } - - override Location getLocation() { result = instance.getLocation() } - - override Crypto::RNGSourceSecurity getSourceSecurity() { result = instance.getSourceSecurity() } - - override Crypto::TRNGSeedSecurity getSeedSecurity(Location location) { - result = instance.getSeedSecurity(location) - } - - override Crypto::DataFlowNode asOutputData() { result.asExpr() = instance } - - override Crypto::DataFlowNode getInputData() { none() } } // Import library-specific modeling diff --git a/java/ql/src/experimental/Quantum/ReusedNonce.ql b/java/ql/src/experimental/Quantum/ReusedNonce.ql new file mode 100644 index 000000000000..cb0d6ff9d610 --- /dev/null +++ b/java/ql/src/experimental/Quantum/ReusedNonce.ql @@ -0,0 +1,23 @@ +/** + * @name Unsafe nonce source or reuse + * @id java/unsafe-nonce-source-or-reuse + */ + +import experimental.Quantum.Language +import semmle.code.java.dataflow.DataFlow + +Element getNonceOrigin(Crypto::NonceArtifactInstance nonce) { + // TODO: this check is currently ultra hacky just for demoing + result = nonce.getInput().asExpr().(VarAccess).getVariable() +} + +from + Crypto::CipherOperationInstance op, Crypto::NonceArtifactInstance nonce1, + Crypto::NonceArtifactInstance nonce2 +where + op.(Expr).getEnclosingCallable().getName() = "encrypt" and + nonce1 = op.getNonce() and + nonce2 = op.getNonce() and + not nonce1 = nonce2 and + getNonceOrigin(nonce1) = getNonceOrigin(nonce2) +select op, nonce1, nonce2 diff --git a/java/ql/src/experimental/Quantum/Test.ql b/java/ql/src/experimental/Quantum/Test.ql deleted file mode 100644 index ba76213132c3..000000000000 --- a/java/ql/src/experimental/Quantum/Test.ql +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @name "PQC Test" - */ - -import experimental.Quantum.Language - -from Crypto::EncryptionAlgorithm a, Crypto::ModeOfOperationAlgorithm m, Crypto::PaddingAlgorithm p -where m = a.getModeOfOperation() and p = a.getPadding() -select a, a.getRawAlgorithmName(), m, m.getRawAlgorithmName(), p, p.getRawAlgorithmName() diff --git a/java/ql/src/experimental/Quantum/TestCipher.ql b/java/ql/src/experimental/Quantum/TestCipher.ql new file mode 100644 index 000000000000..6be308c25606 --- /dev/null +++ b/java/ql/src/experimental/Quantum/TestCipher.ql @@ -0,0 +1,16 @@ +/** + * @name "PQC Test" + */ + +import experimental.Quantum.Language + +from + Crypto::CipherOperation op, Crypto::CipherAlgorithm a, Crypto::ModeOfOperationAlgorithm m, + Crypto::PaddingAlgorithm p, Crypto::Nonce nonce +where + a = op.getAlgorithm() and + m = a.getModeOfOperation() and + p = a.getPadding() and + nonce = op.getNonce() +select op, op.getCipherOperationMode(), a, a.getRawAlgorithmName(), m, m.getRawAlgorithmName(), p, + p.getRawAlgorithmName(), nonce, nonce.getInputData() diff --git a/misc/scripts/cryptography/cbom.sh b/misc/scripts/cryptography/cbom.sh index 9cbef951bbf4..ef558ccf432e 100755 --- a/misc/scripts/cryptography/cbom.sh +++ b/misc/scripts/cryptography/cbom.sh @@ -1,8 +1,8 @@ #!/bin/bash -CODEQL_PATH="/Users/nicolaswill/Library/Application Support/Code/User/globalStorage/github.vscode-codeql/distribution5/codeql/codeql" -DATABASE_PATH="/Users/nicolaswill/openssl_codeql/openssl/openssl_db" -QUERY_FILE="/Users/nicolaswill/pqc/codeql/cpp/ql/src/experimental/Quantum/CBOMGraph.ql" +CODEQL_PATH="/Users/nicolaswill/.local/share/gh/extensions/gh-codeql/dist/release/v2.20.4/codeql" +DATABASE_PATH="/Users/nicolaswill/pqc/gpt-crypto-test-cases/gpt_ai_gen_jca_test_cases_db" +QUERY_FILE="/Users/nicolaswill/pqc/codeql/java/ql/src/experimental/Quantum/PrintCBOMGraph.ql" OUTPUT_DIR="graph_output" python3 generate_cbom.py -c "$CODEQL_PATH" -d "$DATABASE_PATH" -q "$QUERY_FILE" -o "$OUTPUT_DIR" diff --git a/misc/scripts/cryptography/generate_cbom.py b/misc/scripts/cryptography/generate_cbom.py index 10ec895dc629..07400d6cd6a3 100644 --- a/misc/scripts/cryptography/generate_cbom.py +++ b/misc/scripts/cryptography/generate_cbom.py @@ -56,6 +56,9 @@ def convert_dgml_to_dot(dgml_file, dot_file): else: label_parts.append(f"{key}={value}") label = "\\n".join(label_parts) + # Escape forward slashes and double quotes + label = label.replace("/", "\\/") + label = label.replace("\"", "\\\"") prop_l = [f'label="{label}"'] node_s = f'nd_{node_id} [{", ".join(prop_l)}];' body_l.append(node_s) @@ -63,8 +66,11 @@ def convert_dgml_to_dot(dgml_file, dot_file): # Process edges for edge in root.find("{http://schemas.microsoft.com/vs/2009/dgml}Links"): att = edge.attrib + edge_label = att.get("Label", "") + edge_label = edge_label.replace("/", "\\/") + edge_label = edge_label.replace("\"", "\\\"") edge_s = 'nd_{} -> nd_{} [label="{}"];'.format( - att["Source"], att["Target"], att.get("Label", "")) + att["Source"], att["Target"], edge_label) body_l.append(edge_s) body_l.append("}") @@ -89,7 +95,7 @@ def main(): run_codeql_analysis(args.codeql, args.database, args.query, args.output) # Locate DGML file - dgml_file = os.path.join(args.output, "cbomgraph.dgml") + dgml_file = os.path.join(args.output, "java", "print-cbom-graph.dgml") dot_file = dgml_file.replace(".dgml", ".dot") if os.path.exists(dgml_file): diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index a0f22d0229b6..e5b91e198eaf 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -19,8 +19,6 @@ signature module InputSig { } class UnknownLocation instanceof Location; - - predicate rngToIvFlow(DataFlowNode rng, DataFlowNode iv); } module CryptographyBase Input> { @@ -34,11 +32,13 @@ module CryptographyBase Input> { UnknownPropertyValue() { this = "" } } - private string getPropertyAsGraphString(NodeBase node, string key) { + private string getPropertyAsGraphString(NodeBase node, string key, Location root) { result = strictconcat(any(string value, Location location, string parsed | node.properties(key, value, location) and - parsed = "(" + value + "," + location.toString() + ")" + if location = root or location instanceof UnknownLocation + then parsed = value + else parsed = "(" + value + "," + location.toString() + ")" | parsed ), "," @@ -46,19 +46,26 @@ module CryptographyBase Input> { } predicate nodes_graph_impl(NodeBase node, string key, string value) { - key = "semmle.label" and - value = node.toString() - or - // CodeQL's DGML output does not include a location - key = "Location" and - value = node.getLocation().toString() - or - // Known unknown edges should be reported as properties rather than edges - node = node.getChild(key) and - value = "" - or - // Report properties - value = getPropertyAsGraphString(node, key) + not ( + // exclude Artifact nodes with no edges to or from them + node instanceof Artifact and + not (edges_graph_impl(node, _, _, _) or edges_graph_impl(_, node, _, _)) + ) and + ( + key = "semmle.label" and + value = node.toString() + or + // CodeQL's DGML output does not include a location + key = "Location" and + value = node.getLocation().toString() + or + // Known unknown edges should be reported as properties rather than edges + node = node.getChild(key) and + value = "" + or + // Report properties + value = getPropertyAsGraphString(node, key, node.getLocation()) + ) } predicate edges_graph_impl(NodeBase source, NodeBase target, string key, string value) { @@ -80,12 +87,16 @@ module CryptographyBase Input> { abstract class KeyDerivationAlgorithmInstance extends LocatableElement { } abstract class CipherOperationInstance extends LocatableElement { - abstract EncryptionAlgorithmInstance getAlgorithm(); + abstract CipherAlgorithmInstance getAlgorithm(); + + abstract CipherOperationSubtype getCipherOperationSubtype(); - abstract CipherOperationMode getCipherOperationMode(); + abstract NonceArtifactInstance getNonce(); + + abstract DataFlowNode getInputData(); } - abstract class EncryptionAlgorithmInstance extends LocatableElement { } + abstract class CipherAlgorithmInstance extends LocatableElement { } abstract class KeyEncapsulationOperationInstance extends LocatableElement { } @@ -99,21 +110,26 @@ module CryptographyBase Input> { abstract class PaddingAlgorithmInstance extends LocatableElement { } // Artifacts - abstract class DigestArtifactInstance extends LocatableElement { } + abstract private class ArtifactLocatableElement extends LocatableElement { + abstract DataFlowNode asOutputData(); - abstract class KeyArtifactInstance extends LocatableElement { } + abstract DataFlowNode getInput(); + } - abstract class InitializationVectorArtifactInstance extends LocatableElement { } + abstract class DigestArtifactInstance extends ArtifactLocatableElement { } - abstract class NonceArtifactInstance extends LocatableElement { } + abstract class KeyArtifactInstance extends ArtifactLocatableElement { } - abstract class RandomNumberGenerationInstance extends LocatableElement { } + abstract class NonceArtifactInstance extends ArtifactLocatableElement { } + + abstract class RandomNumberGenerationInstance extends ArtifactLocatableElement { + final override DataFlowNode getInput() { none() } + } newtype TNode = // Artifacts (data that is not an operation or algorithm, e.g., a key) TDigest(DigestArtifactInstance e) or TKey(KeyArtifactInstance e) or - TInitializationVector(InitializationVectorArtifactInstance e) or TNonce(NonceArtifactInstance e) or TRandomNumberGeneration(RandomNumberGenerationInstance e) or // Operations (e.g., hashing, encryption) @@ -122,7 +138,7 @@ module CryptographyBase Input> { TCipherOperation(CipherOperationInstance e) or TKeyEncapsulationOperation(KeyEncapsulationOperationInstance e) or // Algorithms (e.g., SHA-256, AES) - TEncryptionAlgorithm(EncryptionAlgorithmInstance e) or + TCipherAlgorithm(CipherAlgorithmInstance e) or TEllipticCurveAlgorithm(EllipticCurveAlgorithmInstance e) or THashAlgorithm(HashAlgorithmInstance e) or TKeyDerivationAlgorithm(KeyDerivationAlgorithmInstance e) or @@ -133,10 +149,10 @@ module CryptographyBase Input> { TPaddingAlgorithm(PaddingAlgorithmInstance e) or // Composite and hybrid cryptosystems (e.g., RSA-OAEP used with AES, post-quantum hybrid cryptosystems) // These nodes are always parent nodes and are not modeled but rather defined via library-agnostic patterns. - TKemDemHybridCryptosystem(EncryptionAlgorithm dem) or // TODO, change this relation and the below ones - TKeyAgreementHybridCryptosystem(EncryptionAlgorithmInstance ka) or - TAsymmetricEncryptionMacHybridCryptosystem(EncryptionAlgorithmInstance enc) or - TPostQuantumHybridCryptosystem(EncryptionAlgorithmInstance enc) + TKemDemHybridCryptosystem(CipherAlgorithm dem) or // TODO, change this relation and the below ones + TKeyAgreementHybridCryptosystem(CipherAlgorithmInstance ka) or + TAsymmetricEncryptionMacHybridCryptosystem(CipherAlgorithmInstance enc) or + TPostQuantumHybridCryptosystem(CipherAlgorithmInstance enc) /** * The base class for all cryptographic assets, such as operations and algorithms. @@ -183,7 +199,7 @@ module CryptographyBase Input> { } /** - * Returns the parent of this node. + * Returns a parent of this node. */ final NodeBase getAParent() { result.getChild(_) = this } } @@ -197,43 +213,43 @@ module CryptographyBase Input> { } /** - * An initialization vector + * A nonce or initialization vector */ - abstract class InitializationVector extends Artifact, TInitializationVector { - final override string getInternalType() { result = "InitializationVector" } + private class NonceImpl extends Artifact, TNonce { + NonceArtifactInstance instance; - RandomNumberGeneration getRNGSource() { - Input::rngToIvFlow(result.asOutputData(), this.getInputData()) - } - } + NonceImpl() { this = TNonce(instance) } - newtype TRNGSourceSecurity = - RNGSourceSecure() or // Secure RNG source (unrelated to seed) - RNGSourceInsecure() // Insecure RNG source (unrelated to seed) + final override string getInternalType() { result = "Nonce" } - class RNGSourceSecurity extends TRNGSourceSecurity { - string toString() { - this instanceof RNGSourceSecure and result = "Secure RNG Source" - or - this instanceof RNGSourceInsecure and result = "Insecure RNG Source" - } + override Location getLocation() { result = instance.getLocation() } + + override DataFlowNode asOutputData() { result = instance.asOutputData() } + + override DataFlowNode getInputData() { result = instance.getInput() } } - newtype TRNGSeedSecurity = - RNGSeedSecure() or - RNGSeedInsecure() + final class Nonce = NonceImpl; /** * A source of random number generation */ - abstract class RandomNumberGeneration extends Artifact, TRandomNumberGeneration { + final private class RandomNumberGenerationImpl extends Artifact, TRandomNumberGeneration { + RandomNumberGenerationInstance instance; + + RandomNumberGenerationImpl() { this = TRandomNumberGeneration(instance) } + final override string getInternalType() { result = "RandomNumberGeneration" } - abstract RNGSourceSecurity getSourceSecurity(); + override Location getLocation() { result = instance.getLocation() } + + override DataFlowNode asOutputData() { result = instance.asOutputData() } - abstract TRNGSeedSecurity getSeedSecurity(Location location); + override DataFlowNode getInputData() { result = instance.getInput() } } + final class RandomNumberGeneration = RandomNumberGenerationImpl; + /** * A cryptographic operation, such as hashing or encryption. */ @@ -243,14 +259,6 @@ module CryptographyBase Input> { */ abstract Algorithm getAlgorithm(); - // TODO: I only removed this because I want the operation type to be non-string - // since for CipherOperations the user will have to pick the right type, - // and I want to force them to use a type that is restricted. In this case to a TCipherOperationType - // /** - // * Gets the name of this operation, e.g., "hash" or "encrypt". - // */ - // abstract string getOperationType(); - // final override string getInternalType() { result = this.getOperationType() } override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) or @@ -685,24 +693,34 @@ module CryptographyBase Input> { abstract override string getRawAlgorithmName(); } - newtype TCipherOperationMode = + newtype TCipherOperationSubtype = TEncryptionMode() or TDecryptionMode() or + TWrapMode() or + TUnwrapMode() or TUnknownCipherOperationMode() - abstract class CipherOperationMode extends TCipherOperationMode { + abstract class CipherOperationSubtype extends TCipherOperationSubtype { abstract string toString(); } - class EncryptionMode extends CipherOperationMode, TEncryptionMode { - override string toString() { result = "Encryption" } + class EncryptionMode extends CipherOperationSubtype, TEncryptionMode { + override string toString() { result = "Encrypt" } } - class DecryptionMode extends CipherOperationMode, TDecryptionMode { - override string toString() { result = "Decryption" } + class DecryptionMode extends CipherOperationSubtype, TDecryptionMode { + override string toString() { result = "Decrypt" } } - class UnknownCipherOperationMode extends CipherOperationMode, TUnknownCipherOperationMode { + class WrapMode extends CipherOperationSubtype, TWrapMode { + override string toString() { result = "Wrap" } + } + + class UnwrapMode extends CipherOperationSubtype, TUnwrapMode { + override string toString() { result = "Unwrap" } + } + + class UnknownCipherOperationMode extends CipherOperationSubtype, TUnknownCipherOperationMode { override string toString() { result = "Unknown" } } @@ -711,32 +729,51 @@ module CryptographyBase Input> { * This operation takes an input message (plaintext) of arbitrary content and length * and produces a ciphertext as the output using a specified encryption algorithm (with a mode and padding). */ - // NOTE FOR NICK: making this concrete here as I don't think users need to worry about making/extending these operations, just instances - class CipherOperation extends Operation, TCipherOperation { + class CipherOperationImpl extends Operation, TCipherOperation { CipherOperationInstance instance; - CipherOperation() { this = TCipherOperation(instance) } + CipherOperationImpl() { this = TCipherOperation(instance) } + + override string getInternalType() { result = "CipherOperation" } override Location getLocation() { result = instance.getLocation() } - final TCipherOperationMode getCipherOperationMode() { - result = instance.getCipherOperationMode() + CipherOperationSubtype getCipherOperationMode() { + result = instance.getCipherOperationSubtype() } - final override EncryptionAlgorithm getAlgorithm() { - result.getInstance() = instance.getAlgorithm() + final override CipherAlgorithm getAlgorithm() { result.getInstance() = instance.getAlgorithm() } + + override NodeBase getChild(string key) { + result = super.getChild(key) + or + // [KNOWN_OR_UNKNOWN] + key = "nonce" and + if exists(this.getNonce()) then result = this.getNonce() else result = this } - override string getInternalType() { result = "CipherOperation" } - // /** - // * Gets the initialization vector associated with this encryption operation. - // * - // * This predicate does not need to hold for all encryption operations, - // * as the initialization vector is not always required. - // */ - // abstract InitializationVector getInitializationVector(); + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + // [ALWAYS_KNOWN] - Unknown is handled in getCipherOperationMode() + key = "operation" and + value = this.getCipherOperationMode().toString() and + location = this.getLocation() + } + + /** + * Gets the initialization vector associated with this encryption operation. + * + * This predicate does not need to hold for all encryption operations, + * as the initialization vector is not always required. + */ + Nonce getNonce() { result = TNonce(instance.getNonce()) } + + DataFlowNode getInputData() { result = instance.getInputData() } } + final class CipherOperation = CipherOperationImpl; + /** * Block cipher modes of operation algorithms */ @@ -858,10 +895,10 @@ module CryptographyBase Input> { RC4() or RC5() or RSA() or - OtherSymmetricCipherType() + OtherCipherType() - abstract class EncryptionAlgorithm extends Algorithm, TEncryptionAlgorithm { - final LocatableElement getInstance() { this = TEncryptionAlgorithm(result) } + abstract class CipherAlgorithm extends Algorithm, TCipherAlgorithm { + final LocatableElement getInstance() { this = TCipherAlgorithm(result) } final TCipherStructureType getCipherStructure() { this.cipherFamilyToNameAndStructure(this.getCipherFamily(), _, result) @@ -871,7 +908,7 @@ module CryptographyBase Input> { this.cipherFamilyToNameAndStructure(this.getCipherFamily(), result, _) } - final override string getAlgorithmType() { result = "EncryptionAlgorithm" } + override string getAlgorithmType() { result = "CipherAlgorithm" } /** * Gets the key size of this cipher, e.g., "128" or "256". @@ -917,7 +954,7 @@ module CryptographyBase Input> { or type instanceof RSA and name = "RSA" and s = Asymmetric() or - type instanceof OtherSymmetricCipherType and + type instanceof OtherCipherType and name = this.getRawAlgorithmName() and s = UnknownCipherStructureType() } @@ -929,19 +966,21 @@ module CryptographyBase Input> { override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) or - ( - // [KNOWN_OR_UNKNOWN] - edgeName = "mode" and - if exists(this.getModeOfOperation()) - then result = this.getModeOfOperation() - else result = this - ) + // [KNOWN_OR_UNKNOWN] + edgeName = "mode" and + if exists(this.getModeOfOperation()) + then result = this.getModeOfOperation() + else result = this + or + // [KNOWN_OR_UNKNOWN] + edgeName = "padding" and + if exists(this.getPadding()) then result = this.getPadding() else result = this } override predicate properties(string key, string value, Location location) { super.properties(key, value, location) or - // [ALWAYS_KNOWN]: unknown case is handled in `getCipherStructureTypeString` + // [ALWAYS_KNOWN] - unknown case is handled in `getCipherStructureTypeString` key = "structure" and getCipherStructureTypeString(this.getCipherStructure()) = value and location instanceof UnknownLocation From eb91ecf1fb8864856a7dea33e513edb0a2bd7f68 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Tue, 25 Feb 2025 02:53:13 +0100 Subject: [PATCH 029/336] Add generic artifact data-flow The relation between RNG and other artifacts has been added Nonce has been completed to report its source --- java/ql/lib/experimental/Quantum/Language.qll | 20 ++++++ .../codeql/cryptography/Model.qll | 71 +++++++++++++++---- 2 files changed, 79 insertions(+), 12 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index e88bce6d9959..f8b7bf7a914c 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -2,6 +2,7 @@ private import codeql.cryptography.Model private import java as Language private import semmle.code.java.security.InsecureRandomnessQuery private import semmle.code.java.security.RandomQuery +private import semmle.code.java.dataflow.DataFlow private class UnknownLocation extends Language::Location { UnknownLocation() { this.getFile().getAbsolutePath() = "" } @@ -36,6 +37,10 @@ module Crypto = CryptographyBase; */ abstract class RandomnessInstance extends Crypto::RandomNumberGenerationInstance { override DataFlow::Node asOutputData() { result.asExpr() = this } + + override predicate flowsTo(Crypto::ArtifactLocatableElement other) { + RNGToArtifactFlow::flow(this.asOutputData(), other.getInput()) + } } class SecureRandomnessInstance extends RandomnessInstance { @@ -50,5 +55,20 @@ class InsecureRandomnessInstance extends RandomnessInstance { InsecureRandomnessInstance() { exists(InsecureRandomnessSource node | this = node.asExpr()) } } +/** + * Random number generation artifact to other artifact flow configuration + */ +module RNGToArtifactFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source = any(Crypto::RandomNumberGenerationInstance rng).asOutputData() + } + + predicate isSink(DataFlow::Node sink) { + sink = any(Crypto::ArtifactLocatableElement other).getInput() + } +} + +module RNGToArtifactFlow = DataFlow::Global; + // Import library-specific modeling import JCA diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index e5b91e198eaf..4e8dae8aa02a 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -47,8 +47,9 @@ module CryptographyBase Input> { predicate nodes_graph_impl(NodeBase node, string key, string value) { not ( - // exclude Artifact nodes with no edges to or from them - node instanceof Artifact and + // exclude certain Artifact nodes with no edges to or from them + node instanceof RandomNumberGeneration and + // TODO: performance? not (edges_graph_impl(node, _, _, _) or edges_graph_impl(_, node, _, _)) ) and ( @@ -110,17 +111,47 @@ module CryptographyBase Input> { abstract class PaddingAlgorithmInstance extends LocatableElement { } // Artifacts - abstract private class ArtifactLocatableElement extends LocatableElement { + abstract class ArtifactLocatableElement extends LocatableElement { + /** + * Gets the output node for this artifact, which should usually be the same as `this`. + */ abstract DataFlowNode asOutputData(); + /** + * Gets the input node for this artifact. + * + * If `getInput` is implemented as `none()`, the artifact will not have inbound flow analysis. + */ abstract DataFlowNode getInput(); + + /** + * Holds if this artifact flows to `other`. + * + * This predicate should be defined generically per-language with library-specific extension support. + * The expected implementation is to perform flow analysis from this artifact's output to another artifact's input. + * The `other` argument should be one or more `ArtifactLocatableElement` that are sinks of the flow. + * + * If `flowsTo` is implemented as `none()`, the artifact will not have outbound flow analysis. + */ + abstract predicate flowsTo(ArtifactLocatableElement other); } + newtype TGenericDataSourceType = + FilesystemDataSource() or + ExternalLibraryDataSource() or + MemoryAllocationDataSource() or + ConstantDataSource() + + abstract class GenericDataSourceInstance extends ArtifactLocatableElement { } + abstract class DigestArtifactInstance extends ArtifactLocatableElement { } abstract class KeyArtifactInstance extends ArtifactLocatableElement { } - abstract class NonceArtifactInstance extends ArtifactLocatableElement { } + abstract class NonceArtifactInstance extends ArtifactLocatableElement { + // no implicit outbound data-flow (only modelled in cipher operations) + override predicate flowsTo(ArtifactLocatableElement other) { none() } + } abstract class RandomNumberGenerationInstance extends ArtifactLocatableElement { final override DataFlowNode getInput() { none() } @@ -206,10 +237,30 @@ module CryptographyBase Input> { class Asset = NodeBase; + /** + * An artifact is an instance of data that is used in a cryptographic operation or produced by one. + */ abstract class Artifact extends NodeBase { - abstract DataFlowNode asOutputData(); + /** + * Gets the artifact locatable element associated with this artifact. + * + * *Implementation note*: to avoid cross-products, the result *must* only bind to the + * `ArtifactLocatableElement` that is already associated with the node instance. + */ + abstract ArtifactLocatableElement asArtifactLocatableElement(); - abstract DataFlowNode getInputData(); + final Artifact getSourceArtifact() { + not result = this and + result.asArtifactLocatableElement().flowsTo(this.asArtifactLocatableElement()) + } + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + // [ONLY_KNOWN] - TODO: unknown case handled by reporting a generic source type or unknown as a property + edgeName = "source" and + result = this.getSourceArtifact() + } } /** @@ -224,9 +275,7 @@ module CryptographyBase Input> { override Location getLocation() { result = instance.getLocation() } - override DataFlowNode asOutputData() { result = instance.asOutputData() } - - override DataFlowNode getInputData() { result = instance.getInput() } + override ArtifactLocatableElement asArtifactLocatableElement() { result = instance } } final class Nonce = NonceImpl; @@ -243,9 +292,7 @@ module CryptographyBase Input> { override Location getLocation() { result = instance.getLocation() } - override DataFlowNode asOutputData() { result = instance.asOutputData() } - - override DataFlowNode getInputData() { result = instance.getInput() } + override ArtifactLocatableElement asArtifactLocatableElement() { result = instance } } final class RandomNumberGeneration = RandomNumberGenerationImpl; From f55f27b0d92297d314a2cccfb913032379edfbac Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Tue, 25 Feb 2025 18:22:38 +0100 Subject: [PATCH 030/336] Expand handling of generic artifact sources --- java/ql/lib/experimental/Quantum/JCA.qll | 8 +- java/ql/lib/experimental/Quantum/Language.qll | 35 +++++ .../ql/src/experimental/Quantum/TestCipher.ql | 2 +- .../codeql/cryptography/Model.qll | 138 ++++++++++++++---- 4 files changed, 147 insertions(+), 36 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 9892b445312a..df96a4460e2e 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -125,16 +125,10 @@ module JCAModel { } } - class CipherUpdateCall extends MethodCall { - CipherUpdateCall() { this.getMethod().hasQualifiedName("javax.crypto", "Cipher", "update") } - - DataFlow::Node getInputData() { result.asExpr() = this.getArgument(0) } - } - private newtype TCipherModeFlowState = TUninitializedCipherModeFlowState() or TInitializedCipherModeFlowState(CipherInitCall call) or - TUsedCipherModeFlowState(CipherInitCall init, CipherUpdateCall update) + TUsedCipherModeFlowState(CipherInitCall init) abstract private class CipherModeFlowState extends TCipherModeFlowState { string toString() { diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index f8b7bf7a914c..5abac9e9462f 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -3,6 +3,7 @@ private import java as Language private import semmle.code.java.security.InsecureRandomnessQuery private import semmle.code.java.security.RandomQuery private import semmle.code.java.dataflow.DataFlow +private import semmle.code.java.dataflow.FlowSources private class UnknownLocation extends Language::Location { UnknownLocation() { this.getFile().getAbsolutePath() = "" } @@ -31,6 +32,25 @@ module CryptoInput implements InputSig { */ module Crypto = CryptographyBase; +/** + * Definitions of various generic data sources + */ +final class DefaultFlowSource = SourceNode; + +final class DefaultRemoteFlowSource = RemoteFlowSource; + +class GenericLocalDataSource extends Crypto::GenericRemoteDataSource { + GenericLocalDataSource() { + any(DefaultFlowSource src | not src instanceof DefaultRemoteFlowSource).asExpr() = this + } + + override DataFlow::Node asOutputData() { result.asExpr() = this } + + override predicate flowsTo(Crypto::ArtifactLocatableElement other) { + DataSourceToArtifactFlow::flow(this.asOutputData(), other.getInput()) + } +} + /** * Random number generation, where each instance is modelled as the expression * tied to an output node (i.e., the result of the source of randomness) @@ -70,5 +90,20 @@ module RNGToArtifactFlowConfig implements DataFlow::ConfigSig { module RNGToArtifactFlow = DataFlow::Global; +/** + * Generic data source to artifact flow configuration + */ +module DataSourceToArtifactFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source = any(Crypto::GenericDataSourceInstance i).asOutputData() + } + + predicate isSink(DataFlow::Node sink) { + sink = any(Crypto::ArtifactLocatableElement other).getInput() + } +} + +module DataSourceToArtifactFlow = DataFlow::Global; + // Import library-specific modeling import JCA diff --git a/java/ql/src/experimental/Quantum/TestCipher.ql b/java/ql/src/experimental/Quantum/TestCipher.ql index 6be308c25606..14041cd3b224 100644 --- a/java/ql/src/experimental/Quantum/TestCipher.ql +++ b/java/ql/src/experimental/Quantum/TestCipher.ql @@ -13,4 +13,4 @@ where p = a.getPadding() and nonce = op.getNonce() select op, op.getCipherOperationMode(), a, a.getRawAlgorithmName(), m, m.getRawAlgorithmName(), p, - p.getRawAlgorithmName(), nonce, nonce.getInputData() + p.getRawAlgorithmName(), nonce diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 4e8dae8aa02a..713c503ea655 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -136,13 +136,30 @@ module CryptographyBase Input> { abstract predicate flowsTo(ArtifactLocatableElement other); } - newtype TGenericDataSourceType = - FilesystemDataSource() or - ExternalLibraryDataSource() or - MemoryAllocationDataSource() or - ConstantDataSource() + // TODO: WARNING: + // If this overlaps with any other LocatableElement, there will be a cross-product + // This is never to be used for unknowns + abstract class GenericDataSourceInstance extends ArtifactLocatableElement { + final override DataFlowNode getInput() { none() } + + abstract string getLabel(); + } + + abstract class GenericConstantOrAllocationSource extends GenericDataSourceInstance { + final override string getLabel() { result = "ConstantData" } // TODO: toString of source? + } + + abstract class GenericExternalCallSource extends GenericDataSourceInstance { + final override string getLabel() { result = "ExternalCall" } // TODO: call target name or toString of source? + } - abstract class GenericDataSourceInstance extends ArtifactLocatableElement { } + abstract class GenericRemoteDataSource extends GenericDataSourceInstance { + final override string getLabel() { result = "RemoteData" } // TODO: toString of source? + } + + abstract class GenericLocalDataSource extends GenericDataSourceInstance { + final override string getLabel() { result = "LocalData" } // TODO: toString of source? + } abstract class DigestArtifactInstance extends ArtifactLocatableElement { } @@ -224,7 +241,7 @@ module CryptographyBase Input> { * This predicate is overriden by derived classes to construct the graph of cryptographic operations. */ predicate properties(string key, string value, Location location) { - key = "origin" and + key = "Origin" and location = this.getOrigin(value).getLocation() and not location = this.getLocation() } @@ -249,18 +266,65 @@ module CryptographyBase Input> { */ abstract ArtifactLocatableElement asArtifactLocatableElement(); + /** + * Gets the `Artifact` node that is the data source for this artifact. + */ final Artifact getSourceArtifact() { - not result = this and - result.asArtifactLocatableElement().flowsTo(this.asArtifactLocatableElement()) + result.asArtifactLocatableElement() = this.getSourceArtifactElement() + } + + /** + * Gets the `ArtifactLocatableElement` that is the data source for this artifact. + * + * This predicate is equivalent to `getSourceArtifact().asArtifactLocatableElement()`. + */ + final ArtifactLocatableElement getSourceArtifactElement() { + not result = this.asArtifactLocatableElement() and + result.flowsTo(this.asArtifactLocatableElement()) } override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) or - // [ONLY_KNOWN] - TODO: unknown case handled by reporting a generic source type or unknown as a property - edgeName = "source" and + // [ONLY_KNOWN] - TODO: known-unknown case handled by reporting a generic source type or unknown as a property + edgeName = "Source" and result = this.getSourceArtifact() } + + // TODO: document the below + final private predicate src_generic_data_source_to_label_and_loc(string label, Location location) { + exists(GenericDataSourceInstance instance | + this.getSourceArtifactElement() = instance and + instance.getLabel() = label and + instance.getLocation() = location + ) + } + + final private predicate src_artifact_to_label_and_loc(string label, Location location) { + exists(Artifact a | + this.getSourceArtifact() = a and + a.getInternalType() = label and + a.getLocation() = location + ) + } + + final private predicate source_type_property(string key, string value, Location location) { + key = "SourceType" and + if this.src_artifact_to_label_and_loc(_, _) + then this.src_artifact_to_label_and_loc(value, location) + else + if + exists(this.asArtifactLocatableElement().getInput()) and + not this.src_generic_data_source_to_label_and_loc(_, _) + then value instanceof UnknownPropertyValue and location instanceof UnknownLocation + else this.src_generic_data_source_to_label_and_loc(value, location) + } + + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + this.source_type_property(key, value, location) + } } /** @@ -309,7 +373,25 @@ module CryptographyBase Input> { override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) or - edgeName = "uses" and + /* + * TODO: Consider a case with getProperty, where an unknown value is loaded from the filesystem, + * but a default is specified as such: + * String value = getProperty("property", "default_algorithm") + * In this case, getAlgorithm *could* be resolved to default_algorithm, but in that case, the known + * unknown case, i.e., what is loaded from `property`, would not be reported at all as a known unknown. + * + * Implementation brainstorming: + * We have two cases, and we only considered one before: the case where we can't point to the known unknown. + * The new case is pointing to a known unknown, e.g., "property" loaded via getProperty. + * A potential solution is to create a known unknown node for each node type (particularly algorithms) + * and model those elements in the database to associate with that known unknown type?? + * + * - Idea: use the generic data source concept as the definition of potential known unknowns. + * flow should be tracked from them to anything that could be a "sink" that specifies the relation. + * in this case, the sink would be an instantiaition of an algorithm where the value is not resolvable. + */ + + edgeName = "Uses" and if exists(this.getAlgorithm()) then result = this.getAlgorithm() else result = this } } @@ -336,10 +418,10 @@ module CryptographyBase Input> { super.properties(key, value, location) or // [ONLY_KNOWN] - key = "name" and value = this.getAlgorithmName() and location = this.getLocation() + key = "Name" and value = this.getAlgorithmName() and location = this.getLocation() or // [ONLY_KNOWN] - key = "raw_name" and value = this.getRawAlgorithmName() and location = this.getLocation() + key = "RawName" and value = this.getRawAlgorithmName() and location = this.getLocation() } } @@ -445,7 +527,7 @@ module CryptographyBase Input> { super.properties(key, value, location) or // [KNOWN_OR_UNKNOWN] - key = "digest_size" and + key = "DigestSize" and if exists(this.getDigestSize(location)) then value = this.getDigestSize(location) else ( @@ -492,7 +574,7 @@ module CryptographyBase Input> { or ( // [KNOWN_OR_UNKNOWN] - edgeName = "uses" and + edgeName = "Uses" and if exists(this.getHashAlgorithm()) then result = this.getHashAlgorithm() else result = this ) } @@ -526,7 +608,7 @@ module CryptographyBase Input> { or ( // [KNOWN_OR_UNKNOWN] - key = "iterations" and + key = "Iterations" and if exists(this.getIterationCount(location)) then value = this.getIterationCount(location) else ( @@ -536,7 +618,7 @@ module CryptographyBase Input> { or ( // [KNOWN_OR_UNKNOWN] - key = "key_len" and + key = "KeyLength" and if exists(this.getKeyLength(location)) then value = this.getKeyLength(location) else ( @@ -580,7 +662,7 @@ module CryptographyBase Input> { or ( // [KNOWN_OR_UNKNOWN] - key = "iterations" and + key = "Iterations" and if exists(this.getIterationCount(location)) then value = this.getIterationCount(location) else ( @@ -590,7 +672,7 @@ module CryptographyBase Input> { or ( // [KNOWN_OR_UNKNOWN] - key = "id_byte" and + key = "IdByte" and if exists(this.getIDByte(location)) then value = this.getIDByte(location) else ( @@ -661,7 +743,7 @@ module CryptographyBase Input> { or ( // [KNOWN_OR_UNKNOWN] - key = "key_len" and + key = "KeyLength" and if exists(this.getDerivedKeyLength(location)) then value = this.getDerivedKeyLength(location) else ( @@ -714,7 +796,7 @@ module CryptographyBase Input> { super.properties(key, value, location) or // [KNOWN_OR_UNKNOWN] - key = "key_size" and + key = "KeySize" and if exists(this.getKeySize(location)) then value = this.getKeySize(location) else ( @@ -795,7 +877,7 @@ module CryptographyBase Input> { result = super.getChild(key) or // [KNOWN_OR_UNKNOWN] - key = "nonce" and + key = "Nonce" and if exists(this.getNonce()) then result = this.getNonce() else result = this } @@ -803,7 +885,7 @@ module CryptographyBase Input> { super.properties(key, value, location) or // [ALWAYS_KNOWN] - Unknown is handled in getCipherOperationMode() - key = "operation" and + key = "Operation" and value = this.getCipherOperationMode().toString() and location = this.getLocation() } @@ -1014,13 +1096,13 @@ module CryptographyBase Input> { result = super.getChild(edgeName) or // [KNOWN_OR_UNKNOWN] - edgeName = "mode" and + edgeName = "Mode" and if exists(this.getModeOfOperation()) then result = this.getModeOfOperation() else result = this or // [KNOWN_OR_UNKNOWN] - edgeName = "padding" and + edgeName = "Padding" and if exists(this.getPadding()) then result = this.getPadding() else result = this } @@ -1028,13 +1110,13 @@ module CryptographyBase Input> { super.properties(key, value, location) or // [ALWAYS_KNOWN] - unknown case is handled in `getCipherStructureTypeString` - key = "structure" and + key = "Structure" and getCipherStructureTypeString(this.getCipherStructure()) = value and location instanceof UnknownLocation or ( // [KNOWN_OR_UNKNOWN] - key = "key_size" and + key = "KeySize" and if exists(this.getKeySize(location)) then value = this.getKeySize(location) else ( From 04f46833991dffedfb91d425cba61dc4146b6fac Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 27 Feb 2025 05:42:02 +0100 Subject: [PATCH 031/336] Rewrite handling of known unknowns and data-flow --- java/ql/lib/experimental/Quantum/JCA.qll | 344 ++-- java/ql/lib/experimental/Quantum/Language.qll | 64 +- .../src/experimental/Quantum/ReusedNonce.ql | 14 +- .../ql/src/experimental/Quantum/TestCipher.ql | 14 +- .../codeql/cryptography/Model.qll | 1534 +++++++++-------- 5 files changed, 1058 insertions(+), 912 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index df96a4460e2e..f1e1ce9ccdc3 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -66,7 +66,7 @@ module JCAModel { ) } - DataFlow::Node getInputData() { result.asExpr() = this.getArgument(0) } + DataFlow::Node getMessageArg() { result.asExpr() = this.getArgument(0) } } /** @@ -82,27 +82,137 @@ module JCAModel { module AlgorithmStringToFetchFlow = DataFlow::Global; + /** + * Note: padding and a mode of operation will only exist when the padding / mode (*and its type*) are determinable. + * This is because the mode will always be specified alongside the algorithm and never independently. + * Therefore, we can always assume that a determinable algorithm will have a determinable mode. + * + * In the case that only an algorithm is specified, e.g., "AES", the provider provides a default mode. + * + * TODO: Model the case of relying on a provider default, but alert on it as a bad practice. + */ + class CipherStringLiteralAlgorithmInstance extends Crypto::CipherAlgorithmInstance, + Crypto::ModeOfOperationAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof CipherStringLiteral + { + CipherGetInstanceAlgorithmArg consumer; + + CipherStringLiteralAlgorithmInstance() { + AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), DataFlow::exprNode(consumer)) + } + + CipherGetInstanceAlgorithmArg getConsumer() { result = consumer } + + override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { + result = this and exists(this.getRawModeAlgorithmName()) // TODO: provider defaults + } + + override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { + result = this and exists(this.getRawPaddingAlgorithmName()) // TODO: provider defaults + } + + override string getRawAlgorithmName() { result = super.getValue() } + + override Crypto::TCipherType getCipherFamily() { + if this.cipherNameMappingKnown(_, super.getAlgorithmName()) + then this.cipherNameMappingKnown(result, super.getAlgorithmName()) + else result instanceof Crypto::OtherCipherType + } + + bindingset[name] + private predicate cipherNameMappingKnown(Crypto::TCipherType type, string name) { + name = "AES" and + type instanceof Crypto::AES + or + name = "DES" and + type instanceof Crypto::DES + or + name = "TripleDES" and + type instanceof Crypto::TripleDES + or + name = "IDEA" and + type instanceof Crypto::IDEA + or + name = "CAST5" and + type instanceof Crypto::CAST5 + or + name = "ChaCha20" and + type instanceof Crypto::ChaCha20 + or + name = "RC4" and + type instanceof Crypto::RC4 + or + name = "RC5" and + type instanceof Crypto::RC5 + or + name = "RSA" and + type instanceof Crypto::RSA + } + + private predicate modeToNameMappingKnown(Crypto::TBlockCipherModeOperationType type, string name) { + type instanceof Crypto::ECB and name = "ECB" + or + type instanceof Crypto::CBC and name = "CBC" + or + type instanceof Crypto::GCM and name = "GCM" + or + type instanceof Crypto::CTR and name = "CTR" + or + type instanceof Crypto::XTS and name = "XTS" + or + type instanceof Crypto::CCM and name = "CCM" + or + type instanceof Crypto::SIV and name = "SIV" + or + type instanceof Crypto::OCB and name = "OCB" + } + + override Crypto::TBlockCipherModeOperationType getModeType() { + if this.modeToNameMappingKnown(_, super.getMode()) + then this.modeToNameMappingKnown(result, super.getMode()) + else result instanceof Crypto::OtherMode + } + + override string getRawModeAlgorithmName() { result = super.getMode() } + + override string getRawPaddingAlgorithmName() { result = super.getPadding() } + + bindingset[name] + private predicate paddingToNameMappingKnown(Crypto::TPaddingType type, string name) { + type instanceof Crypto::NoPadding and name = "NOPADDING" + or + type instanceof Crypto::PKCS7 and name = ["PKCS5Padding", "PKCS7Padding"] // TODO: misnomer in the JCA? + or + type instanceof Crypto::OAEP and name.matches("OAEP%") // TODO: handle OAEPWith% + } + + override Crypto::TPaddingType getPaddingType() { + if this.paddingToNameMappingKnown(_, super.getPadding()) + then this.paddingToNameMappingKnown(result, super.getPadding()) + else result instanceof Crypto::OtherPadding + } + } + /** * The cipher algorithm argument to a `CipherGetInstanceCall`. * * For example, in `Cipher.getInstance(algorithm)`, this class represents `algorithm`. */ - class CipherGetInstanceAlgorithmArg extends Crypto::CipherAlgorithmInstance, - Crypto::BlockCipherModeOfOperationAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof Expr - { + class CipherGetInstanceAlgorithmArg extends Crypto::AlgorithmConsumer instanceof Expr { CipherGetInstanceCall call; CipherGetInstanceAlgorithmArg() { this = call.getAlgorithmArg() } - /** - * Returns the `StringLiteral` from which this argument is derived, if known. - */ - CipherStringLiteral getOrigin() { + override DataFlow::Node getInputNode() { result.asExpr() = this } + + CipherStringLiteral getOrigin(string value) { AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(result), - DataFlow::exprNode(this.(Expr).getAChildExpr*())) + DataFlow::exprNode(this.(Expr).getAChildExpr*())) and + value = result.getValue() } - CipherGetInstanceCall getCall() { result = call } + override Crypto::AlgorithmElement getAKnownAlgorithmSource() { + result.(CipherStringLiteralAlgorithmInstance).getConsumer() = this + } } /** @@ -144,7 +254,7 @@ module JCAModel { TUninitializedCipherModeFlowState { override Crypto::CipherOperationSubtype getCipherOperationMode() { - result instanceof Crypto::UnknownCipherOperationMode + result instanceof Crypto::UnknownCipherOperationSubtype } } @@ -200,6 +310,7 @@ module JCAModel { predicate isAdditionalFlowStep( DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 ) { + state1 = state1 and node1 = state2.(InitializedCipherModeFlowState).getFstNode() and node2 = state2.(InitializedCipherModeFlowState).getSndNode() } @@ -218,195 +329,40 @@ module JCAModel { class CipherOperationInstance extends Crypto::CipherOperationInstance instanceof Call { Crypto::CipherOperationSubtype mode; - Crypto::CipherAlgorithmInstance algorithm; CipherGetInstanceToCipherOperationFlow::PathNode sink; JCACipherOperationCall doFinalize; + CipherGetInstanceAlgorithmArg consumer; CipherOperationInstance() { - exists( - CipherGetInstanceToCipherOperationFlow::PathNode src, CipherGetInstanceCall getCipher, - CipherGetInstanceAlgorithmArg arg - | + exists(CipherGetInstanceToCipherOperationFlow::PathNode src, CipherGetInstanceCall getCipher | CipherGetInstanceToCipherOperationFlow::flowPath(src, sink) and src.getNode().asExpr() = getCipher and sink.getNode().asExpr() = doFinalize.getQualifier() and sink.getState().(CipherModeFlowState).getCipherOperationMode() = mode and this = doFinalize and - arg.getCall() = getCipher and - algorithm = arg + consumer = getCipher.getAlgorithmArg() ) } - override Crypto::CipherAlgorithmInstance getAlgorithm() { result = algorithm } - override Crypto::CipherOperationSubtype getCipherOperationSubtype() { result = mode } - override Crypto::NonceArtifactInstance getNonce() { - NonceArtifactToCipherInitCallFlow::flow(result.asOutputData(), - DataFlow::exprNode(sink.getState() - .(InitializedCipherModeFlowState) - .getInitCall() - .getNonceArg())) + override Crypto::ArtifactConsumer getNonceConsumer() { + result = sink.getState().(InitializedCipherModeFlowState).getInitCall().getNonceArg() } - override DataFlow::Node getInputData() { result = doFinalize.getInputData() } - } - - /** - * A block cipher mode of operation, where the mode is specified in the ALG or ALG/MODE/PADDING format. - * - * This class will only exist when the mode (*and its type*) is determinable. - * This is because the mode will always be specified alongside the algorithm and never independently. - * Therefore, we can always assume that a determinable algorithm will have a determinable mode. - * - * In the case that only an algorithm is specified, e.g., "AES", the provider provides a default mode. - * - * TODO: Model the case of relying on a provider default, but alert on it as a bad practice. - */ - class ModeOfOperation extends Crypto::ModeOfOperationAlgorithm { - CipherGetInstanceAlgorithmArg instance; - - ModeOfOperation() { - this = Crypto::TBlockCipherModeOfOperationAlgorithm(instance) and - // TODO: this currently only holds for explicitly defined modes in a string literal. - // Cases with defaults, e.g., "AES", are not yet modelled. - // For these cases, in a CBOM, the AES node would have an unknown edge to its mode child. - exists(instance.getOrigin().getMode()) - } - - override Location getLocation() { result = instance.getLocation() } - - // In this case, the raw name is still only the /MODE/ part. - // TODO: handle defaults - override string getRawAlgorithmName() { result = instance.getOrigin().getMode() } - - private predicate modeToNameMappingKnown(Crypto::TBlockCipherModeOperationType type, string name) { - type instanceof Crypto::ECB and name = "ECB" - or - type instanceof Crypto::CBC and name = "CBC" - or - type instanceof Crypto::GCM and name = "GCM" - or - type instanceof Crypto::CTR and name = "CTR" - or - type instanceof Crypto::XTS and name = "XTS" - or - type instanceof Crypto::CCM and name = "CCM" - or - type instanceof Crypto::SIV and name = "SIV" - or - type instanceof Crypto::OCB and name = "OCB" - } - - override Crypto::TBlockCipherModeOperationType getModeType() { - if this.modeToNameMappingKnown(_, instance.getOrigin().getMode()) - then this.modeToNameMappingKnown(result, instance.getOrigin().getMode()) - else result instanceof Crypto::OtherMode - } - - CipherStringLiteral getInstance() { result = instance } - } - - class PaddingAlgorithm extends Crypto::PaddingAlgorithm { - CipherGetInstanceAlgorithmArg instance; - - PaddingAlgorithm() { - this = Crypto::TPaddingAlgorithm(instance) and - exists(instance.getOrigin().getPadding()) - } - - override Location getLocation() { result = instance.getLocation() } - - override string getRawAlgorithmName() { result = instance.getOrigin().getPadding() } - - bindingset[name] - private predicate paddingToNameMappingKnown(Crypto::TPaddingType type, string name) { - type instanceof Crypto::NoPadding and name = "NOPADDING" - or - type instanceof Crypto::PKCS7 and name = ["PKCS5Padding", "PKCS7Padding"] // TODO: misnomer in the JCA? - or - type instanceof Crypto::OAEP and name.matches("OAEP%") // TODO: handle OAEPWith% + override Crypto::ArtifactConsumer getMessageConsumer() { + result = doFinalize.getMessageArg().asExpr() } - override Crypto::TPaddingType getPaddingType() { - if this.paddingToNameMappingKnown(_, instance.getOrigin().getPadding()) - then this.paddingToNameMappingKnown(result, instance.getOrigin().getPadding()) - else result instanceof Crypto::OtherPadding - } - - CipherStringLiteral getInstance() { result = instance } - } - - class EncryptionAlgorithm extends Crypto::CipherAlgorithm { - CipherStringLiteral origin; - CipherGetInstanceAlgorithmArg instance; - - EncryptionAlgorithm() { - this = Crypto::TCipherAlgorithm(instance) and - instance.getOrigin() = origin - } - - override Location getLocation() { result = instance.getLocation() } - - override Crypto::ModeOfOperationAlgorithm getModeOfOperation() { - result.(ModeOfOperation).getInstance() = origin - } - - override Crypto::PaddingAlgorithm getPadding() { - result.(PaddingAlgorithm).getInstance() = origin - } - - override Crypto::LocatableElement getOrigin(string name) { - result = origin and name = origin.toString() - } - - override string getRawAlgorithmName() { result = origin.getValue() } - - override Crypto::TCipherType getCipherFamily() { - if this.cipherNameMappingKnown(_, origin.getAlgorithmName()) - then this.cipherNameMappingKnown(result, origin.getAlgorithmName()) - else result instanceof Crypto::OtherCipherType - } - - override string getKeySize(Location location) { none() } - - bindingset[name] - private predicate cipherNameMappingKnown(Crypto::TCipherType type, string name) { - name = "AES" and - type instanceof Crypto::AES - or - name = "DES" and - type instanceof Crypto::DES - or - name = "TripleDES" and - type instanceof Crypto::TripleDES - or - name = "IDEA" and - type instanceof Crypto::IDEA - or - name = "CAST5" and - type instanceof Crypto::CAST5 - or - name = "ChaCha20" and - type instanceof Crypto::ChaCha20 - or - name = "RC4" and - type instanceof Crypto::RC4 - or - name = "RC5" and - type instanceof Crypto::RC5 - or - name = "RSA" and - type instanceof Crypto::RSA - } + override Crypto::AlgorithmConsumer getAlgorithmConsumer() { result = consumer } } /** * Initialization vectors and other nonce artifacts */ - abstract class NonceParameterInstantiation extends Crypto::NonceArtifactInstance instanceof ClassInstanceExpr + abstract class NonceParameterInstantiation extends NonceArtifactInstance instanceof ClassInstanceExpr { - override DataFlow::Node asOutputData() { result.asExpr() = this } + override DataFlow::Node getOutputNode() { result.asExpr() = this } } class IvParameterSpecInstance extends NonceParameterInstantiation { @@ -416,7 +372,9 @@ module JCAModel { .hasQualifiedName("javax.crypto.spec", "IvParameterSpec") } - override DataFlow::Node getInput() { result.asExpr() = this.(ClassInstanceExpr).getArgument(0) } + override DataFlow::Node getInputNode() { + result.asExpr() = this.(ClassInstanceExpr).getArgument(0) + } } // TODO: this also specifies the tag length for GCM @@ -427,7 +385,9 @@ module JCAModel { .hasQualifiedName("javax.crypto.spec", "GCMParameterSpec") } - override DataFlow::Node getInput() { result.asExpr() = this.(ClassInstanceExpr).getArgument(1) } + override DataFlow::Node getInputNode() { + result.asExpr() = this.(ClassInstanceExpr).getArgument(1) + } } class IvParameterSpecGetIvCall extends MethodCall { @@ -439,8 +399,8 @@ module JCAModel { module NonceArtifactToCipherInitCallConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { exists(NonceParameterInstantiation n | - src = n.asOutputData() and - not exists(IvParameterSpecGetIvCall m | n.getInput().asExpr() = m) + src = n.getOutputNode() and + not exists(IvParameterSpecGetIvCall m | n.getInputNode().asExpr() = m) ) } @@ -455,7 +415,7 @@ module JCAModel { ) or exists(NonceParameterInstantiation n | - node1 = n.getInput() and + node1 = n.getInputNode() and node2.asExpr() = n ) } @@ -482,13 +442,13 @@ module JCAModel { private predicate cipher_mode_str_to_cipher_mode_known( string mode, Crypto::CipherOperationSubtype cipher_mode ) { - mode = "ENCRYPT_MODE" and cipher_mode instanceof Crypto::EncryptionMode + mode = "ENCRYPT_MODE" and cipher_mode instanceof Crypto::EncryptionSubtype or - mode = "WRAP_MODE" and cipher_mode instanceof Crypto::WrapMode + mode = "WRAP_MODE" and cipher_mode instanceof Crypto::WrapSubtype or - mode = "DECRYPT_MODE" and cipher_mode instanceof Crypto::DecryptionMode + mode = "DECRYPT_MODE" and cipher_mode instanceof Crypto::DecryptionSubtype or - mode = "UNWRAP_MODE" and cipher_mode instanceof Crypto::UnwrapMode + mode = "UNWRAP_MODE" and cipher_mode instanceof Crypto::UnwrapSubtype } class CipherInitCall extends MethodCall { @@ -514,7 +474,7 @@ module JCAModel { Crypto::CipherOperationSubtype getCipherOperationModeType() { if cipher_mode_str_to_cipher_mode_known(this.getModeOrigin().getField().getName(), _) then cipher_mode_str_to_cipher_mode_known(this.getModeOrigin().getField().getName(), result) - else result instanceof Crypto::UnknownCipherOperationMode + else result instanceof Crypto::UnknownCipherOperationSubtype } Expr getKeyArg() { @@ -526,4 +486,16 @@ module JCAModel { this.getMethod().getParameterType(2).hasName("AlgorithmParameterSpec") } } + + class CipherInitCallNonceArgConsumer extends Crypto::ArtifactConsumer instanceof Expr { + CipherInitCallNonceArgConsumer() { this = any(CipherInitCall call).getNonceArg() } + + override DataFlow::Node getInputNode() { result.asExpr() = this } + } + + class CipherInitCallKeyConsumer extends Crypto::ArtifactConsumer instanceof Expr { + CipherInitCallKeyConsumer() { this = any(CipherInitCall call).getKeyArg() } + + override DataFlow::Node getInputNode() { result.asExpr() = this } + } } diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 5abac9e9462f..228f21bd69bf 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -39,16 +39,30 @@ final class DefaultFlowSource = SourceNode; final class DefaultRemoteFlowSource = RemoteFlowSource; -class GenericLocalDataSource extends Crypto::GenericRemoteDataSource { +class GenericLocalDataSource extends Crypto::GenericLocalDataSource { GenericLocalDataSource() { any(DefaultFlowSource src | not src instanceof DefaultRemoteFlowSource).asExpr() = this } - override DataFlow::Node asOutputData() { result.asExpr() = this } + override DataFlow::Node getOutputNode() { result.asExpr() = this } - override predicate flowsTo(Crypto::ArtifactLocatableElement other) { - DataSourceToArtifactFlow::flow(this.asOutputData(), other.getInput()) + override predicate flowsTo(Crypto::FlowAwareElement other) { + GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) } + + override string getAdditionalDescription() { result = this.toString() } +} + +class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { + GenericRemoteDataSource() { any(DefaultRemoteFlowSource src).asExpr() = this } + + override DataFlow::Node getOutputNode() { result.asExpr() = this } + + override predicate flowsTo(Crypto::FlowAwareElement other) { + GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) + } + + override string getAdditionalDescription() { result = this.toString() } } /** @@ -56,10 +70,12 @@ class GenericLocalDataSource extends Crypto::GenericRemoteDataSource { * tied to an output node (i.e., the result of the source of randomness) */ abstract class RandomnessInstance extends Crypto::RandomNumberGenerationInstance { - override DataFlow::Node asOutputData() { result.asExpr() = this } + override DataFlow::Node getOutputNode() { result.asExpr() = this } + + override DataFlow::Node getInputNode() { none() } // TODO: add seed - override predicate flowsTo(Crypto::ArtifactLocatableElement other) { - RNGToArtifactFlow::flow(this.asOutputData(), other.getInput()) + override predicate flowsTo(Crypto::FlowAwareElement other) { + ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) } } @@ -76,34 +92,48 @@ class InsecureRandomnessInstance extends RandomnessInstance { } /** - * Random number generation artifact to other artifact flow configuration + * Artifact output to node input configuration */ -module RNGToArtifactFlowConfig implements DataFlow::ConfigSig { +module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { - source = any(Crypto::RandomNumberGenerationInstance rng).asOutputData() + source = any(Crypto::ArtifactElement artifact).getOutputNode() } predicate isSink(DataFlow::Node sink) { - sink = any(Crypto::ArtifactLocatableElement other).getInput() + sink = any(Crypto::FlowAwareElement other).getInputNode() + } + + predicate isBarrierIn(DataFlow::Node node) { + node = any(Crypto::FlowAwareElement element).getOutputNode() } } -module RNGToArtifactFlow = DataFlow::Global; +module ArtifactUniversalFlow = DataFlow::Global; + +abstract class NonceArtifactInstance extends Crypto::NonceArtifactInstance { + override predicate flowsTo(Crypto::FlowAwareElement other) { + ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) + } +} /** - * Generic data source to artifact flow configuration + * Generic data source to node input configuration */ -module DataSourceToArtifactFlowConfig implements DataFlow::ConfigSig { +module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { - source = any(Crypto::GenericDataSourceInstance i).asOutputData() + source = any(Crypto::GenericDataSourceInstance i).getOutputNode() } predicate isSink(DataFlow::Node sink) { - sink = any(Crypto::ArtifactLocatableElement other).getInput() + sink = any(Crypto::FlowAwareElement other).getInputNode() + } + + predicate isBarrierIn(DataFlow::Node node) { + node = any(Crypto::FlowAwareElement element).getOutputNode() } } -module DataSourceToArtifactFlow = DataFlow::Global; +module GenericDataSourceUniversalFlow = DataFlow::Global; // Import library-specific modeling import JCA diff --git a/java/ql/src/experimental/Quantum/ReusedNonce.ql b/java/ql/src/experimental/Quantum/ReusedNonce.ql index cb0d6ff9d610..7847781e0be5 100644 --- a/java/ql/src/experimental/Quantum/ReusedNonce.ql +++ b/java/ql/src/experimental/Quantum/ReusedNonce.ql @@ -6,18 +6,16 @@ import experimental.Quantum.Language import semmle.code.java.dataflow.DataFlow -Element getNonceOrigin(Crypto::NonceArtifactInstance nonce) { +Crypto::NodeBase getNonceOrigin(Crypto::NonceNode nonce) { // TODO: this check is currently ultra hacky just for demoing - result = nonce.getInput().asExpr().(VarAccess).getVariable() + result = nonce.getSourceNode() } -from - Crypto::CipherOperationInstance op, Crypto::NonceArtifactInstance nonce1, - Crypto::NonceArtifactInstance nonce2 +from Crypto::CipherOperationNode op, Crypto::NonceNode nonce1, Crypto::NonceNode nonce2 where - op.(Expr).getEnclosingCallable().getName() = "encrypt" and - nonce1 = op.getNonce() and - nonce2 = op.getNonce() and + op.asElement().(Expr).getEnclosingCallable().getName() = "encrypt" and + nonce1 = op.getANonce() and + nonce2 = op.getANonce() and not nonce1 = nonce2 and getNonceOrigin(nonce1) = getNonceOrigin(nonce2) select op, nonce1, nonce2 diff --git a/java/ql/src/experimental/Quantum/TestCipher.ql b/java/ql/src/experimental/Quantum/TestCipher.ql index 14041cd3b224..fa04770d8549 100644 --- a/java/ql/src/experimental/Quantum/TestCipher.ql +++ b/java/ql/src/experimental/Quantum/TestCipher.ql @@ -5,12 +5,12 @@ import experimental.Quantum.Language from - Crypto::CipherOperation op, Crypto::CipherAlgorithm a, Crypto::ModeOfOperationAlgorithm m, - Crypto::PaddingAlgorithm p, Crypto::Nonce nonce + Crypto::CipherOperationNode op, Crypto::CipherAlgorithmNode a, + Crypto::ModeOfOperationAlgorithmNode m, Crypto::PaddingAlgorithmNode p, Crypto::NonceNode nonce where - a = op.getAlgorithm() and + a = op.getAKnownCipherAlgorithm() and m = a.getModeOfOperation() and - p = a.getPadding() and - nonce = op.getNonce() -select op, op.getCipherOperationMode(), a, a.getRawAlgorithmName(), m, m.getRawAlgorithmName(), p, - p.getRawAlgorithmName(), nonce + p = a.getPaddingAlgorithm() and + nonce = op.getANonce() +select op, op.getCipherOperationSubtype(), a, a.getRawAlgorithmName(), m, m.getRawAlgorithmName(), + p, p.getRawAlgorithmName(), nonce diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 713c503ea655..5889e9eb5e28 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -48,7 +48,7 @@ module CryptographyBase Input> { predicate nodes_graph_impl(NodeBase node, string key, string value) { not ( // exclude certain Artifact nodes with no edges to or from them - node instanceof RandomNumberGeneration and + node instanceof RandomNumberGenerationNode and // TODO: performance? not (edges_graph_impl(node, _, _, _) or edges_graph_impl(_, node, _, _)) ) and @@ -58,7 +58,7 @@ module CryptographyBase Input> { or // CodeQL's DGML output does not include a location key = "Location" and - value = node.getLocation().toString() + value = "" // node.getLocation().toString() or // Known unknown edges should be reported as properties rather than edges node = node.getChild(key) and @@ -77,52 +77,20 @@ module CryptographyBase Input> { } /** - * All elements in the database that are mapped to nodes must extend the following classes + * An element that is flow-aware, i.e., it has an input and output node implicitly used for data flow analysis. */ - abstract class HashOperationInstance extends LocatableElement { } - - abstract class HashAlgorithmInstance extends LocatableElement { } - - abstract class KeyDerivationOperationInstance extends LocatableElement { } - - abstract class KeyDerivationAlgorithmInstance extends LocatableElement { } - - abstract class CipherOperationInstance extends LocatableElement { - abstract CipherAlgorithmInstance getAlgorithm(); - - abstract CipherOperationSubtype getCipherOperationSubtype(); - - abstract NonceArtifactInstance getNonce(); - - abstract DataFlowNode getInputData(); - } - - abstract class CipherAlgorithmInstance extends LocatableElement { } - - abstract class KeyEncapsulationOperationInstance extends LocatableElement { } - - abstract class KeyEncapsulationAlgorithmInstance extends LocatableElement { } - - abstract class EllipticCurveAlgorithmInstance extends LocatableElement { } - - // Non-standalone algorithms - abstract class BlockCipherModeOfOperationAlgorithmInstance extends LocatableElement { } - - abstract class PaddingAlgorithmInstance extends LocatableElement { } - - // Artifacts - abstract class ArtifactLocatableElement extends LocatableElement { + abstract class FlowAwareElement extends LocatableElement { /** * Gets the output node for this artifact, which should usually be the same as `this`. */ - abstract DataFlowNode asOutputData(); + abstract DataFlowNode getOutputNode(); /** * Gets the input node for this artifact. * * If `getInput` is implemented as `none()`, the artifact will not have inbound flow analysis. */ - abstract DataFlowNode getInput(); + abstract DataFlowNode getInputNode(); /** * Holds if this artifact flows to `other`. @@ -133,53 +101,227 @@ module CryptographyBase Input> { * * If `flowsTo` is implemented as `none()`, the artifact will not have outbound flow analysis. */ - abstract predicate flowsTo(ArtifactLocatableElement other); + abstract predicate flowsTo(FlowAwareElement other); + } + + /** + * An element that represents a _known_ cryptographic asset. + */ + abstract class KnownElement extends LocatableElement { + final ConsumerElement getAConsumer() { result.getAKnownSource() = this } + } + + /** + * An element that represents a _known_ cryptographic operation. + */ + abstract class OperationElement extends KnownElement { + /** + * Gets the consumer of algorithms associated with this operation. + */ + abstract AlgorithmConsumer getAlgorithmConsumer(); } - // TODO: WARNING: - // If this overlaps with any other LocatableElement, there will be a cross-product - // This is never to be used for unknowns - abstract class GenericDataSourceInstance extends ArtifactLocatableElement { - final override DataFlowNode getInput() { none() } + /** + * An element that represents a _known_ cryptographic algorithm. + */ + abstract class AlgorithmElement extends KnownElement { } + + /** + * An element that represents a _known_ cryptographic artifact. + */ + abstract class ArtifactElement extends KnownElement, FlowAwareElement { } + + /** + * An element that represents an _unknown_ data-source with a non-statically determinable value. + */ + abstract class GenericDataSourceInstance extends FlowAwareElement { + final override DataFlowNode getInputNode() { none() } + + abstract string getInternalType(); - abstract string getLabel(); + string getAdditionalDescription() { none() } } abstract class GenericConstantOrAllocationSource extends GenericDataSourceInstance { - final override string getLabel() { result = "ConstantData" } // TODO: toString of source? + final override string getInternalType() { result = "ConstantData" } // TODO: toString of source? } abstract class GenericExternalCallSource extends GenericDataSourceInstance { - final override string getLabel() { result = "ExternalCall" } // TODO: call target name or toString of source? + final override string getInternalType() { result = "ExternalCall" } // TODO: call target name or toString of source? } abstract class GenericRemoteDataSource extends GenericDataSourceInstance { - final override string getLabel() { result = "RemoteData" } // TODO: toString of source? + final override string getInternalType() { result = "RemoteData" } // TODO: toString of source? } abstract class GenericLocalDataSource extends GenericDataSourceInstance { - final override string getLabel() { result = "LocalData" } // TODO: toString of source? + final override string getInternalType() { result = "LocalData" } // TODO: toString of source? + } + + /** + * An element that consumes _known_ or _unknown_ cryptographic assets. + * + * Note that known assets are to be modeled explicitly with the `getAKnownSource` predicate, whereas + * unknown assets are modeled implicitly via flow analysis from any `GenericDataSourceInstance` to this element. + * + * A consumer can consume multiple instances and types of assets at once, e.g., both a `PaddingAlgorithm` and `CipherAlgorithm`. + */ + abstract private class ConsumerElement extends FlowAwareElement { + override predicate flowsTo(FlowAwareElement other) { none() } + + override DataFlowNode getOutputNode() { none() } + + GenericDataSourceInstance getAnUnknownSource() { result.flowsTo(this) } + + GenericSourceNode getAnUnknownSourceNode() { result.asElement() = this.getAnUnknownSource() } + + abstract KnownElement getAKnownSource(); + + final NodeBase getAKnownSourceNode() { result.asElement() = this.getAKnownSource() } + + final LocatableElement getAKnownOrUnknownSource() { + result = this.getAKnownSource() + or + result = this.getAnUnknownSource() + } + + NodeBase getAKnownOrUnknownSourceNode() { result.asElement() = this.getAKnownOrUnknownSource() } + } + + /** + * An element that consumes _known_ and _unknown_ values. + * + * A value consumer can consume multiple values and multiple value sources at once. + */ + abstract class ValueConsumer extends ConsumerElement { + final override KnownElement getAKnownSource() { none() } + + abstract string getAKnownValue(Location location); + } + + abstract class AlgorithmConsumer extends ConsumerElement { + final override KnownElement getAKnownSource() { result = this.getAKnownAlgorithmSource() } + + abstract AlgorithmElement getAKnownAlgorithmSource(); } - abstract class DigestArtifactInstance extends ArtifactLocatableElement { } + abstract class ArtifactConsumer extends ConsumerElement { + final override KnownElement getAKnownSource() { result = this.getAKnownArtifactSource() } - abstract class KeyArtifactInstance extends ArtifactLocatableElement { } + final ArtifactElement getAKnownArtifactSource() { result.flowsTo(this) } + } + + abstract class CipherOperationInstance extends OperationElement { + /** + * Gets the subtype of this cipher operation, distinguishing encryption, decryption, key wrapping, and key unwrapping. + */ + abstract CipherOperationSubtype getCipherOperationSubtype(); + + /** + * Gets the consumer of nonces/IVs associated with this cipher operation. + */ + abstract ArtifactConsumer getNonceConsumer(); + + /** + * Gets the consumer of plaintext or ciphertext input associated with this cipher operation. + */ + abstract ArtifactConsumer getMessageConsumer(); + } + + abstract class CipherAlgorithmInstance extends AlgorithmElement { + /** + * Gets the raw name as it appears in source, e.g., "AES/CBC/PKCS7Padding". + * This name is not parsed or formatted. + */ + abstract string getRawAlgorithmName(); + + /** + * Gets the type of this cipher, e.g., "AES" or "ChaCha20". + */ + abstract TCipherType getCipherFamily(); + + /** + * Gets the mode of operation of this cipher, e.g., "GCM" or "CBC". + * + * IMPLEMENTATION NOTE: as a trade-off, this is not a consumer but always either an instance or unknown. + * A mode of operation is therefore assumed to always be part of the cipher algorithm itself. + */ + abstract ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm(); + + /** + * Gets the padding scheme of this cipher, e.g., "PKCS7" or "NoPadding". + * + * IMPLEMENTATION NOTE: as a trade-off, this is not a consumer but always either an instance or unknown. + * A padding algorithm is therefore assumed to always be defined as part of the cipher algorithm itself. + */ + abstract PaddingAlgorithmInstance getPaddingAlgorithm(); + } - abstract class NonceArtifactInstance extends ArtifactLocatableElement { - // no implicit outbound data-flow (only modelled in cipher operations) - override predicate flowsTo(ArtifactLocatableElement other) { none() } + abstract class ModeOfOperationAlgorithmInstance extends AlgorithmElement { + /** + * Gets the type of this mode of operation, e.g., "ECB" or "CBC". + * + * When modeling a new mode of operation, use this predicate to specify the type of the mode. + * + * If a type cannot be determined, the result is `OtherMode`. + */ + abstract TBlockCipherModeOperationType getModeType(); + + /** + * Gets the isolated name as it appears in source, e.g., "CBC" in "AES/CBC/PKCS7Padding". + * + * This name should not be parsed or formatted beyond isolating the raw mode name if necessary. + */ + abstract string getRawModeAlgorithmName(); } - abstract class RandomNumberGenerationInstance extends ArtifactLocatableElement { - final override DataFlowNode getInput() { none() } + abstract class PaddingAlgorithmInstance extends AlgorithmElement { + /** + * Gets the isolated name as it appears in source, e.g., "PKCS7Padding" in "AES/CBC/PKCS7Padding". + * + * This name should not be parsed or formatted beyond isolating the raw padding name if necessary. + */ + abstract string getRawPaddingAlgorithmName(); + + /** + * Gets the type of this padding algorithm, e.g., "PKCS7" or "OAEP". + * + * When modeling a new padding algorithm, use this predicate to specify the type of the padding. + * + * If a type cannot be determined, the result is `OtherPadding`. + */ + abstract TPaddingType getPaddingType(); } + abstract class KeyEncapsulationOperationInstance extends LocatableElement { } + + abstract class KeyEncapsulationAlgorithmInstance extends LocatableElement { } + + abstract class EllipticCurveAlgorithmInstance extends LocatableElement { } + + abstract class HashOperationInstance extends KnownElement { } + + abstract class HashAlgorithmInstance extends KnownElement { } + + abstract class KeyDerivationOperationInstance extends KnownElement { } + + abstract class KeyDerivationAlgorithmInstance extends KnownElement { } + + // Artifacts + abstract class DigestArtifactInstance extends ArtifactElement { } + + abstract class KeyArtifactInstance extends ArtifactElement { } + + abstract class NonceArtifactInstance extends ArtifactElement { } + + abstract class RandomNumberGenerationInstance extends ArtifactElement { } + newtype TNode = // Artifacts (data that is not an operation or algorithm, e.g., a key) TDigest(DigestArtifactInstance e) or TKey(KeyArtifactInstance e) or TNonce(NonceArtifactInstance e) or - TRandomNumberGeneration(RandomNumberGenerationInstance e) or + TRandomNumberGeneration(RandomNumberGenerationInstance e) { e.flowsTo(_) } or // Operations (e.g., hashing, encryption) THashOperation(HashOperationInstance e) or TKeyDerivationOperation(KeyDerivationOperationInstance e) or @@ -193,19 +335,40 @@ module CryptographyBase Input> { TKeyEncapsulationAlgorithm(KeyEncapsulationAlgorithmInstance e) or // Non-standalone Algorithms (e.g., Mode, Padding) // TODO: need to rename this, as "mode" is getting reused in different contexts, be precise - TBlockCipherModeOfOperationAlgorithm(BlockCipherModeOfOperationAlgorithmInstance e) or + TModeOfOperationAlgorithm(ModeOfOperationAlgorithmInstance e) or TPaddingAlgorithm(PaddingAlgorithmInstance e) or // Composite and hybrid cryptosystems (e.g., RSA-OAEP used with AES, post-quantum hybrid cryptosystems) // These nodes are always parent nodes and are not modeled but rather defined via library-agnostic patterns. - TKemDemHybridCryptosystem(CipherAlgorithm dem) or // TODO, change this relation and the below ones + TKemDemHybridCryptosystem(CipherAlgorithmNode dem) or // TODO, change this relation and the below ones TKeyAgreementHybridCryptosystem(CipherAlgorithmInstance ka) or TAsymmetricEncryptionMacHybridCryptosystem(CipherAlgorithmInstance enc) or - TPostQuantumHybridCryptosystem(CipherAlgorithmInstance enc) + TPostQuantumHybridCryptosystem(CipherAlgorithmInstance enc) or + // Unknown source node + TGenericSourceNode(GenericDataSourceInstance e) { e.flowsTo(_) } /** * The base class for all cryptographic assets, such as operations and algorithms. * * Each `NodeBase` is a node in a graph of cryptographic operations, where the edges are the relationships between the nodes. + * + * A node, as opposed to a property, is a construct that can reference or be referenced by more than one node. + * For example: a key size is a single value configuring a cipher algorithm, but a single mode of operation algorithm + * can be referenced by multiple disjoint cipher algorithms. For example, even if the same key size value is reused + * for multiple cipher algorithms, the key size holds no information when devolved to that simple value, and it is + * therefore not a "construct" or "element" being reused by multiple nodes. + * + * As a rule of thumb, a node is an algorithm or the use of an algorithm (an operation), as well as structured data + * consumed by or produced by an operation or algorithm (an artifact) that represents a construct beyond its data. + * + * _Example 1_: A seed of a random number generation algorithm has meaning beyond its value, as its reuse in multiple + * random number generation algorithms is more relevant than its underlying value. In contrast, a key size is only + * relevant to analysis in terms of its underlying value. Therefore, an RNG seed is a node; a key size is not. + * + * _Example 2_: A salt for a key derivation function *is* an `ArtifactNode`. + * + * _Example 3_: The iteration count of a key derivation function is *not* a node. + * + * _Example 4_: A nonce for a cipher operation *is* an `ArtifactNode`. */ abstract class NodeBase extends TNode { /** @@ -221,12 +384,7 @@ module CryptographyBase Input> { /** * Returns the location of this node in the code. */ - abstract Location getLocation(); - - /** - * Gets the origin of this node, e.g., a string literal in source describing it. - */ - LocatableElement getOrigin(string value) { none() } + Location getLocation() { result = this.asElement().getLocation() } /** * Returns the child of this node with the given edge name. @@ -240,165 +398,109 @@ module CryptographyBase Input> { * * This predicate is overriden by derived classes to construct the graph of cryptographic operations. */ - predicate properties(string key, string value, Location location) { - key = "Origin" and - location = this.getOrigin(value).getLocation() and - not location = this.getLocation() - } + predicate properties(string key, string value, Location location) { none() } /** * Returns a parent of this node. */ final NodeBase getAParent() { result.getChild(_) = this } + + /** + * Gets the element associated with this node. + */ + abstract LocatableElement asElement(); + } + + /** + * A generic source node is a source of data that is not resolvable to a specific value or type. + */ + private class GenericSourceNode extends NodeBase, TGenericSourceNode { + GenericDataSourceInstance instance; + + GenericSourceNode() { this = TGenericSourceNode(instance) } + + final override string getInternalType() { result = instance.getInternalType() } + + override LocatableElement asElement() { result = instance } + + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + // [ONLY_KNOWN] + key = "Description" and + value = instance.getAdditionalDescription() and + location = this.getLocation() + } } - class Asset = NodeBase; + class AssetNode = NodeBase; /** * An artifact is an instance of data that is used in a cryptographic operation or produced by one. */ - abstract class Artifact extends NodeBase { - /** - * Gets the artifact locatable element associated with this artifact. - * - * *Implementation note*: to avoid cross-products, the result *must* only bind to the - * `ArtifactLocatableElement` that is already associated with the node instance. - */ - abstract ArtifactLocatableElement asArtifactLocatableElement(); - + abstract class ArtifactNode extends NodeBase { /** * Gets the `Artifact` node that is the data source for this artifact. */ - final Artifact getSourceArtifact() { - result.asArtifactLocatableElement() = this.getSourceArtifactElement() - } + final NodeBase getSourceNode() { result.asElement() = this.getSourceElement() } /** * Gets the `ArtifactLocatableElement` that is the data source for this artifact. * * This predicate is equivalent to `getSourceArtifact().asArtifactLocatableElement()`. */ - final ArtifactLocatableElement getSourceArtifactElement() { - not result = this.asArtifactLocatableElement() and - result.flowsTo(this.asArtifactLocatableElement()) + final FlowAwareElement getSourceElement() { + not result = this.asElement() and result.flowsTo(this.asElement()) } + /** + * Gets a string describing the relationship between this artifact and its source. + * + * If a child class defines this predicate as `none()`, no relationship will be reported. + */ + string getSourceNodeRelationship() { result = "Source" } + override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) or - // [ONLY_KNOWN] - TODO: known-unknown case handled by reporting a generic source type or unknown as a property - edgeName = "Source" and - result = this.getSourceArtifact() - } - - // TODO: document the below - final private predicate src_generic_data_source_to_label_and_loc(string label, Location location) { - exists(GenericDataSourceInstance instance | - this.getSourceArtifactElement() = instance and - instance.getLabel() = label and - instance.getLocation() = location - ) - } - - final private predicate src_artifact_to_label_and_loc(string label, Location location) { - exists(Artifact a | - this.getSourceArtifact() = a and - a.getInternalType() = label and - a.getLocation() = location - ) - } - - final private predicate source_type_property(string key, string value, Location location) { - key = "SourceType" and - if this.src_artifact_to_label_and_loc(_, _) - then this.src_artifact_to_label_and_loc(value, location) - else - if - exists(this.asArtifactLocatableElement().getInput()) and - not this.src_generic_data_source_to_label_and_loc(_, _) - then value instanceof UnknownPropertyValue and location instanceof UnknownLocation - else this.src_generic_data_source_to_label_and_loc(value, location) - } - - override predicate properties(string key, string value, Location location) { - super.properties(key, value, location) - or - this.source_type_property(key, value, location) + // [KNOWN_OR_UNKNOWN] + edgeName = this.getSourceNodeRelationship() and // only holds if not set to none() + if exists(this.getSourceNode()) then result = this.getSourceNode() else result = this } } /** * A nonce or initialization vector */ - private class NonceImpl extends Artifact, TNonce { + final class NonceNode extends ArtifactNode, TNonce { NonceArtifactInstance instance; - NonceImpl() { this = TNonce(instance) } + NonceNode() { this = TNonce(instance) } final override string getInternalType() { result = "Nonce" } - override Location getLocation() { result = instance.getLocation() } - - override ArtifactLocatableElement asArtifactLocatableElement() { result = instance } + override LocatableElement asElement() { result = instance } } - final class Nonce = NonceImpl; - /** * A source of random number generation */ - final private class RandomNumberGenerationImpl extends Artifact, TRandomNumberGeneration { + final class RandomNumberGenerationNode extends ArtifactNode, TRandomNumberGeneration { RandomNumberGenerationInstance instance; - RandomNumberGenerationImpl() { this = TRandomNumberGeneration(instance) } + RandomNumberGenerationNode() { this = TRandomNumberGeneration(instance) } final override string getInternalType() { result = "RandomNumberGeneration" } - override Location getLocation() { result = instance.getLocation() } - - override ArtifactLocatableElement asArtifactLocatableElement() { result = instance } + override LocatableElement asElement() { result = instance } } - final class RandomNumberGeneration = RandomNumberGenerationImpl; - /** * A cryptographic operation, such as hashing or encryption. */ - abstract class Operation extends Asset { - /** - * Gets the algorithm associated with this operation. - */ - abstract Algorithm getAlgorithm(); - - override NodeBase getChild(string edgeName) { - result = super.getChild(edgeName) - or - /* - * TODO: Consider a case with getProperty, where an unknown value is loaded from the filesystem, - * but a default is specified as such: - * String value = getProperty("property", "default_algorithm") - * In this case, getAlgorithm *could* be resolved to default_algorithm, but in that case, the known - * unknown case, i.e., what is loaded from `property`, would not be reported at all as a known unknown. - * - * Implementation brainstorming: - * We have two cases, and we only considered one before: the case where we can't point to the known unknown. - * The new case is pointing to a known unknown, e.g., "property" loaded via getProperty. - * A potential solution is to create a known unknown node for each node type (particularly algorithms) - * and model those elements in the database to associate with that known unknown type?? - * - * - Idea: use the generic data source concept as the definition of potential known unknowns. - * flow should be tracked from them to anything that could be a "sink" that specifies the relation. - * in this case, the sink would be an instantiaition of an algorithm where the value is not resolvable. - */ - - edgeName = "Uses" and - if exists(this.getAlgorithm()) then result = this.getAlgorithm() else result = this - } - } - - abstract class Algorithm extends Asset { - final override string getInternalType() { result = this.getAlgorithmType() } + abstract class OperationNode extends AssetNode { } + abstract class AlgorithmNode extends AssetNode { /** * Gets the name of this algorithm, e.g., "AES" or "SHA". */ @@ -409,11 +511,6 @@ module CryptographyBase Input> { */ abstract string getRawAlgorithmName(); - /** - * Gets the type of this algorithm, e.g., "hash" or "key derivation". - */ - abstract string getAlgorithmType(); - override predicate properties(string key, string value, Location location) { super.properties(key, value, location) or @@ -425,256 +522,352 @@ module CryptographyBase Input> { } } - /** - * A hashing operation that processes data to generate a hash value. - * - * This operation takes an input message of arbitrary content and length and produces a fixed-size - * hash value as the output using a specified hashing algorithm. - */ - abstract class HashOperation extends Operation, THashOperation { - abstract override HashAlgorithm getAlgorithm(); - //override string getOperationType() { result = "HashOperation" } + newtype TCipherOperationSubtype = + TEncryptionMode() or + TDecryptionMode() or + TWrapMode() or + TUnwrapMode() or + TUnknownCipherOperationMode() + + abstract class CipherOperationSubtype extends TCipherOperationSubtype { + abstract string toString(); } - newtype THashType = - MD2() or - MD4() or - MD5() or - SHA1() or - SHA2() or - SHA3() or - RIPEMD160() or - WHIRLPOOL() or - OtherHashType() + class EncryptionSubtype extends CipherOperationSubtype, TEncryptionMode { + override string toString() { result = "Encrypt" } + } + + class DecryptionSubtype extends CipherOperationSubtype, TDecryptionMode { + override string toString() { result = "Decrypt" } + } + + class WrapSubtype extends CipherOperationSubtype, TWrapMode { + override string toString() { result = "Wrap" } + } + + class UnwrapSubtype extends CipherOperationSubtype, TUnwrapMode { + override string toString() { result = "Unwrap" } + } + + class UnknownCipherOperationSubtype extends CipherOperationSubtype, TUnknownCipherOperationMode { + override string toString() { result = "Unknown" } + } /** - * A hashing algorithm that transforms variable-length input into a fixed-size hash value. + * An encryption operation that processes plaintext to generate a ciphertext. + * This operation takes an input message (plaintext) of arbitrary content and length + * and produces a ciphertext as the output using a specified encryption algorithm (with a mode and padding). */ - abstract class HashAlgorithm extends Algorithm, THashAlgorithm { - override string getAlgorithmType() { result = "HashAlgorithm" } + final class CipherOperationNode extends OperationNode, TCipherOperation { + CipherOperationInstance instance; - final predicate hashTypeToNameMapping(THashType type, string name) { - type instanceof MD2 and name = "MD2" - or - type instanceof MD4 and name = "MD4" - or - type instanceof MD5 and name = "MD5" - or - type instanceof SHA1 and name = "SHA1" - or - type instanceof SHA2 and name = "SHA2" - or - type instanceof SHA3 and name = "SHA3" + CipherOperationNode() { this = TCipherOperation(instance) } + + override LocatableElement asElement() { result = instance } + + override string getInternalType() { result = "CipherOperation" } + + /** + * Gets the algorithm or unknown source nodes consumed as an algorithm associated with this operation. + */ + NodeBase getACipherAlgorithmOrUnknown() { + result = this.getAKnownCipherAlgorithm() or + result = this.asElement().(OperationElement).getAlgorithmConsumer().getAnUnknownSourceNode() + } + + /** + * Gets a known algorithm associated with this operation + */ + CipherAlgorithmNode getAKnownCipherAlgorithm() { + result = this.asElement().(OperationElement).getAlgorithmConsumer().getAKnownSourceNode() + } + + CipherOperationSubtype getCipherOperationSubtype() { + result = instance.getCipherOperationSubtype() + } + + NodeBase getANonceOrUnknown() { + result = + this.asElement().(CipherOperationInstance).getNonceConsumer().getAKnownOrUnknownSourceNode() + } + + NonceNode getANonce() { + result = this.asElement().(CipherOperationInstance).getNonceConsumer().getAKnownSourceNode() + } + + NodeBase getAMessageOrUnknown() { + result = + this.asElement() + .(CipherOperationInstance) + .getMessageConsumer() + .getAKnownOrUnknownSourceNode() + } + + override NodeBase getChild(string key) { + result = super.getChild(key) or - type instanceof RIPEMD160 and name = "RIPEMD160" + // [KNOWN_OR_UNKNOWN] + key = "Algorithm" and + if exists(this.getACipherAlgorithmOrUnknown()) + then result = this.getACipherAlgorithmOrUnknown() + else result = this or - type instanceof WHIRLPOOL and name = "WHIRLPOOL" + // [KNOWN_OR_UNKNOWN] + key = "Nonce" and + if exists(this.getANonceOrUnknown()) + then result = this.getANonceOrUnknown() + else result = this or - type instanceof OtherHashType and name = this.getRawAlgorithmName() + // [KNOWN_OR_UNKNOWN] + key = "Message" and + if exists(this.getAMessageOrUnknown()) + then result = this.getAMessageOrUnknown() + else result = this } - /** - * Gets the type of this hashing algorithm, e.g., MD5 or SHA. - * - * When modeling a new hashing algorithm, use this predicate to specify the type of the algorithm. - */ - abstract THashType getHashType(); + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + // [ALWAYS_KNOWN] - Unknown is handled in getCipherOperationMode() + key = "Operation" and + value = this.getCipherOperationSubtype().toString() and + location = this.getLocation() + } + } - override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashType(), result) } + /** + * Block cipher modes of operation algorithms + */ + newtype TBlockCipherModeOperationType = + ECB() or // Not secure, widely used + CBC() or // Vulnerable to padding oracle attacks + GCM() or // Widely used AEAD mode (TLS 1.3, SSH, IPsec) + CTR() or // Fast stream-like encryption (SSH, disk encryption) + XTS() or // Standard for full-disk encryption (BitLocker, LUKS, FileVault) + CCM() or // Used in lightweight cryptography (IoT, WPA2) + SIV() or // Misuse-resistant encryption, used in secure storage + OCB() or // Efficient AEAD mode + OtherMode() + + class ModeOfOperationAlgorithmNode extends AlgorithmNode, TModeOfOperationAlgorithm { + ModeOfOperationAlgorithmInstance instance; + + ModeOfOperationAlgorithmNode() { this = TModeOfOperationAlgorithm(instance) } + + override LocatableElement asElement() { result = instance } + + override string getInternalType() { result = "ModeOfOperation" } + + override string getRawAlgorithmName() { result = instance.getRawModeAlgorithmName() } /** - * Gets the digest size of SHA2 or SHA3 algorithms. + * Gets the type of this mode of operation, e.g., "ECB" or "CBC". * - * This predicate does not need to hold for other algorithms, - * as the digest size is already known based on the algorithm itself. + * When modeling a new mode of operation, use this predicate to specify the type of the mode. * - * For `OtherHashType` algorithms where a digest size should be reported, `THashType` - * should be extended to explicitly model that algorithm. If the algorithm has variable - * or multiple digest size variants, a similar predicate to this one must be defined - * for that algorithm to report the digest size. + * If a type cannot be determined, the result is `OtherMode`. */ - abstract string getSHA2OrSHA3DigestSize(Location location); + TBlockCipherModeOperationType getModeType() { result = instance.getModeType() } bindingset[type] - private string getTypeDigestSizeFixed(THashType type) { - type instanceof MD2 and result = "128" + final private predicate modeToNameMapping(TBlockCipherModeOperationType type, string name) { + type instanceof ECB and name = "ECB" or - type instanceof MD4 and result = "128" + type instanceof CBC and name = "CBC" or - type instanceof MD5 and result = "128" + type instanceof GCM and name = "GCM" or - type instanceof SHA1 and result = "160" + type instanceof CTR and name = "CTR" or - type instanceof RIPEMD160 and result = "160" + type instanceof XTS and name = "XTS" or - type instanceof WHIRLPOOL and result = "512" + type instanceof CCM and name = "CCM" + or + type instanceof SIV and name = "SIV" + or + type instanceof OCB and name = "OCB" + or + type instanceof OtherMode and name = this.getRawAlgorithmName() } + override string getAlgorithmName() { this.modeToNameMapping(this.getModeType(), result) } + } + + newtype TPaddingType = + PKCS1_v1_5() or // RSA encryption/signing padding + PKCS7() or // Standard block cipher padding (PKCS5 for 8-byte blocks) + ANSI_X9_23() or // Zero-padding except last byte = padding length + NoPadding() or // Explicit no-padding + OAEP() or // RSA OAEP padding + OtherPadding() + + class PaddingAlgorithmNode extends AlgorithmNode, TPaddingAlgorithm { + PaddingAlgorithmInstance instance; + + PaddingAlgorithmNode() { this = TPaddingAlgorithm(instance) } + + override string getInternalType() { result = "PaddingAlgorithm" } + + override LocatableElement asElement() { result = instance } + + TPaddingType getPaddingType() { result = instance.getPaddingType() } + bindingset[type] - private string getTypeDigestSize(THashType type, Location location) { - result = this.getTypeDigestSizeFixed(type) and location = this.getLocation() + final private predicate paddingToNameMapping(TPaddingType type, string name) { + type instanceof PKCS1_v1_5 and name = "PKCS1_v1_5" or - type instanceof SHA2 and result = this.getSHA2OrSHA3DigestSize(location) + type instanceof PKCS7 and name = "PKCS7" or - type instanceof SHA3 and result = this.getSHA2OrSHA3DigestSize(location) + type instanceof ANSI_X9_23 and name = "ANSI_X9_23" + or + type instanceof NoPadding and name = "NoPadding" + or + type instanceof OAEP and name = "OAEP" + or + type instanceof OtherPadding and name = this.getRawAlgorithmName() } - string getDigestSize(Location location) { - result = this.getTypeDigestSize(this.getHashType(), location) - } + override string getAlgorithmName() { this.paddingToNameMapping(this.getPaddingType(), result) } - final override predicate properties(string key, string value, Location location) { - super.properties(key, value, location) - or - // [KNOWN_OR_UNKNOWN] - key = "DigestSize" and - if exists(this.getDigestSize(location)) - then value = this.getDigestSize(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - } + override string getRawAlgorithmName() { result = instance.getRawPaddingAlgorithmName() } } /** - * An operation that derives one or more keys from an input value. + * A helper type for distinguishing between block and stream ciphers. */ - abstract class KeyDerivationOperation extends Operation, TKeyDerivationOperation { - final override Location getLocation() { - exists(LocatableElement le | this = TKeyDerivationOperation(le) and result = le.getLocation()) - } - //override string getOperationType() { result = "KeyDerivationOperation" } + newtype TCipherStructureType = + Block() or + Stream() or + Asymmetric() or + UnknownCipherStructureType() + + private string getCipherStructureTypeString(TCipherStructureType type) { + type instanceof Block and result = "Block" + or + type instanceof Stream and result = "Stream" + or + type instanceof Asymmetric and result = "Asymmetric" + or + type instanceof UnknownCipherStructureType and result instanceof UnknownPropertyValue } /** - * An algorithm that derives one or more keys from an input value. - * - * Only use this class to model UNKNOWN key derivation algorithms. - * - * For known algorithms, use the specialized classes, e.g., `HKDF` and `PKCS12KDF`. + * Symmetric algorithms */ - abstract class KeyDerivationAlgorithm extends Algorithm, TKeyDerivationAlgorithm { - final override Location getLocation() { - exists(LocatableElement le | this = TKeyDerivationAlgorithm(le) and result = le.getLocation()) - } + newtype TCipherType = + AES() or + Camellia() or + DES() or + TripleDES() or + IDEA() or + CAST5() or + ChaCha20() or + RC4() or + RC5() or + RSA() or + OtherCipherType() - override string getAlgorithmType() { result = "KeyDerivationAlgorithm" } + final class CipherAlgorithmNode extends AlgorithmNode, TCipherAlgorithm { + CipherAlgorithmInstance instance; - override string getAlgorithmName() { result = this.getRawAlgorithmName() } - } + CipherAlgorithmNode() { this = TCipherAlgorithm(instance) } - /** - * An algorithm that derives one or more keys from an input value, using a configurable digest algorithm. - */ - abstract private class KeyDerivationWithDigestParameter extends KeyDerivationAlgorithm { - abstract HashAlgorithm getHashAlgorithm(); + override LocatableElement asElement() { result = instance } - override NodeBase getChild(string edgeName) { - result = super.getChild(edgeName) - or - ( - // [KNOWN_OR_UNKNOWN] - edgeName = "Uses" and - if exists(this.getHashAlgorithm()) then result = this.getHashAlgorithm() else result = this - ) + override string getInternalType() { result = "CipherAlgorithm" } + + final TCipherStructureType getCipherStructure() { + this.cipherFamilyToNameAndStructure(this.getCipherFamily(), _, result) } - } - /** - * HKDF key derivation function - */ - abstract class HKDF extends KeyDerivationWithDigestParameter { - final override string getAlgorithmName() { result = "HKDF" } - } + final override string getAlgorithmName() { + this.cipherFamilyToNameAndStructure(this.getCipherFamily(), result, _) + } - /** - * PBKDF2 key derivation function - */ - abstract class PBKDF2 extends KeyDerivationWithDigestParameter { - final override string getAlgorithmName() { result = "PBKDF2" } + final override string getRawAlgorithmName() { result = instance.getRawAlgorithmName() } /** - * Gets the iteration count of this key derivation algorithm. + * Gets the key size of this cipher, e.g., "128" or "256". */ - abstract string getIterationCount(Location location); + string getKeySize(Location location) { none() } // TODO /** - * Gets the bit-length of the derived key. + * Gets the type of this cipher, e.g., "AES" or "ChaCha20". */ - abstract string getKeyLength(Location location); + TCipherType getCipherFamily() { result = instance.getCipherFamily() } - override predicate properties(string key, string value, Location location) { - super.properties(key, value, location) - or - ( - // [KNOWN_OR_UNKNOWN] - key = "Iterations" and - if exists(this.getIterationCount(location)) - then value = this.getIterationCount(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - ) - or - ( - // [KNOWN_OR_UNKNOWN] - key = "KeyLength" and - if exists(this.getKeyLength(location)) - then value = this.getKeyLength(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - ) + /** + * Gets the mode of operation of this cipher, e.g., "GCM" or "CBC". + */ + ModeOfOperationAlgorithmNode getModeOfOperation() { + result.asElement() = instance.getModeOfOperationAlgorithm() } - } - - /** - * PKCS12KDF key derivation function - */ - abstract class PKCS12KDF extends KeyDerivationWithDigestParameter { - override string getAlgorithmName() { result = "PKCS12KDF" } /** - * Gets the iteration count of this key derivation algorithm. + * Gets the padding scheme of this cipher, e.g., "PKCS7" or "NoPadding". */ - abstract string getIterationCount(Location location); + PaddingAlgorithmNode getPaddingAlgorithm() { + result.asElement() = instance.getPaddingAlgorithm() + } - /** - * Gets the raw ID argument specifying the intended use of the derived key. - * - * The intended use is defined in RFC 7292, appendix B.3, as follows: - * - * This standard specifies 3 different values for the ID byte mentioned above: - * - * 1. If ID=1, then the pseudorandom bits being produced are to be used - * as key material for performing encryption or decryption. - * - * 2. If ID=2, then the pseudorandom bits being produced are to be used - * as an IV (Initial Value) for encryption or decryption. - * - * 3. If ID=3, then the pseudorandom bits being produced are to be used - * as an integrity key for MACing. - */ - abstract string getIDByte(Location location); + bindingset[type] + final private predicate cipherFamilyToNameAndStructure( + TCipherType type, string name, TCipherStructureType s + ) { + type instanceof AES and name = "AES" and s = Block() + or + type instanceof Camellia and name = "Camellia" and s = Block() + or + type instanceof DES and name = "DES" and s = Block() + or + type instanceof TripleDES and name = "TripleDES" and s = Block() + or + type instanceof IDEA and name = "IDEA" and s = Block() + or + type instanceof CAST5 and name = "CAST5" and s = Block() + or + type instanceof ChaCha20 and name = "ChaCha20" and s = Stream() + or + type instanceof RC4 and name = "RC4" and s = Stream() + or + type instanceof RC5 and name = "RC5" and s = Block() + or + type instanceof RSA and name = "RSA" and s = Asymmetric() + or + type instanceof OtherCipherType and + name = this.getRawAlgorithmName() and + s = UnknownCipherStructureType() + } + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + // [KNOWN_OR_UNKNOWN] + edgeName = "Mode" and + if exists(this.getModeOfOperation()) + then result = this.getModeOfOperation() + else result = this + or + // [KNOWN_OR_UNKNOWN] + edgeName = "Padding" and + if exists(this.getPaddingAlgorithm()) + then result = this.getPaddingAlgorithm() + else result = this + } override predicate properties(string key, string value, Location location) { super.properties(key, value, location) or - ( - // [KNOWN_OR_UNKNOWN] - key = "Iterations" and - if exists(this.getIterationCount(location)) - then value = this.getIterationCount(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - ) + // [ALWAYS_KNOWN] - unknown case is handled in `getCipherStructureTypeString` + key = "Structure" and + getCipherStructureTypeString(this.getCipherStructure()) = value and + location instanceof UnknownLocation or ( // [KNOWN_OR_UNKNOWN] - key = "IdByte" and - if exists(this.getIDByte(location)) - then value = this.getIDByte(location) + key = "KeySize" and + if exists(this.getKeySize(location)) + then value = this.getKeySize(location) else ( value instanceof UnknownPropertyValue and location instanceof UnknownLocation ) @@ -683,39 +876,191 @@ module CryptographyBase Input> { } /** - * scrypt key derivation function + * A hashing operation that processes data to generate a hash value. + * + * This operation takes an input message of arbitrary content and length and produces a fixed-size + * hash value as the output using a specified hashing algorithm. */ - abstract class SCRYPT extends KeyDerivationAlgorithm { - final override string getAlgorithmName() { result = "scrypt" } + abstract class HashOperationNode extends OperationNode, THashOperation { + abstract HashAlgorithmNode getAlgorithm(); + } + + newtype THashType = + MD2() or + MD4() or + MD5() or + SHA1() or + SHA2() or + SHA3() or + RIPEMD160() or + WHIRLPOOL() or + OtherHashType() + + /** + * A hashing algorithm that transforms variable-length input into a fixed-size hash value. + */ + abstract class HashAlgorithmNode extends AlgorithmNode, THashAlgorithm { + override string getInternalType() { result = "HashAlgorithm" } + + final predicate hashTypeToNameMapping(THashType type, string name) { + type instanceof MD2 and name = "MD2" + or + type instanceof MD4 and name = "MD4" + or + type instanceof MD5 and name = "MD5" + or + type instanceof SHA1 and name = "SHA1" + or + type instanceof SHA2 and name = "SHA2" + or + type instanceof SHA3 and name = "SHA3" + or + type instanceof RIPEMD160 and name = "RIPEMD160" + or + type instanceof WHIRLPOOL and name = "WHIRLPOOL" + or + type instanceof OtherHashType and name = this.getRawAlgorithmName() + } /** - * Gets the iteration count (`N`) argument + * Gets the type of this hashing algorithm, e.g., MD5 or SHA. + * + * When modeling a new hashing algorithm, use this predicate to specify the type of the algorithm. */ - abstract string get_N(Location location); + abstract THashType getHashType(); + + override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashType(), result) } /** - * Gets the block size (`r`) argument + * Gets the digest size of SHA2 or SHA3 algorithms. + * + * This predicate does not need to hold for other algorithms, + * as the digest size is already known based on the algorithm itself. + * + * For `OtherHashType` algorithms where a digest size should be reported, `THashType` + * should be extended to explicitly model that algorithm. If the algorithm has variable + * or multiple digest size variants, a similar predicate to this one must be defined + * for that algorithm to report the digest size. */ - abstract string get_r(Location location); + abstract string getSHA2OrSHA3DigestSize(Location location); + + bindingset[type] + private string getTypeDigestSizeFixed(THashType type) { + type instanceof MD2 and result = "128" + or + type instanceof MD4 and result = "128" + or + type instanceof MD5 and result = "128" + or + type instanceof SHA1 and result = "160" + or + type instanceof RIPEMD160 and result = "160" + or + type instanceof WHIRLPOOL and result = "512" + } + + bindingset[type] + private string getTypeDigestSize(THashType type, Location location) { + result = this.getTypeDigestSizeFixed(type) and location = this.getLocation() + or + type instanceof SHA2 and result = this.getSHA2OrSHA3DigestSize(location) + or + type instanceof SHA3 and result = this.getSHA2OrSHA3DigestSize(location) + } + + string getDigestSize(Location location) { + result = this.getTypeDigestSize(this.getHashType(), location) + } + + final override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + // [KNOWN_OR_UNKNOWN] + key = "DigestSize" and + if exists(this.getDigestSize(location)) + then value = this.getDigestSize(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + } + } + + /** + * An operation that derives one or more keys from an input value. + */ + abstract class KeyDerivationOperationNode extends OperationNode, TKeyDerivationOperation { + final override Location getLocation() { + exists(LocatableElement le | this = TKeyDerivationOperation(le) and result = le.getLocation()) + } + + override string getInternalType() { result = "KeyDerivationOperation" } + } + + /** + * An algorithm that derives one or more keys from an input value. + * + * Only use this class to model UNKNOWN key derivation algorithms. + * + * For known algorithms, use the specialized classes, e.g., `HKDF` and `PKCS12KDF`. + */ + abstract class KeyDerivationAlgorithmNode extends AlgorithmNode, TKeyDerivationAlgorithm { + final override Location getLocation() { + exists(LocatableElement le | this = TKeyDerivationAlgorithm(le) and result = le.getLocation()) + } + + override string getInternalType() { result = "KeyDerivationAlgorithm" } + + override string getAlgorithmName() { result = this.getRawAlgorithmName() } + } + + /** + * An algorithm that derives one or more keys from an input value, using a configurable digest algorithm. + */ + abstract private class KeyDerivationWithDigestParameterNode extends KeyDerivationAlgorithmNode { + abstract HashAlgorithmNode getHashAlgorithm(); + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + ( + // [KNOWN_OR_UNKNOWN] + edgeName = "Uses" and + if exists(this.getHashAlgorithm()) then result = this.getHashAlgorithm() else result = this + ) + } + } + + /** + * HKDF key derivation function + */ + abstract class HKDFNode extends KeyDerivationWithDigestParameterNode { + final override string getAlgorithmName() { result = "HKDF" } + } + + /** + * PBKDF2 key derivation function + */ + abstract class PBKDF2Node extends KeyDerivationWithDigestParameterNode { + final override string getAlgorithmName() { result = "PBKDF2" } /** - * Gets the parallelization factor (`p`) argument + * Gets the iteration count of this key derivation algorithm. */ - abstract string get_p(Location location); + abstract string getIterationCount(Location location); /** - * Gets the derived key length argument + * Gets the bit-length of the derived key. */ - abstract string getDerivedKeyLength(Location location); + abstract string getKeyLength(Location location); override predicate properties(string key, string value, Location location) { super.properties(key, value, location) or ( // [KNOWN_OR_UNKNOWN] - key = "N" and - if exists(this.get_N(location)) - then value = this.get_N(location) + key = "Iterations" and + if exists(this.getIterationCount(location)) + then value = this.getIterationCount(location) else ( value instanceof UnknownPropertyValue and location instanceof UnknownLocation ) @@ -723,21 +1068,126 @@ module CryptographyBase Input> { or ( // [KNOWN_OR_UNKNOWN] - key = "r" and - if exists(this.get_r(location)) - then value = this.get_r(location) + key = "KeyLength" and + if exists(this.getKeyLength(location)) + then value = this.getKeyLength(location) else ( value instanceof UnknownPropertyValue and location instanceof UnknownLocation ) ) - or - ( - // [KNOWN_OR_UNKNOWN] - key = "p" and - if exists(this.get_p(location)) - then value = this.get_p(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation + } + } + + /** + * PKCS12KDF key derivation function + */ + abstract class PKCS12KDF extends KeyDerivationWithDigestParameterNode { + override string getAlgorithmName() { result = "PKCS12KDF" } + + /** + * Gets the iteration count of this key derivation algorithm. + */ + abstract string getIterationCount(Location location); + + /** + * Gets the raw ID argument specifying the intended use of the derived key. + * + * The intended use is defined in RFC 7292, appendix B.3, as follows: + * + * This standard specifies 3 different values for the ID byte mentioned above: + * + * 1. If ID=1, then the pseudorandom bits being produced are to be used + * as key material for performing encryption or decryption. + * + * 2. If ID=2, then the pseudorandom bits being produced are to be used + * as an IV (Initial Value) for encryption or decryption. + * + * 3. If ID=3, then the pseudorandom bits being produced are to be used + * as an integrity key for MACing. + */ + abstract string getIDByte(Location location); + + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + ( + // [KNOWN_OR_UNKNOWN] + key = "Iterations" and + if exists(this.getIterationCount(location)) + then value = this.getIterationCount(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + ) + or + ( + // [KNOWN_OR_UNKNOWN] + key = "IdByte" and + if exists(this.getIDByte(location)) + then value = this.getIDByte(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + ) + } + } + + /** + * scrypt key derivation function + */ + abstract class SCRYPT extends KeyDerivationAlgorithmNode { + final override string getAlgorithmName() { result = "scrypt" } + + /** + * Gets the iteration count (`N`) argument + */ + abstract string get_N(Location location); + + /** + * Gets the block size (`r`) argument + */ + abstract string get_r(Location location); + + /** + * Gets the parallelization factor (`p`) argument + */ + abstract string get_p(Location location); + + /** + * Gets the derived key length argument + */ + abstract string getDerivedKeyLength(Location location); + + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + ( + // [KNOWN_OR_UNKNOWN] + key = "N" and + if exists(this.get_N(location)) + then value = this.get_N(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + ) + or + ( + // [KNOWN_OR_UNKNOWN] + key = "r" and + if exists(this.get_r(location)) + then value = this.get_r(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation + ) + ) + or + ( + // [KNOWN_OR_UNKNOWN] + key = "p" and + if exists(this.get_p(location)) + then value = this.get_p(location) + else ( + value instanceof UnknownPropertyValue and location instanceof UnknownLocation ) ) or @@ -787,7 +1237,7 @@ module CryptographyBase Input> { ES() or OtherEllipticCurveType() - abstract class EllipticCurve extends Algorithm, TEllipticCurveAlgorithm { + abstract class EllipticCurve extends AlgorithmNode, TEllipticCurveAlgorithm { abstract string getKeySize(Location location); abstract TEllipticCurveType getCurveFamily(); @@ -822,311 +1272,7 @@ module CryptographyBase Input> { abstract override string getRawAlgorithmName(); } - newtype TCipherOperationSubtype = - TEncryptionMode() or - TDecryptionMode() or - TWrapMode() or - TUnwrapMode() or - TUnknownCipherOperationMode() - - abstract class CipherOperationSubtype extends TCipherOperationSubtype { - abstract string toString(); - } - - class EncryptionMode extends CipherOperationSubtype, TEncryptionMode { - override string toString() { result = "Encrypt" } - } - - class DecryptionMode extends CipherOperationSubtype, TDecryptionMode { - override string toString() { result = "Decrypt" } - } - - class WrapMode extends CipherOperationSubtype, TWrapMode { - override string toString() { result = "Wrap" } - } - - class UnwrapMode extends CipherOperationSubtype, TUnwrapMode { - override string toString() { result = "Unwrap" } - } - - class UnknownCipherOperationMode extends CipherOperationSubtype, TUnknownCipherOperationMode { - override string toString() { result = "Unknown" } - } - - /** - * An encryption operation that processes plaintext to generate a ciphertext. - * This operation takes an input message (plaintext) of arbitrary content and length - * and produces a ciphertext as the output using a specified encryption algorithm (with a mode and padding). - */ - class CipherOperationImpl extends Operation, TCipherOperation { - CipherOperationInstance instance; - - CipherOperationImpl() { this = TCipherOperation(instance) } - - override string getInternalType() { result = "CipherOperation" } - - override Location getLocation() { result = instance.getLocation() } - - CipherOperationSubtype getCipherOperationMode() { - result = instance.getCipherOperationSubtype() - } - - final override CipherAlgorithm getAlgorithm() { result.getInstance() = instance.getAlgorithm() } - - override NodeBase getChild(string key) { - result = super.getChild(key) - or - // [KNOWN_OR_UNKNOWN] - key = "Nonce" and - if exists(this.getNonce()) then result = this.getNonce() else result = this - } - - override predicate properties(string key, string value, Location location) { - super.properties(key, value, location) - or - // [ALWAYS_KNOWN] - Unknown is handled in getCipherOperationMode() - key = "Operation" and - value = this.getCipherOperationMode().toString() and - location = this.getLocation() - } - - /** - * Gets the initialization vector associated with this encryption operation. - * - * This predicate does not need to hold for all encryption operations, - * as the initialization vector is not always required. - */ - Nonce getNonce() { result = TNonce(instance.getNonce()) } - - DataFlowNode getInputData() { result = instance.getInputData() } - } - - final class CipherOperation = CipherOperationImpl; - - /** - * Block cipher modes of operation algorithms - */ - newtype TBlockCipherModeOperationType = - ECB() or // Not secure, widely used - CBC() or // Vulnerable to padding oracle attacks - GCM() or // Widely used AEAD mode (TLS 1.3, SSH, IPsec) - CTR() or // Fast stream-like encryption (SSH, disk encryption) - XTS() or // Standard for full-disk encryption (BitLocker, LUKS, FileVault) - CCM() or // Used in lightweight cryptography (IoT, WPA2) - SIV() or // Misuse-resistant encryption, used in secure storage - OCB() or // Efficient AEAD mode - OtherMode() - - abstract class ModeOfOperationAlgorithm extends Algorithm, TBlockCipherModeOfOperationAlgorithm { - override string getAlgorithmType() { result = "ModeOfOperation" } - - /** - * Gets the type of this mode of operation, e.g., "ECB" or "CBC". - * - * When modeling a new mode of operation, use this predicate to specify the type of the mode. - * - * If a type cannot be determined, the result is `OtherMode`. - */ - abstract TBlockCipherModeOperationType getModeType(); - - bindingset[type] - final private predicate modeToNameMapping(TBlockCipherModeOperationType type, string name) { - type instanceof ECB and name = "ECB" - or - type instanceof CBC and name = "CBC" - or - type instanceof GCM and name = "GCM" - or - type instanceof CTR and name = "CTR" - or - type instanceof XTS and name = "XTS" - or - type instanceof CCM and name = "CCM" - or - type instanceof SIV and name = "SIV" - or - type instanceof OCB and name = "OCB" - or - type instanceof OtherMode and name = this.getRawAlgorithmName() - } - - override string getAlgorithmName() { this.modeToNameMapping(this.getModeType(), result) } - } - - newtype TPaddingType = - PKCS1_v1_5() or // RSA encryption/signing padding - PKCS7() or // Standard block cipher padding (PKCS5 for 8-byte blocks) - ANSI_X9_23() or // Zero-padding except last byte = padding length - NoPadding() or // Explicit no-padding - OAEP() or // RSA OAEP padding - OtherPadding() - - abstract class PaddingAlgorithm extends Algorithm, TPaddingAlgorithm { - override string getAlgorithmType() { result = "PaddingAlgorithm" } - - /** - * Gets the type of this padding algorithm, e.g., "PKCS7" or "OAEP". - * - * When modeling a new padding algorithm, use this predicate to specify the type of the padding. - * - * If a type cannot be determined, the result is `OtherPadding`. - */ - abstract TPaddingType getPaddingType(); - - bindingset[type] - final private predicate paddingToNameMapping(TPaddingType type, string name) { - type instanceof PKCS1_v1_5 and name = "PKCS1_v1_5" - or - type instanceof PKCS7 and name = "PKCS7" - or - type instanceof ANSI_X9_23 and name = "ANSI_X9_23" - or - type instanceof NoPadding and name = "NoPadding" - or - type instanceof OAEP and name = "OAEP" - or - type instanceof OtherPadding and name = this.getRawAlgorithmName() - } - - override string getAlgorithmName() { this.paddingToNameMapping(this.getPaddingType(), result) } - } - - /** - * A helper type for distinguishing between block and stream ciphers. - */ - newtype TCipherStructureType = - Block() or - Stream() or - Asymmetric() or - UnknownCipherStructureType() - - private string getCipherStructureTypeString(TCipherStructureType type) { - type instanceof Block and result = "Block" - or - type instanceof Stream and result = "Stream" - or - type instanceof Asymmetric and result = "Asymmetric" - or - type instanceof UnknownCipherStructureType and result instanceof UnknownPropertyValue - } - - /** - * Symmetric algorithms - */ - newtype TCipherType = - AES() or - Camellia() or - DES() or - TripleDES() or - IDEA() or - CAST5() or - ChaCha20() or - RC4() or - RC5() or - RSA() or - OtherCipherType() - - abstract class CipherAlgorithm extends Algorithm, TCipherAlgorithm { - final LocatableElement getInstance() { this = TCipherAlgorithm(result) } - - final TCipherStructureType getCipherStructure() { - this.cipherFamilyToNameAndStructure(this.getCipherFamily(), _, result) - } - - final override string getAlgorithmName() { - this.cipherFamilyToNameAndStructure(this.getCipherFamily(), result, _) - } - - override string getAlgorithmType() { result = "CipherAlgorithm" } - - /** - * Gets the key size of this cipher, e.g., "128" or "256". - */ - abstract string getKeySize(Location location); - - /** - * Gets the type of this cipher, e.g., "AES" or "ChaCha20". - */ - abstract TCipherType getCipherFamily(); - - /** - * Gets the mode of operation of this cipher, e.g., "GCM" or "CBC". - */ - abstract ModeOfOperationAlgorithm getModeOfOperation(); - - /** - * Gets the padding scheme of this cipher, e.g., "PKCS7" or "NoPadding". - */ - abstract PaddingAlgorithm getPadding(); - - bindingset[type] - final private predicate cipherFamilyToNameAndStructure( - TCipherType type, string name, TCipherStructureType s - ) { - type instanceof AES and name = "AES" and s = Block() - or - type instanceof Camellia and name = "Camellia" and s = Block() - or - type instanceof DES and name = "DES" and s = Block() - or - type instanceof TripleDES and name = "TripleDES" and s = Block() - or - type instanceof IDEA and name = "IDEA" and s = Block() - or - type instanceof CAST5 and name = "CAST5" and s = Block() - or - type instanceof ChaCha20 and name = "ChaCha20" and s = Stream() - or - type instanceof RC4 and name = "RC4" and s = Stream() - or - type instanceof RC5 and name = "RC5" and s = Block() - or - type instanceof RSA and name = "RSA" and s = Asymmetric() - or - type instanceof OtherCipherType and - name = this.getRawAlgorithmName() and - s = UnknownCipherStructureType() - } - - //mode, padding scheme, keysize, block/stream, auth'd - //nodes = mode, padding scheme - //properties = keysize, block/stream, auth'd - //leave authd to lang specific - override NodeBase getChild(string edgeName) { - result = super.getChild(edgeName) - or - // [KNOWN_OR_UNKNOWN] - edgeName = "Mode" and - if exists(this.getModeOfOperation()) - then result = this.getModeOfOperation() - else result = this - or - // [KNOWN_OR_UNKNOWN] - edgeName = "Padding" and - if exists(this.getPadding()) then result = this.getPadding() else result = this - } - - override predicate properties(string key, string value, Location location) { - super.properties(key, value, location) - or - // [ALWAYS_KNOWN] - unknown case is handled in `getCipherStructureTypeString` - key = "Structure" and - getCipherStructureTypeString(this.getCipherStructure()) = value and - location instanceof UnknownLocation - or - ( - // [KNOWN_OR_UNKNOWN] - key = "KeySize" and - if exists(this.getKeySize(location)) - then value = this.getKeySize(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - ) - } - } - - abstract class KEMAlgorithm extends TKeyEncapsulationAlgorithm, Algorithm { - final override string getAlgorithmType() { result = "KeyEncapsulationAlgorithm" } + abstract class KEMAlgorithm extends TKeyEncapsulationAlgorithm, AlgorithmNode { + final override string getInternalType() { result = "KeyEncapsulationAlgorithm" } } } From ef0614ad45d451e6f4982279230e5ba25fc050de Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 27 Feb 2025 05:45:27 +0100 Subject: [PATCH 032/336] Restore removed node location output --- shared/cryptography/codeql/cryptography/Model.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 5889e9eb5e28..2006804952a8 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -58,7 +58,7 @@ module CryptographyBase Input> { or // CodeQL's DGML output does not include a location key = "Location" and - value = "" // node.getLocation().toString() + value = node.getLocation().toString() or // Known unknown edges should be reported as properties rather than edges node = node.getChild(key) and From 0354afc365a8db1fa22b917f358d32bfa047bb24 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 27 Feb 2025 15:54:38 +0100 Subject: [PATCH 033/336] Make ArtifactConsumers instances of some Artifacts TODO: refactor the interfaces --- java/ql/lib/experimental/Quantum/JCA.qll | 50 ++++++++----------- java/ql/lib/experimental/Quantum/Language.qll | 39 ++++++++++++++- .../codeql/cryptography/Model.qll | 19 +++---- 3 files changed, 68 insertions(+), 40 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index f1e1ce9ccdc3..4370d34ca28a 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -346,7 +346,7 @@ module JCAModel { override Crypto::CipherOperationSubtype getCipherOperationSubtype() { result = mode } - override Crypto::ArtifactConsumer getNonceConsumer() { + override Crypto::NonceArtifactConsumer getNonceConsumer() { result = sink.getState().(InitializedCipherModeFlowState).getInitCall().getNonceArg() } @@ -360,9 +360,10 @@ module JCAModel { /** * Initialization vectors and other nonce artifacts */ - abstract class NonceParameterInstantiation extends NonceArtifactInstance instanceof ClassInstanceExpr - { - override DataFlow::Node getOutputNode() { result.asExpr() = this } + abstract class NonceParameterInstantiation extends ClassInstanceExpr { + DataFlow::Node getOutputNode() { result.asExpr() = this } + + abstract DataFlow::Node getInputNode(); } class IvParameterSpecInstance extends NonceParameterInstantiation { @@ -396,32 +397,25 @@ module JCAModel { } } - module NonceArtifactToCipherInitCallConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { - exists(NonceParameterInstantiation n | - src = n.getOutputNode() and - not exists(IvParameterSpecGetIvCall m | n.getInputNode().asExpr() = m) - ) - } + predicate additionalFlowSteps(DataFlow::Node node1, DataFlow::Node node2) { + exists(IvParameterSpecGetIvCall m | + node1.asExpr() = m.getQualifier() and + node2.asExpr() = m + ) + or + exists(NonceParameterInstantiation n | + node1 = n.getInputNode() and + node2 = n.getOutputNode() + ) + } - predicate isSink(DataFlow::Node sink) { - exists(CipherInitCall c | c.getNonceArg() = sink.asExpr()) - } + class NonceAdditionalFlowInputStep extends AdditionalFlowInputStep { + DataFlow::Node output; - predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - exists(IvParameterSpecGetIvCall m | - node1.asExpr() = m.getQualifier() and - node2.asExpr() = m - ) - or - exists(NonceParameterInstantiation n | - node1 = n.getInputNode() and - node2.asExpr() = n - ) - } - } + NonceAdditionalFlowInputStep() { additionalFlowSteps(this, output) } - module NonceArtifactToCipherInitCallFlow = DataFlow::Global; + override DataFlow::Node getOutput() { result = output } + } /** * A data-flow configuration to track flow from a mode field access to @@ -487,7 +481,7 @@ module JCAModel { } } - class CipherInitCallNonceArgConsumer extends Crypto::ArtifactConsumer instanceof Expr { + class CipherInitCallNonceArgConsumer extends Crypto::NonceArtifactConsumer instanceof Expr { CipherInitCallNonceArgConsumer() { this = any(CipherInitCall call).getNonceArg() } override DataFlow::Node getInputNode() { result.asExpr() = this } diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 228f21bd69bf..a2945bb6dd38 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -65,6 +65,19 @@ class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { override string getAdditionalDescription() { result = this.toString() } } +class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource instanceof Literal { + override DataFlow::Node getOutputNode() { result.asExpr() = this } + + override predicate flowsTo(Crypto::FlowAwareElement other) { + other instanceof NonceArtifactInstance and + // limit to only nonces for now + // TODO: separate config to avoid blowing up data-flow analysis + GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) + } + + override string getAdditionalDescription() { result = this.toString() } +} + /** * Random number generation, where each instance is modelled as the expression * tied to an output node (i.e., the result of the source of randomness) @@ -94,6 +107,12 @@ class InsecureRandomnessInstance extends RandomnessInstance { /** * Artifact output to node input configuration */ +abstract class AdditionalFlowInputStep extends DataFlow::Node { + abstract DataFlow::Node getOutput(); + + final DataFlow::Node getInput() { result = this } +} + module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source = any(Crypto::ArtifactElement artifact).getOutputNode() @@ -106,14 +125,28 @@ module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { predicate isBarrierIn(DataFlow::Node node) { node = any(Crypto::FlowAwareElement element).getOutputNode() } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + node1.(AdditionalFlowInputStep).getOutput() = node2 + } } module ArtifactUniversalFlow = DataFlow::Global; -abstract class NonceArtifactInstance extends Crypto::NonceArtifactInstance { +class NonceArtifactInstance extends Crypto::NonceArtifactInstance { + NonceArtifactInstance() { this instanceof Crypto::NonceArtifactConsumer } + override predicate flowsTo(Crypto::FlowAwareElement other) { ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) } + + override DataFlow::Node getOutputNode() { + result = this.(Crypto::NonceArtifactConsumer).getOutputNode() + } + + override DataFlow::Node getInputNode() { + result = this.(Crypto::NonceArtifactConsumer).getInputNode() + } } /** @@ -131,6 +164,10 @@ module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { predicate isBarrierIn(DataFlow::Node node) { node = any(Crypto::FlowAwareElement element).getOutputNode() } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + node1.(AdditionalFlowInputStep).getOutput() = node2 + } } module GenericDataSourceUniversalFlow = DataFlow::Global; diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 2006804952a8..8799bbef572a 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -205,12 +205,16 @@ module CryptographyBase Input> { abstract AlgorithmElement getAKnownAlgorithmSource(); } - abstract class ArtifactConsumer extends ConsumerElement { + abstract class ArtifactConsumer extends ConsumerElement, ArtifactElement { final override KnownElement getAKnownSource() { result = this.getAKnownArtifactSource() } final ArtifactElement getAKnownArtifactSource() { result.flowsTo(this) } } + abstract class NonceArtifactConsumer extends ArtifactConsumer { + NonceArtifactInstance asNonce() { result = this } + } + abstract class CipherOperationInstance extends OperationElement { /** * Gets the subtype of this cipher operation, distinguishing encryption, decryption, key wrapping, and key unwrapping. @@ -220,7 +224,7 @@ module CryptographyBase Input> { /** * Gets the consumer of nonces/IVs associated with this cipher operation. */ - abstract ArtifactConsumer getNonceConsumer(); + abstract NonceArtifactConsumer getNonceConsumer(); /** * Gets the consumer of plaintext or ciphertext input associated with this cipher operation. @@ -586,13 +590,8 @@ module CryptographyBase Input> { result = instance.getCipherOperationSubtype() } - NodeBase getANonceOrUnknown() { - result = - this.asElement().(CipherOperationInstance).getNonceConsumer().getAKnownOrUnknownSourceNode() - } - NonceNode getANonce() { - result = this.asElement().(CipherOperationInstance).getNonceConsumer().getAKnownSourceNode() + result.asElement() = this.asElement().(CipherOperationInstance).getNonceConsumer().asNonce() } NodeBase getAMessageOrUnknown() { @@ -614,9 +613,7 @@ module CryptographyBase Input> { or // [KNOWN_OR_UNKNOWN] key = "Nonce" and - if exists(this.getANonceOrUnknown()) - then result = this.getANonceOrUnknown() - else result = this + if exists(this.getANonce()) then result = this.getANonce() else result = this or // [KNOWN_OR_UNKNOWN] key = "Message" and From cf33cf7653c0d8d902a0537bf098ad26eeb08458 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Fri, 28 Feb 2025 15:21:46 +0100 Subject: [PATCH 034/336] Add input and output nodes and fix cross product --- java/ql/lib/experimental/Quantum/JCA.qll | 42 +++-- java/ql/lib/experimental/Quantum/Language.qll | 68 +++++--- .../codeql/cryptography/Model.qll | 145 ++++++++++++++---- 3 files changed, 193 insertions(+), 62 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 4370d34ca28a..8d748772bffc 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -59,14 +59,22 @@ module JCAModel { Expr getProviderArg() { result = this.getArgument(1) } } - private class JCACipherOperationCall extends Call { - JCACipherOperationCall() { + private class CipherOperationCall extends MethodCall { + CipherOperationCall() { exists(string s | s in ["doFinal", "wrap", "unwrap"] | - this.getCallee().hasQualifiedName("javax.crypto", "Cipher", s) + this.getMethod().hasQualifiedName("javax.crypto", "Cipher", s) ) } - DataFlow::Node getMessageArg() { result.asExpr() = this.getArgument(0) } + Expr getInput() { result = this.getArgument(0) } + + Expr getOutput() { + result = this.getArgument(3) + or + this.getMethod().getReturnType().hasName("byte[]") and result = this + } + + DataFlow::Node getMessageArg() { result.asExpr() = this.getInput() } } /** @@ -304,7 +312,7 @@ module JCAModel { predicate isSink(DataFlow::Node sink, FlowState state) { none() } predicate isSink(DataFlow::Node sink) { - exists(JCACipherOperationCall c | c.getQualifier() = sink.asExpr()) + exists(CipherOperationCall c | c.getQualifier() = sink.asExpr()) } predicate isAdditionalFlowStep( @@ -330,7 +338,7 @@ module JCAModel { class CipherOperationInstance extends Crypto::CipherOperationInstance instanceof Call { Crypto::CipherOperationSubtype mode; CipherGetInstanceToCipherOperationFlow::PathNode sink; - JCACipherOperationCall doFinalize; + CipherOperationCall doFinalize; CipherGetInstanceAlgorithmArg consumer; CipherOperationInstance() { @@ -350,11 +358,15 @@ module JCAModel { result = sink.getState().(InitializedCipherModeFlowState).getInitCall().getNonceArg() } - override Crypto::ArtifactConsumer getMessageConsumer() { + override Crypto::CipherInputConsumer getInputConsumer() { result = doFinalize.getMessageArg().asExpr() } override Crypto::AlgorithmConsumer getAlgorithmConsumer() { result = consumer } + + override Crypto::CipherOutputArtifactInstance getOutputArtifact() { + result = doFinalize.getOutput() + } } /** @@ -481,15 +493,27 @@ module JCAModel { } } - class CipherInitCallNonceArgConsumer extends Crypto::NonceArtifactConsumer instanceof Expr { + class CipherInitCallNonceArgConsumer extends NonceArtifactConsumer instanceof Expr { CipherInitCallNonceArgConsumer() { this = any(CipherInitCall call).getNonceArg() } override DataFlow::Node getInputNode() { result.asExpr() = this } } - class CipherInitCallKeyConsumer extends Crypto::ArtifactConsumer instanceof Expr { + class CipherInitCallKeyConsumer extends Crypto::ArtifactConsumer { CipherInitCallKeyConsumer() { this = any(CipherInitCall call).getKeyArg() } override DataFlow::Node getInputNode() { result.asExpr() = this } } + + class CipherMessageInputConsumer extends Crypto::CipherInputConsumer { + CipherMessageInputConsumer() { this = any(CipherOperationCall call).getMessageArg().asExpr() } + + override DataFlow::Node getInputNode() { result.asExpr() = this } + } + + class CipherOperationCallOutput extends CipherOutputArtifact { + CipherOperationCallOutput() { this = any(CipherOperationCall call).getOutput() } + + override DataFlow::Node getOutputNode() { result.asExpr() = this } + } } diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index a2945bb6dd38..03c351005380 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -69,8 +69,6 @@ class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource insta override DataFlow::Node getOutputNode() { result.asExpr() = this } override predicate flowsTo(Crypto::FlowAwareElement other) { - other instanceof NonceArtifactInstance and - // limit to only nonces for now // TODO: separate config to avoid blowing up data-flow analysis GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) } @@ -113,40 +111,42 @@ abstract class AdditionalFlowInputStep extends DataFlow::Node { final DataFlow::Node getInput() { result = this } } -module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { - source = any(Crypto::ArtifactElement artifact).getOutputNode() - } +module ArtifactUniversalFlow = DataFlow::Global; - predicate isSink(DataFlow::Node sink) { - sink = any(Crypto::FlowAwareElement other).getInputNode() +class NonceArtifactConsumer extends Crypto::NonceArtifactInstance instanceof Crypto::NonceArtifactConsumer +{ + override predicate flowsTo(Crypto::FlowAwareElement other) { + ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) } - predicate isBarrierIn(DataFlow::Node node) { - node = any(Crypto::FlowAwareElement element).getOutputNode() + override DataFlow::Node getOutputNode() { + result = this.(Crypto::NonceArtifactConsumer).getOutputNode() } - predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - node1.(AdditionalFlowInputStep).getOutput() = node2 + override DataFlow::Node getInputNode() { + result = this.(Crypto::NonceArtifactConsumer).getInputNode() } } -module ArtifactUniversalFlow = DataFlow::Global; - -class NonceArtifactInstance extends Crypto::NonceArtifactInstance { - NonceArtifactInstance() { this instanceof Crypto::NonceArtifactConsumer } - +class CipherInputConsumer extends Crypto::CipherInputArtifactInstance instanceof Crypto::CipherInputConsumer +{ override predicate flowsTo(Crypto::FlowAwareElement other) { ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) } - override DataFlow::Node getOutputNode() { - result = this.(Crypto::NonceArtifactConsumer).getOutputNode() - } + override DataFlow::Node getOutputNode() { none() } override DataFlow::Node getInputNode() { - result = this.(Crypto::NonceArtifactConsumer).getInputNode() + result = this.(Crypto::CipherInputArtifactInstance).getInputNode() + } +} + +abstract class CipherOutputArtifact extends Crypto::CipherOutputArtifactInstance { + override predicate flowsTo(Crypto::FlowAwareElement other) { + ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) } + + override DataFlow::Node getInputNode() { none() } } /** @@ -161,6 +161,32 @@ module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { sink = any(Crypto::FlowAwareElement other).getInputNode() } + predicate isBarrierOut(DataFlow::Node node) { + node = any(Crypto::FlowAwareElement element).getInputNode() + } + + predicate isBarrierIn(DataFlow::Node node) { + node = any(Crypto::FlowAwareElement element).getOutputNode() + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + node1.(AdditionalFlowInputStep).getOutput() = node2 + } +} + +module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source = any(Crypto::ArtifactElement artifact).getOutputNode() + } + + predicate isSink(DataFlow::Node sink) { + sink = any(Crypto::FlowAwareElement other).getInputNode() + } + + predicate isBarrierOut(DataFlow::Node node) { + node = any(Crypto::FlowAwareElement element).getInputNode() + } + predicate isBarrierIn(DataFlow::Node node) { node = any(Crypto::FlowAwareElement element).getOutputNode() } diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 8799bbef572a..83111519a006 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -46,12 +46,7 @@ module CryptographyBase Input> { } predicate nodes_graph_impl(NodeBase node, string key, string value) { - not ( - // exclude certain Artifact nodes with no edges to or from them - node instanceof RandomNumberGenerationNode and - // TODO: performance? - not (edges_graph_impl(node, _, _, _) or edges_graph_impl(_, node, _, _)) - ) and + not node.isExcludedFromGraph() and ( key = "semmle.label" and value = node.toString() @@ -106,6 +101,9 @@ module CryptographyBase Input> { /** * An element that represents a _known_ cryptographic asset. + * + * CROSS PRODUCT WARNING: Do not model any *other* element that is a `FlowAwareElement` to the same + * instance in the database, as every other `KnownElement` will share that output artifact's flow. */ abstract class KnownElement extends LocatableElement { final ConsumerElement getAConsumer() { result.getAKnownSource() = this } @@ -167,25 +165,21 @@ module CryptographyBase Input> { * A consumer can consume multiple instances and types of assets at once, e.g., both a `PaddingAlgorithm` and `CipherAlgorithm`. */ abstract private class ConsumerElement extends FlowAwareElement { + abstract KnownElement getAKnownSource(); + override predicate flowsTo(FlowAwareElement other) { none() } override DataFlowNode getOutputNode() { none() } - GenericDataSourceInstance getAnUnknownSource() { result.flowsTo(this) } - - GenericSourceNode getAnUnknownSourceNode() { result.asElement() = this.getAnUnknownSource() } - - abstract KnownElement getAKnownSource(); - - final NodeBase getAKnownSourceNode() { result.asElement() = this.getAKnownSource() } + final GenericDataSourceInstance getAnUnknownSource() { + result.flowsTo(this) and not result = this.getAKnownSource() + } - final LocatableElement getAKnownOrUnknownSource() { - result = this.getAKnownSource() - or - result = this.getAnUnknownSource() + final GenericSourceNode getAnUnknownSourceNode() { + result.asElement() = this.getAnUnknownSource() } - NodeBase getAKnownOrUnknownSourceNode() { result.asElement() = this.getAKnownOrUnknownSource() } + final NodeBase getAKnownSourceNode() { result.asElement() = this.getAKnownSource() } } /** @@ -205,16 +199,47 @@ module CryptographyBase Input> { abstract AlgorithmElement getAKnownAlgorithmSource(); } - abstract class ArtifactConsumer extends ConsumerElement, ArtifactElement { + /** + * An `ArtifactConsumer` represents an element in code that consumes an artifact. + * + * The concept of "`ArtifactConsumer` = `ArtifactNode`" should be used for inputs, as a consumer can be directly tied + * to the artifact it receives, thereby becoming the definitive contextual source for that artifact. + * + * For example, consider a nonce artifact consumer: + * + * A `NonceArtifactConsumer` is always the `NonceArtifactInstance` itself, since data only becomes (i.e., is determined to be) + * a `NonceArtifactInstance` when it is consumed in a context that expects a nonce (e.g., an argument expecting nonce data). + * In this case, the artifact (nonce) is fully defined by the context in which it is consumed, and the consumer embodies + * that identity without the need for additional differentiation. Without the context a consumer provides, that data could + * otherwise be any other type of artifact or even simply random data. + * + * + * Architectural Implications: + * * By directly coupling a consumer with the node that receives an artifact, + * the data flow is fully transparent with the consumer itself serving only as a transparent node. + * * An artifact's properties (such as being a nonce) are not necessarily inherent; they are determined by the context in which the artifact is consumed. + * The consumer node is therefore essential in defining these properties for inputs. + * * This approach reduces ambiguity by avoiding separate notions of "artifact source" and "consumer", as the node itself encapsulates both roles. + * * Instances of nodes do not necessarily have to come from a consumer, allowing additional modelling of an artifact to occur outside of the consumer. + */ + abstract class ArtifactConsumer extends ConsumerElement { final override KnownElement getAKnownSource() { result = this.getAKnownArtifactSource() } final ArtifactElement getAKnownArtifactSource() { result.flowsTo(this) } } - abstract class NonceArtifactConsumer extends ArtifactConsumer { + abstract class NonceArtifactConsumer extends ArtifactConsumer, NonceArtifactInstance { NonceArtifactInstance asNonce() { result = this } } + abstract class CipherInputArtifactInstance extends ArtifactElement { } + + abstract class CipherInputConsumer extends ArtifactConsumer, CipherInputArtifactInstance { + CipherInputArtifactInstance asCipherInput() { result = this } + } + + abstract class CipherOutputArtifactInstance extends ArtifactElement { } + abstract class CipherOperationInstance extends OperationElement { /** * Gets the subtype of this cipher operation, distinguishing encryption, decryption, key wrapping, and key unwrapping. @@ -229,7 +254,16 @@ module CryptographyBase Input> { /** * Gets the consumer of plaintext or ciphertext input associated with this cipher operation. */ - abstract ArtifactConsumer getMessageConsumer(); + abstract CipherInputConsumer getInputConsumer(); + + /** + * Gets the output artifact of this cipher operation. + * + * Implementation guidelines: + * 1. Each unique output target should have an artifact. + * 1. Discarded outputs from intermittent calls should not be artifacts. + */ + abstract CipherOutputArtifactInstance getOutputArtifact(); } abstract class CipherAlgorithmInstance extends AlgorithmElement { @@ -325,6 +359,8 @@ module CryptographyBase Input> { TDigest(DigestArtifactInstance e) or TKey(KeyArtifactInstance e) or TNonce(NonceArtifactInstance e) or + TCipherInput(CipherInputArtifactInstance e) or + TCipherOutput(CipherOutputArtifactInstance e) or TRandomNumberGeneration(RandomNumberGenerationInstance e) { e.flowsTo(_) } or // Operations (e.g., hashing, encryption) THashOperation(HashOperationInstance e) or @@ -413,6 +449,11 @@ module CryptographyBase Input> { * Gets the element associated with this node. */ abstract LocatableElement asElement(); + + /** + * If this predicate holds, this node should be excluded from the graph. + */ + predicate isExcludedFromGraph() { none() } } /** @@ -435,6 +476,10 @@ module CryptographyBase Input> { value = instance.getAdditionalDescription() and location = this.getLocation() } + + override predicate isExcludedFromGraph() { + not exists(NodeBase other | not other = this and other.getChild(_) = this) + } } class AssetNode = NodeBase; @@ -444,9 +489,12 @@ module CryptographyBase Input> { */ abstract class ArtifactNode extends NodeBase { /** - * Gets the `Artifact` node that is the data source for this artifact. + * Gets the `ArtifactNode` or `GenericSourceNode` node that is the data source for this artifact. */ - final NodeBase getSourceNode() { result.asElement() = this.getSourceElement() } + final NodeBase getSourceNode() { + result.asElement() = this.getSourceElement() and + (result instanceof ArtifactNode or result instanceof GenericSourceNode) + } /** * Gets the `ArtifactLocatableElement` that is the data source for this artifact. @@ -486,6 +534,32 @@ module CryptographyBase Input> { override LocatableElement asElement() { result = instance } } + /** + * Output text from a cipher operation + */ + final class CipherOutputNode extends ArtifactNode, TCipherOutput { + CipherOutputArtifactInstance instance; + + CipherOutputNode() { this = TCipherOutput(instance) } + + final override string getInternalType() { result = "CipherOutput" } + + override LocatableElement asElement() { result = instance } + } + + /** + * Input text to a cipher operation + */ + final class CipherMessageNode extends ArtifactNode, TCipherInput { + CipherInputArtifactInstance instance; + + CipherMessageNode() { this = TCipherInput(instance) } + + final override string getInternalType() { result = "CipherMessage" } + + override LocatableElement asElement() { result = instance } + } + /** * A source of random number generation */ @@ -594,12 +668,13 @@ module CryptographyBase Input> { result.asElement() = this.asElement().(CipherOperationInstance).getNonceConsumer().asNonce() } - NodeBase getAMessageOrUnknown() { - result = - this.asElement() - .(CipherOperationInstance) - .getMessageConsumer() - .getAKnownOrUnknownSourceNode() + CipherMessageNode getAnInputArtifact() { + result.asElement() = + this.asElement().(CipherOperationInstance).getInputConsumer().asCipherInput() + } + + CipherOutputNode getAnOutputArtifact() { + result.asElement() = this.asElement().(CipherOperationInstance).getOutputArtifact() } override NodeBase getChild(string key) { @@ -616,9 +691,15 @@ module CryptographyBase Input> { if exists(this.getANonce()) then result = this.getANonce() else result = this or // [KNOWN_OR_UNKNOWN] - key = "Message" and - if exists(this.getAMessageOrUnknown()) - then result = this.getAMessageOrUnknown() + key = "InputText" and + if exists(this.getAnInputArtifact()) + then result = this.getAnInputArtifact() + else result = this + or + // [KNOWN_OR_UNKNOWN] + key = "OutputText" and + if exists(this.getAnOutputArtifact()) + then result = this.getAnOutputArtifact() else result = this } From 627790f98b1a0ebb0a724ee9f23b673276d1d04e Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Mon, 3 Mar 2025 19:06:53 +0100 Subject: [PATCH 035/336] Clean up consumer and instance interfaces --- java/ql/lib/experimental/Quantum/JCA.qll | 2 +- java/ql/lib/experimental/Quantum/Language.qll | 32 -------- .../codeql/cryptography/Model.qll | 82 +++++++++++++------ 3 files changed, 57 insertions(+), 59 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 8d748772bffc..5cb7bcf23dcb 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -493,7 +493,7 @@ module JCAModel { } } - class CipherInitCallNonceArgConsumer extends NonceArtifactConsumer instanceof Expr { + class CipherInitCallNonceArgConsumer extends Crypto::NonceArtifactConsumer instanceof Expr { CipherInitCallNonceArgConsumer() { this = any(CipherInitCall call).getNonceArg() } override DataFlow::Node getInputNode() { result.asExpr() = this } diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 03c351005380..0e875295bd8a 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -83,8 +83,6 @@ class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource insta abstract class RandomnessInstance extends Crypto::RandomNumberGenerationInstance { override DataFlow::Node getOutputNode() { result.asExpr() = this } - override DataFlow::Node getInputNode() { none() } // TODO: add seed - override predicate flowsTo(Crypto::FlowAwareElement other) { ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) } @@ -113,40 +111,10 @@ abstract class AdditionalFlowInputStep extends DataFlow::Node { module ArtifactUniversalFlow = DataFlow::Global; -class NonceArtifactConsumer extends Crypto::NonceArtifactInstance instanceof Crypto::NonceArtifactConsumer -{ - override predicate flowsTo(Crypto::FlowAwareElement other) { - ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) - } - - override DataFlow::Node getOutputNode() { - result = this.(Crypto::NonceArtifactConsumer).getOutputNode() - } - - override DataFlow::Node getInputNode() { - result = this.(Crypto::NonceArtifactConsumer).getInputNode() - } -} - -class CipherInputConsumer extends Crypto::CipherInputArtifactInstance instanceof Crypto::CipherInputConsumer -{ - override predicate flowsTo(Crypto::FlowAwareElement other) { - ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) - } - - override DataFlow::Node getOutputNode() { none() } - - override DataFlow::Node getInputNode() { - result = this.(Crypto::CipherInputArtifactInstance).getInputNode() - } -} - abstract class CipherOutputArtifact extends Crypto::CipherOutputArtifactInstance { override predicate flowsTo(Crypto::FlowAwareElement other) { ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) } - - override DataFlow::Node getInputNode() { none() } } /** diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 83111519a006..243d52cd2e67 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -45,15 +45,26 @@ module CryptographyBase Input> { ) } + NodeBase getPassthroughNodeChild(NodeBase node) { + result = node.(CipherInputNode).getChild(_) or + result = node.(NonceNode).getChild(_) + } + + predicate isPassthroughNode(NodeBase node) { + node instanceof CipherInputNode or + node instanceof NonceNode + } + predicate nodes_graph_impl(NodeBase node, string key, string value) { not node.isExcludedFromGraph() and + not isPassthroughNode(node) and ( key = "semmle.label" and value = node.toString() or // CodeQL's DGML output does not include a location key = "Location" and - value = node.getLocation().toString() + value = "" // node.getLocation().toString() or // Known unknown edges should be reported as properties rather than edges node = node.getChild(key) and @@ -66,7 +77,14 @@ module CryptographyBase Input> { predicate edges_graph_impl(NodeBase source, NodeBase target, string key, string value) { key = "semmle.label" and - target = source.getChild(value) and + exists(NodeBase directTarget | + directTarget = source.getChild(value) and + // [NodeA] ---Input--> [Passthrough] ---Source---> [NodeB] + // should get reported as [NodeA] ---Input--> [NodeB] + if isPassthroughNode(directTarget) + then target = getPassthroughNodeChild(directTarget) + else target = directTarget + ) and // Known unknowns are reported as properties rather than edges not source = target } @@ -223,22 +241,23 @@ module CryptographyBase Input> { * * Instances of nodes do not necessarily have to come from a consumer, allowing additional modelling of an artifact to occur outside of the consumer. */ abstract class ArtifactConsumer extends ConsumerElement { + /** + * Use `getAKnownArtifactSource() instead. The behaviour of these two predicates is equivalent. + */ final override KnownElement getAKnownSource() { result = this.getAKnownArtifactSource() } final ArtifactElement getAKnownArtifactSource() { result.flowsTo(this) } } - abstract class NonceArtifactConsumer extends ArtifactConsumer, NonceArtifactInstance { - NonceArtifactInstance asNonce() { result = this } - } - - abstract class CipherInputArtifactInstance extends ArtifactElement { } + abstract class ArtifactConsumerAndInstance extends ArtifactConsumer { + final override DataFlowNode getOutputNode() { none() } - abstract class CipherInputConsumer extends ArtifactConsumer, CipherInputArtifactInstance { - CipherInputArtifactInstance asCipherInput() { result = this } + final override predicate flowsTo(FlowAwareElement other) { none() } } - abstract class CipherOutputArtifactInstance extends ArtifactElement { } + abstract class CipherOutputArtifactInstance extends ArtifactElement { + final override DataFlowNode getInputNode() { none() } + } abstract class CipherOperationInstance extends OperationElement { /** @@ -345,21 +364,33 @@ module CryptographyBase Input> { abstract class KeyDerivationAlgorithmInstance extends KnownElement { } - // Artifacts - abstract class DigestArtifactInstance extends ArtifactElement { } + // Artifacts determined solely by the element that produces them + // Implementation guidance: these *do* need to be defined generically at the language-level + // in order for a flowsTo to be defined. At the per-modeling-instance level, extend that language-level class! + abstract class OutputArtifactElement extends ArtifactElement { + final override DataFlowNode getInputNode() { none() } + } + + abstract class DigestArtifactInstance extends OutputArtifactElement { } + + abstract class RandomNumberGenerationInstance extends OutputArtifactElement { } // TODO: is this an OutputArtifactElement if it takes a seed? - abstract class KeyArtifactInstance extends ArtifactElement { } + // Artifacts determined solely by the consumer that consumes them are defined as consumers + // Implementation guidance: these do not need to be defined generically at the language-level + // Only the sink node needs to be defined per-modeling-instance (e.g., in JCA.qll) + abstract class NonceArtifactConsumer extends ArtifactConsumerAndInstance { } - abstract class NonceArtifactInstance extends ArtifactElement { } + abstract class CipherInputConsumer extends ArtifactConsumerAndInstance { } - abstract class RandomNumberGenerationInstance extends ArtifactElement { } + // Other artifacts + abstract class KeyArtifactInstance extends ArtifactElement { } // TODO: implement and categorize newtype TNode = // Artifacts (data that is not an operation or algorithm, e.g., a key) TDigest(DigestArtifactInstance e) or TKey(KeyArtifactInstance e) or - TNonce(NonceArtifactInstance e) or - TCipherInput(CipherInputArtifactInstance e) or + TNonce(NonceArtifactConsumer e) or + TCipherInput(CipherInputConsumer e) or TCipherOutput(CipherOutputArtifactInstance e) or TRandomNumberGeneration(RandomNumberGenerationInstance e) { e.flowsTo(_) } or // Operations (e.g., hashing, encryption) @@ -525,7 +556,7 @@ module CryptographyBase Input> { * A nonce or initialization vector */ final class NonceNode extends ArtifactNode, TNonce { - NonceArtifactInstance instance; + NonceArtifactConsumer instance; NonceNode() { this = TNonce(instance) } @@ -550,12 +581,12 @@ module CryptographyBase Input> { /** * Input text to a cipher operation */ - final class CipherMessageNode extends ArtifactNode, TCipherInput { - CipherInputArtifactInstance instance; + final class CipherInputNode extends ArtifactNode, TCipherInput { + CipherInputConsumer instance; - CipherMessageNode() { this = TCipherInput(instance) } + CipherInputNode() { this = TCipherInput(instance) } - final override string getInternalType() { result = "CipherMessage" } + final override string getInternalType() { result = "CipherInput" } override LocatableElement asElement() { result = instance } } @@ -665,12 +696,11 @@ module CryptographyBase Input> { } NonceNode getANonce() { - result.asElement() = this.asElement().(CipherOperationInstance).getNonceConsumer().asNonce() + result.asElement() = this.asElement().(CipherOperationInstance).getNonceConsumer() } - CipherMessageNode getAnInputArtifact() { - result.asElement() = - this.asElement().(CipherOperationInstance).getInputConsumer().asCipherInput() + CipherInputNode getAnInputArtifact() { + result.asElement() = this.asElement().(CipherOperationInstance).getInputConsumer() } CipherOutputNode getAnOutputArtifact() { From 076f53147dc7d1598ad6d9bea6bbfe9332e317fc Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 3 Mar 2025 13:53:16 -0500 Subject: [PATCH 036/336] Proof-of-concept query for InsecureOrUnknownNonceAtOperation --- .../InsecureOrUnknownNonceAtOperation.ql | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql diff --git a/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql b/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql new file mode 100644 index 000000000000..ba43413d281f --- /dev/null +++ b/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql @@ -0,0 +1,76 @@ +/** + * @name Insecure or unknown nonce source at a cipher operation + * @id java/insecure-or-unknown-nonce-at-operation + * @kind problem + */ + +import experimental.Quantum.Language + + +from Crypto::NonceNode n, Crypto::CipherOperationNode op, Crypto::FlowAwareElement src, string msg +where + op.getANonce() = n and + ( + // Known sources cases that are not secure + src = n.getSourceElement() and + not src instanceof SecureRandomnessInstance and + msg = "Operation uses insecure nonce source $@" + + or + // Totally unknown sources (unmodeled input sources) + not exists(n.getSourceElement()) and msg = "Operation uses unknown nonce source" and src = n.asElement() + ) +select n, msg, src, src.toString() + + +// variant using instances, does not yield the same results +// from Crypto::NonceArtifactConsumer n, Crypto::CipherOperationInstance op, Crypto::FlowAwareElement src, string msg +// where +// op.getNonceConsumer() = n and +// ( +// // Known sources cases that are not secure +// src = n.getAKnownArtifactSource()and +// not src instanceof SecureRandomnessInstance and +// msg = "Operation uses insecure nonce source $@" + +// or +// // Totally unknown sources (unmodeled input sources) +// // When this occurs set src to n, just to bind it, but the output message will not report any source +// not exists(n.getAKnownArtifactSource()) and msg = "Operation uses unknown nonce source" and src = n +// ) +// select n, msg, src, src.toString() + + + + + + + + + + + + + +// NOTE: this will find all unknowns too, constants, and allocations, without needing to model them +// which is kinda nice, but accidental, since getSourceElement is not modeled for everything +// If users want to find constants or unallocated, they need to model those sources, and output the +// getSourceElement +// QUESTION: why isn't the source element a node? +// NOTE: when not all sources are modeled, if one source is secure, even if others do exist, you +// will see the nonce and operation are secure, regardless of potentially insecure IV sources +// resulting in False Negatives +// NOTE: need to have a query where the op has no Nonce + +// // Ideal query +// from Crypto::NonceNode n, Crypto::CipherOperationNode op +// where +// n = op.getANonce() and +// // n = op.getAnUnknownNonce() +// not n.asElement() instanceof SecureRandomSource +// select op, "Operation uses insecure nonce source @", n, n.toString() +// from Crypto::Nonce n, Crypto::ArtifactLocatableElement nonceSrc +// where +// n.() = nonceSrc and +// not nonceSrc instanceof SecureRandomnessInstance +// select n, nonceSrc From 14cb2bb12f879e12a0b4b99f77e8d0a78808f3a7 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 3 Mar 2025 14:42:50 -0500 Subject: [PATCH 037/336] Updates to insecure or unknown nonce at operation. --- .../InsecureOrUnknownNonceAtOperation.ql | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql b/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql index ba43413d281f..cdeeebd5a7d7 100644 --- a/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql +++ b/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql @@ -6,52 +6,47 @@ import experimental.Quantum.Language - from Crypto::NonceNode n, Crypto::CipherOperationNode op, Crypto::FlowAwareElement src, string msg where op.getANonce() = n and + // Only encryption mode is relevant for insecure nonces, consder any 'unknown' subtype + // as possibly encryption. + ( + op.getCipherOperationSubtype() instanceof Crypto::EncryptionSubtype + or + op.getCipherOperationSubtype() instanceof Crypto::WrapSubtype + or + op.getCipherOperationSubtype() instanceof Crypto::UnwrapSubtype + ) and ( // Known sources cases that are not secure src = n.getSourceElement() and - not src instanceof SecureRandomnessInstance and - msg = "Operation uses insecure nonce source $@" - + not src instanceof SecureRandomnessInstance and + msg = "Operation uses insecure nonce source $@" or // Totally unknown sources (unmodeled input sources) - not exists(n.getSourceElement()) and msg = "Operation uses unknown nonce source" and src = n.asElement() + not exists(n.getSourceElement()) and + msg = "Operation uses unknown nonce source" and + src = n.asElement() ) select n, msg, src, src.toString() - // variant using instances, does not yield the same results // from Crypto::NonceArtifactConsumer n, Crypto::CipherOperationInstance op, Crypto::FlowAwareElement src, string msg // where // op.getNonceConsumer() = n and +// TODO: only perform the query on encryption // ( // // Known sources cases that are not secure // src = n.getAKnownArtifactSource()and // not src instanceof SecureRandomnessInstance and // msg = "Operation uses insecure nonce source $@" - // or // // Totally unknown sources (unmodeled input sources) // // When this occurs set src to n, just to bind it, but the output message will not report any source // not exists(n.getAKnownArtifactSource()) and msg = "Operation uses unknown nonce source" and src = n // ) // select n, msg, src, src.toString() - - - - - - - - - - - - - // NOTE: this will find all unknowns too, constants, and allocations, without needing to model them // which is kinda nice, but accidental, since getSourceElement is not modeled for everything // If users want to find constants or unallocated, they need to model those sources, and output the @@ -61,7 +56,6 @@ select n, msg, src, src.toString() // will see the nonce and operation are secure, regardless of potentially insecure IV sources // resulting in False Negatives // NOTE: need to have a query where the op has no Nonce - // // Ideal query // from Crypto::NonceNode n, Crypto::CipherOperationNode op // where From 2ee16811267268f610c0f47e5e4887fa97b60cad Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 3 Mar 2025 15:09:27 -0500 Subject: [PATCH 038/336] Adding a proof-of-concept PossibleReusedNonce query. --- .../Quantum/PossibleReusedNonce.ql | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 java/ql/src/experimental/Quantum/PossibleReusedNonce.ql diff --git a/java/ql/src/experimental/Quantum/PossibleReusedNonce.ql b/java/ql/src/experimental/Quantum/PossibleReusedNonce.ql new file mode 100644 index 000000000000..fde1ef121786 --- /dev/null +++ b/java/ql/src/experimental/Quantum/PossibleReusedNonce.ql @@ -0,0 +1,35 @@ +/** + * @name Possible Nonce Reuse: Produces false positives if reuse occurs in a source that is a re-entry point. + * @id java/possible-nonce-reuse + */ + +import experimental.Quantum.Language +import semmle.code.java.dataflow.DataFlow + +from + Crypto::CipherOperationNode op1, Crypto::CipherOperationNode op2, Crypto::NonceNode nonce1, + Crypto::NonceNode nonce2, Crypto::FlowAwareElement src1, Crypto::FlowAwareElement src2 +where + // NOTE: not looking at value of the nonce, if we knew value, it would be insecure (hard coded) + // Instead trying to find nonce sources that trace to multiple operations. + // Only looking for encryption operations, presumably if reuse for decryption either wouldn't be observable + // (the encryption happened else where) or we are able to see the encryption and decryption operation and + // reuse for encryption is the concern) + ( + op1.getCipherOperationSubtype() instanceof Crypto::EncryptionSubtype or + op1.getCipherOperationSubtype() instanceof Crypto::WrapSubtype or + op1.getCipherOperationSubtype() instanceof Crypto::UnknownCipherOperationSubtype + ) and + ( + op2.getCipherOperationSubtype() instanceof Crypto::EncryptionSubtype or + op2.getCipherOperationSubtype() instanceof Crypto::WrapSubtype or + op2.getCipherOperationSubtype() instanceof Crypto::UnknownCipherOperationSubtype + ) and + nonce1 = op1.getANonce() and + nonce2 = op2.getANonce() and + op1 != op2 and + nonce1.getSourceElement() = src1 and + nonce2.getSourceElement() = src2 and + src1 = src2 +// TODO: need to clarify that a reuse in a non-finalize is ok, need to check if 'finalize' through a modeled predicate +select op1, "Operation has a possible reused nonce with source $@", src1, src1.toString() From 8865d89fe9c381d78be44e75b3fde1519d3f1868 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 3 Mar 2025 16:51:30 -0500 Subject: [PATCH 039/336] Removing old ReusedNonce query. --- .../src/experimental/Quantum/ReusedNonce.ql | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 java/ql/src/experimental/Quantum/ReusedNonce.ql diff --git a/java/ql/src/experimental/Quantum/ReusedNonce.ql b/java/ql/src/experimental/Quantum/ReusedNonce.ql deleted file mode 100644 index 7847781e0be5..000000000000 --- a/java/ql/src/experimental/Quantum/ReusedNonce.ql +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @name Unsafe nonce source or reuse - * @id java/unsafe-nonce-source-or-reuse - */ - -import experimental.Quantum.Language -import semmle.code.java.dataflow.DataFlow - -Crypto::NodeBase getNonceOrigin(Crypto::NonceNode nonce) { - // TODO: this check is currently ultra hacky just for demoing - result = nonce.getSourceNode() -} - -from Crypto::CipherOperationNode op, Crypto::NonceNode nonce1, Crypto::NonceNode nonce2 -where - op.asElement().(Expr).getEnclosingCallable().getName() = "encrypt" and - nonce1 = op.getANonce() and - nonce2 = op.getANonce() and - not nonce1 = nonce2 and - getNonceOrigin(nonce1) = getNonceOrigin(nonce2) -select op, nonce1, nonce2 From cce5f24b3860a451dd2869798cee012faf81ec5d Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 4 Mar 2025 15:52:57 -0500 Subject: [PATCH 040/336] Initial OpenSSL modeling work. --- cpp/ql/lib/experimental/Quantum/Language.qll | 123 +- cpp/ql/lib/experimental/Quantum/OpenSSL.qll | 244 -- .../Quantum/OpenSSL/AlgorithmSource.qll | 2848 +++++++++++++++++ .../experimental/Quantum/OpenSSL/CtxFlow.qll | 82 + .../Quantum/OpenSSL/EVPCipherConsumers.qll | 25 + .../Quantum/OpenSSL/EVPCipherInitializer.qll | 153 + .../Quantum/OpenSSL/EVPCipherOperation.qll | 87 + .../experimental/Quantum/OpenSSL/OpenSSL.qll | 357 +++ 8 files changed, 3673 insertions(+), 246 deletions(-) delete mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmSource.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherInitializer.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index 8f400858f07c..3f1d9aa9bdf3 100644 --- a/cpp/ql/lib/experimental/Quantum/Language.qll +++ b/cpp/ql/lib/experimental/Quantum/Language.qll @@ -1,12 +1,131 @@ private import codeql.cryptography.Model +import semmle.code.cpp.ir.IR +import semmle.code.cpp.security.FlowSources as FlowSources private import cpp as Lang + module CryptoInput implements InputSig { + class DataFlowNode = DataFlow::Node; class LocatableElement = Lang::Locatable; - class UnknownLocation = Lang::UnknownDefaultLocation; } module Crypto = CryptographyBase; -import OpenSSL +/** + * Artifact output to node input configuration + */ +abstract class AdditionalFlowInputStep extends DataFlow::Node { + abstract DataFlow::Node getOutput(); + + final DataFlow::Node getInput() { result = this } +} + + +/** + * Generic data source to node input configuration + */ +module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source = any(Crypto::GenericDataSourceInstance i).getOutputNode() + } + + predicate isSink(DataFlow::Node sink) { + sink = any(Crypto::FlowAwareElement other).getInputNode() + } + + predicate isBarrierOut(DataFlow::Node node) { + node = any(Crypto::FlowAwareElement element).getInputNode() + } + + predicate isBarrierIn(DataFlow::Node node) { + node = any(Crypto::FlowAwareElement element).getOutputNode() + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + node1.(AdditionalFlowInputStep).getOutput() = node2 + } +} + + + +// TODO: I think this will be inefficient, no? +class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource instanceof Literal { + override DataFlow::Node getOutputNode() { + result.asExpr() = this + } + + override predicate flowsTo(Crypto::FlowAwareElement other) { + // TODO: separate config to avoid blowing up data-flow analysis + GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) + } + + override string getAdditionalDescription() { result = this.toString() } +} + +/** + * Definitions of various generic data sources + */ +// final class DefaultFlowSource = SourceNode; + +// final class DefaultRemoteFlowSource = RemoteFlowSource; + +// class GenericLocalDataSource extends Crypto::GenericLocalDataSource { +// GenericLocalDataSource() { +// any(DefaultFlowSource src | not src instanceof DefaultRemoteFlowSource).asExpr() = this +// } + +// override DataFlow::Node getOutputNode() { result.asExpr() = this } + +// override predicate flowsTo(Crypto::FlowAwareElement other) { +// GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) +// } + +// override string getAdditionalDescription() { result = this.toString() } +// } + +// class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { +// GenericRemoteDataSource() { any(DefaultRemoteFlowSource src).asExpr() = this } + +// override DataFlow::Node getOutputNode() { result.asExpr() = this } + +// override predicate flowsTo(Crypto::FlowAwareElement other) { +// GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) +// } + +// override string getAdditionalDescription() { result = this.toString() } +// } + + +module GenericDataSourceUniversalFlow = DataFlow::Global; + +module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source = any(Crypto::ArtifactElement artifact).getOutputNode() + } + + predicate isSink(DataFlow::Node sink) { + sink = any(Crypto::FlowAwareElement other).getInputNode() + } + + predicate isBarrierOut(DataFlow::Node node) { + node = any(Crypto::FlowAwareElement element).getInputNode() + } + + predicate isBarrierIn(DataFlow::Node node) { + node = any(Crypto::FlowAwareElement element).getOutputNode() + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + node1.(AdditionalFlowInputStep).getOutput() = node2 + } +} +module ArtifactUniversalFlow = DataFlow::Global; +abstract class CipherOutputArtifact extends Crypto::CipherOutputArtifactInstance { + override predicate flowsTo(Crypto::FlowAwareElement other) { + ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) + } +} + + +import OpenSSL.OpenSSL diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll deleted file mode 100644 index 821fc0aec8ff..000000000000 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll +++ /dev/null @@ -1,244 +0,0 @@ -import cpp -import semmle.code.cpp.dataflow.new.DataFlow - -module OpenSSLModel { - import Language - - /** - * Hash function references in OpenSSL. - */ - predicate hash_ref_type_mapping_known(string name, Crypto::THashType algo) { - // `ma` name has an LN_ or SN_ prefix, which we want to ignore - // capture any name after the _ prefix using regex matching - name = ["sha1", "sha160"] and algo instanceof Crypto::SHA1 - or - name = ["sha224", "sha256", "sha384", "sha512"] and algo instanceof Crypto::SHA2 - or - name = ["sha3-224", "sha3-256", "sha3-384", "sha3-512"] and algo instanceof Crypto::SHA3 - or - name = "md2" and algo instanceof Crypto::MD2 - or - name = "md4" and algo instanceof Crypto::MD4 - or - name = "md5" and algo instanceof Crypto::MD5 - or - name = "ripemd160" and algo instanceof Crypto::RIPEMD160 - or - name = "whirlpool" and algo instanceof Crypto::WHIRLPOOL - } - - predicate hash_ref_type_mapping(FunctionCallOrMacroAccess ref, string name, Crypto::THashType algo) { - name = ref.getTargetName().regexpCapture("(?:SN_|LN_|EVP_)([a-z0-9]+)", 1) and - hash_ref_type_mapping_known(name, algo) - } - - class FunctionCallOrMacroAccess extends Element { - FunctionCallOrMacroAccess() { this instanceof FunctionCall or this instanceof MacroAccess } - - string getTargetName() { - result = this.(FunctionCall).getTarget().getName() - or - result = this.(MacroAccess).getMacroName() - } - } - - class HashAlgorithmCallOrMacro extends Crypto::HashAlgorithmInstance instanceof FunctionCallOrMacroAccess - { - HashAlgorithmCallOrMacro() { hash_ref_type_mapping(this, _, _) } - - string getTargetName() { result = this.(FunctionCallOrMacroAccess).getTargetName() } - } - - class HashAlgorithm extends Crypto::HashAlgorithm { - HashAlgorithmCallOrMacro instance; - - HashAlgorithm() { this = Crypto::THashAlgorithm(instance) } - - override string getSHA2OrSHA3DigestSize(Location location) { - ( - this.getHashType() instanceof Crypto::SHA2 or - this.getHashType() instanceof Crypto::SHA3 - ) and - exists(string name | - hash_ref_type_mapping(instance, name, this.getHashType()) and - result = name.regexpFind("\\d{3}", 0, _) and - location = instance.getLocation() - ) - } - - override string getRawAlgorithmName() { result = instance.getTargetName() } - - override Crypto::THashType getHashType() { hash_ref_type_mapping(instance, _, result) } - - Element getInstance() { result = instance } - - override Location getLocation() { result = instance.getLocation() } - } - - /** - * Data-flow configuration for key derivation algorithm flow to EVP_KDF_derive. - */ - module AlgorithmToEVPKeyDeriveConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { - source.asExpr() = any(KeyDerivationAlgorithm a).getInstance() - } - - predicate isSink(DataFlow::Node sink) { - exists(EVP_KDF_derive kdo | - sink.asExpr() = kdo.getCall().getAlgorithmArg() - or - sink.asExpr() = kdo.getCall().getContextArg() // via `EVP_KDF_CTX_set_params` - ) - } - - predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - none() // TODO - } - } - - module AlgorithmToEVPKeyDeriveFlow = DataFlow::Global; - - predicate algorithm_to_EVP_KDF_derive(KeyDerivationAlgorithm algo, EVP_KDF_derive derive) { - none() - } - - /** - * Key derivation operation (e.g., `EVP_KDF_derive`) - */ - class EVP_KDF_derive_FunctionCall extends Crypto::KeyDerivationOperationInstance instanceof FunctionCall - { - EVP_KDF_derive_FunctionCall() { this.getTarget().getName() = "EVP_KDF_derive" } - - Expr getAlgorithmArg() { result = super.getArgument(3) } - - Expr getContextArg() { result = super.getArgument(0) } - } - - class EVP_KDF_derive extends Crypto::KeyDerivationOperation { - EVP_KDF_derive_FunctionCall instance; - - EVP_KDF_derive() { this = Crypto::TKeyDerivationOperation(instance) } - - override Crypto::Algorithm getAlgorithm() { algorithm_to_EVP_KDF_derive(result, this) } - - EVP_KDF_derive_FunctionCall getCall() { result = instance } - } - - /** - * Key derivation algorithm nodes - */ - abstract class KeyDerivationAlgorithm extends Crypto::KeyDerivationAlgorithm { - abstract Expr getInstance(); - } - - /** - * `EVP_KDF_fetch` returns a key derivation algorithm. - */ - class EVP_KDF_fetch_Call extends FunctionCall { - EVP_KDF_fetch_Call() { this.getTarget().getName() = "EVP_KDF_fetch" } - - Expr getAlgorithmArg() { result = this.getArgument(1) } - } - - class EVP_KDF_fetch_AlgorithmArg extends Crypto::KeyDerivationAlgorithmInstance instanceof Expr { - EVP_KDF_fetch_AlgorithmArg() { exists(EVP_KDF_fetch_Call call | this = call.getAlgorithmArg()) } - } - - predicate kdf_names(string algo) { algo = ["HKDF", "PKCS12KDF", "PBKDF2"] } - - class KDFAlgorithmStringLiteral extends StringLiteral { - KDFAlgorithmStringLiteral() { kdf_names(this.getValue().toUpperCase()) } - } - - private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { src.asExpr() instanceof KDFAlgorithmStringLiteral } - - predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof EVP_KDF_fetch_AlgorithmArg } - } - - module AlgorithmStringToFetchFlow = DataFlow::Global; - - predicate algorithmStringToKDFFetchArgFlow( - string name, KDFAlgorithmStringLiteral origin, EVP_KDF_fetch_AlgorithmArg arg - ) { - origin.getValue().toUpperCase() = name and - AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), DataFlow::exprNode(arg)) - } - - /** - * HKDF key derivation algorithm. - */ - class HKDF extends KeyDerivationAlgorithm, Crypto::HKDF { - KDFAlgorithmStringLiteral origin; - EVP_KDF_fetch_AlgorithmArg instance; - - HKDF() { - this = Crypto::TKeyDerivationAlgorithm(instance) and - algorithmStringToKDFFetchArgFlow("HKDF", origin, instance) - } - - override string getRawAlgorithmName() { result = origin.getValue() } - - override Crypto::HashAlgorithm getHashAlgorithm() { none() } - - override Crypto::LocatableElement getOrigin(string name) { - result = origin and name = origin.toString() - } - - override Expr getInstance() { result = origin } - } - - /** - * PBKDF2 key derivation algorithm. - */ - class PBKDF2 extends KeyDerivationAlgorithm, Crypto::PBKDF2 { - KDFAlgorithmStringLiteral origin; - EVP_KDF_fetch_AlgorithmArg instance; - - PBKDF2() { - this = Crypto::TKeyDerivationAlgorithm(instance) and - algorithmStringToKDFFetchArgFlow("PBKDF2", origin, instance) - } - - override string getRawAlgorithmName() { result = origin.getValue() } - - override string getIterationCount(Location location) { none() } // TODO - - override string getKeyLength(Location location) { none() } // TODO - - override Crypto::HashAlgorithm getHashAlgorithm() { none() } // TODO - - override Crypto::LocatableElement getOrigin(string name) { - result = origin and name = origin.toString() - } - - override Expr getInstance() { result = instance } - } - - /** - * PKCS12KDF key derivation algorithm. - */ - class PKCS12KDF extends KeyDerivationAlgorithm, Crypto::PKCS12KDF { - KDFAlgorithmStringLiteral origin; - EVP_KDF_fetch_AlgorithmArg instance; - - PKCS12KDF() { - this = Crypto::TKeyDerivationAlgorithm(instance) and - algorithmStringToKDFFetchArgFlow("PKCS12KDF", origin, instance) - } - - override string getRawAlgorithmName() { result = origin.getValue() } - - override string getIterationCount(Location location) { none() } // TODO - - override string getIDByte(Location location) { none() } // TODO - - override Crypto::HashAlgorithm getHashAlgorithm() { none() } // TODO - - override Crypto::LocatableElement getOrigin(string name) { - result = origin and name = origin.toString() - } - - override Expr getInstance() { result = instance } - } -} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmSource.qll new file mode 100644 index 000000000000..f409578e98d2 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmSource.qll @@ -0,0 +1,2848 @@ +import cpp +import experimental.Quantum.Language +import EVPCipherConsumers + +/** + * Note: padding and a mode of operation will only exist when the padding / mode (*and its type*) are determinable. + * This is because the mode will always be specified alongside the algorithm and never independently. + * Therefore, we can always assume that a determinable algorithm will have a determinable mode. + * + * In the case that only an algorithm is specified, e.g., "AES", the provider provides a default mode. + * + * TODO: Model the case of relying on a provider default, but alert on it as a bad practice. + */ +class CipherLiteralAlgorithmInstance extends Crypto::CipherAlgorithmInstance instanceof ConstantDataSource +{ + Crypto::AlgorithmConsumer consumer; // TODO: I need to make this an open SSL algorithm consumer specifically + + CipherLiteralAlgorithmInstance() { + GenericDataSourceUniversalFlow::flow(DataFlow::exprNode(this), DataFlow::exprNode(consumer)) + } + + Crypto::AlgorithmConsumer getConsumer() { result = consumer } + + override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { + none() // TODO: provider defaults + } + + override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { none() } + + override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } + + override Crypto::TCipherType getCipherFamily() { none() } +} + +// override Crypto::TCipherType getCipherFamily() { +// if this.cipherNameMappingKnown(_, super.getAlgorithmName()) +// then this.cipherNameMappingKnown(result, super.getAlgorithmName()) +// else result instanceof Crypto::OtherCipherType +// } +// bindingset[name] +// private predicate cipherNameMappingKnown(Crypto::TCipherType type, string name) { +// name = "AES" and +// type instanceof Crypto::AES +// or +// name = "DES" and +// type instanceof Crypto::DES +// or +// name = "TripleDES" and +// type instanceof Crypto::TripleDES +// or +// name = "IDEA" and +// type instanceof Crypto::IDEA +// or +// name = "CAST5" and +// type instanceof Crypto::CAST5 +// or +// name = "ChaCha20" and +// type instanceof Crypto::ChaCha20 +// or +// name = "RC4" and +// type instanceof Crypto::RC4 +// or +// name = "RC5" and +// type instanceof Crypto::RC5 +// or +// name = "RSA" and +// type instanceof Crypto::RSA +// } +// private predicate modeToNameMappingKnown(Crypto::TBlockCipherModeOperationType type, string name) { +// type instanceof Crypto::ECB and name = "ECB" +// or +// type instanceof Crypto::CBC and name = "CBC" +// or +// type instanceof Crypto::GCM and name = "GCM" +// or +// type instanceof Crypto::CTR and name = "CTR" +// or +// type instanceof Crypto::XTS and name = "XTS" +// or +// type instanceof Crypto::CCM and name = "CCM" +// or +// type instanceof Crypto::SIV and name = "SIV" +// or +// type instanceof Crypto::OCB and name = "OCB" +// } +// override Crypto::TBlockCipherModeOperationType getModeType() { +// if this.modeToNameMappingKnown(_, super.getMode()) +// then this.modeToNameMappingKnown(result, super.getMode()) +// else result instanceof Crypto::OtherMode +// } +// override string getRawModeAlgorithmName() { result = super.getMode() } +// override string getRawPaddingAlgorithmName() { result = super.getPadding() } +// bindingset[name] +// private predicate paddingToNameMappingKnown(Crypto::TPaddingType type, string name) { +// type instanceof Crypto::NoPadding and name = "NOPADDING" +// or +// type instanceof Crypto::PKCS7 and name = ["PKCS5Padding", "PKCS7Padding"] // TODO: misnomer in the JCA? +// or +// type instanceof Crypto::OAEP and name.matches("OAEP%") // TODO: handle OAEPWith% +// } +// } +/** + * Resolves literal `e` to a known algorithm name, nid, normalized name, and algType + * if `e` resolves to a known algorithm. + * If this predicate does not hold, then `e` can be interpreted as being of `UNKNOWN` type. + */ +predicate resolveAlgorithmFromLiteral(Literal e, string normalized, string algType) { + exists(int nid | + nid = getPossibleNidFromLiteral(e) and knownOpenSSLAlgorithm(_, nid, normalized, algType) + ) + or + exists(string name | + name = resolveAlgorithmAlias(e) and knownOpenSSLAlgorithm(name, _, normalized, algType) + ) +} + +string resolveAlgorithmAlias(StringLiteral name) { + exists(string lower | lower = name.getValue().toLowerCase() | + // The result is an alias algorithm name if known + result = getAlgorithmAlias(lower) + or + // or the name is itself a known algorithm + knownOpenSSLAlgorithm(lower, _, _, _) and result = lower + ) +} + +private int getPossibleNidFromLiteral(Literal e) { + result = e.getValue().toInt() and + not e instanceof CharLiteral and + not e instanceof StringLiteral and + // ASSUMPTION, no negative numbers are allowed + // RATIONALE: this is a performance improvement to avoid having to trace every number + not exists(UnaryMinusExpr u | u.getOperand() = e) and + // OPENSSL has a special macro for getting every line, ignore it + not exists(MacroInvocation mi | mi.getExpr() = e and mi.getMacroName() = "OPENSSL_LINE") and + // Filter out cases where an int is assigned into a pointer, e.g., char* x = NULL; + not exists(Assignment a | + a.getRValue() = e and a.getLValue().getType().getUnspecifiedType() instanceof PointerType + ) and + not exists(Initializer i | + i.getExpr() = e and + i.getDeclaration().getADeclarationEntry().getUnspecifiedType() instanceof PointerType + ) and + // Filter out cases where an int is returned into a pointer, e.g., return NULL; + not exists(ReturnStmt r | + r.getExpr() = e and + r.getEnclosingFunction().getType().getUnspecifiedType() instanceof PointerType + ) +} + +string getAlgorithmAlias(string alias) { + customAliases(result, alias) + or + defaultAliases(result, alias) +} + +/** + * Finds aliases of known alagorithms defined by users (through obj_name_add and various macros pointing to this function) + * + * The `target` and `alias` are converted to lowercase to be of a standard form. + */ +predicate customAliases(string target, string alias) { + exists(Call c | c.getTarget().getName().toLowerCase() = "obj_name_add" | + target = c.getArgument(2).getValue().toLowerCase() and + alias = c.getArgument(0).getValue().toLowerCase() + ) +} + +/** + * A hard-coded mapping of known algorithm aliases in OpenSSL. + * This was derived by applying the same kind of logic foun din `customAliases` to the + * OpenSSL code base directly. + * + * The `target` and `alias` are converted to lowercase to be of a standard form. + */ +predicate defaultAliases(string target, string alias) { + alias = "aes128" and target = "aes-128-cbc" + or + alias = "aes192" and target = "aes-192-cbc" + or + alias = "aes256" and target = "aes-256-cbc" + or + alias = "aes128-wrap" and target = "id-aes128-wrap" + or + alias = "aes192-wrap" and target = "id-aes192-wrap" + or + alias = "aes256-wrap" and target = "id-aes256-wrap" + or + alias = "aes128-wrap-pad" and target = "id-aes128-wrap-pad" + or + alias = "aes192-wrap-pad" and target = "id-aes192-wrap-pad" + or + alias = "aes256-wrap-pad" and target = "id-aes256-wrap-pad" + or + alias = "aes-128-wrap" and target = "id-aes128-wrap" + or + alias = "aes-192-wrap" and target = "id-aes192-wrap" + or + alias = "aes-256-wrap" and target = "id-aes256-wrap" + or + alias = "aria128" and target = "aria-128-cbc" + or + alias = "aria192" and target = "aria-192-cbc" + or + alias = "aria256" and target = "aria-256-cbc" + or + alias = "aes128" and target = "aes-128-cbc" + or + alias = "bf" and target = "bf-cbc" + or + alias = "blowfish" and target = "bf-cbc" + or + alias = "camellia128" and target = "camellia-128-cbc" + or + alias = "camellia192" and target = "camellia-192-cbc" + or + alias = "camellia256" and target = "camellia-256-cbc" + or + alias = "cast" and target = "cast5-cbc" + or + alias = "cast-cbc" and target = "cast5-cbc" + or + alias = "des" and target = "des-cbc" + or + alias = "des-ede-ecb" and target = "des-ede" + or + alias = "des-ede3-ecb" and target = "des-ede3" + or + alias = "des3" and target = "des-ede3-cbc" + or + alias = "des3-wrap" and target = "id-smime-alg-cms3deswrap" + or + alias = "desx" and target = "desx-cbc" + or + alias = "idea" and target = "idea-cbc" + or + alias = "rc2" and target = "rc2-cbc" + or + alias = "rc2-128" and target = "rc2-cbc" + or + alias = "rc2-40" and target = "rc2-40-cbc" + or + alias = "rc2-64" and target = "rc2-64-cbc" + or + alias = "ripemd" and target = "ripemd160" + or + alias = "rmd160" and target = "ripemd160" + or + alias = "rsa-sha1-2" and target = "rsa-sha1" + or + alias = "seed" and target = "seed-cbc" + or + alias = "sm4" and target = "sm4-cbc" + or + alias = "ssl3-md5" and target = "md5" + or + alias = "ssl3-sha1" and target = "sha1" +} + +/** + * Enumeration of all known crypto algorithms for openSSL + * `name` is all lower case (caller's must ensure they pass in lower case) + * `nid` is the numeric id of the algorithm, + * `normalized` is the normalized name of the algorithm (e.g., "AES128" for "aes-128-cbc") + * `algType` is the type of algorithm (e.g., "SYMMETRIC_ENCRYPTION") + */ +predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string algType) { + name = "rsa" and nid = 19 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "prime192v1" and nid = 409 and normalized = "PRIME192V1" and algType = "ELLIPTIC_CURVE" + or + name = "prime256v1" and nid = 415 and normalized = "PRIME256V1" and algType = "ELLIPTIC_CURVE" + or + name = "pbkdf2" and nid = 69 and normalized = "PBKDF2" and algType = "KEY_DERIVATION" + or + name = "dsa" and nid = 116 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "gost2001" and nid = 811 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost2012_256" and nid = 979 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost2012_512" and nid = 980 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "ed25519" and nid = 1087 and normalized = "ED25519" and algType = "ELLIPTIC_CURVE" + or + name = "ed448" and nid = 1088 and normalized = "ED448" and algType = "ELLIPTIC_CURVE" + or + name = "md2" and nid = 3 and normalized = "MD2" and algType = "HASH" + or + name = "sha" and nid = 41 and normalized = "SHA" and algType = "HASH" + or + name = "sha1" and nid = 64 and normalized = "SHA1" and algType = "HASH" + or + name = "scrypt" and nid = 973 and normalized = "SCRYPT" and algType = "KEY_DERIVATION" + or + name = "pkcs7" and nid = 20 and normalized = "PKCS7" and algType = "SYMMETRIC_PADDING" + or + name = "md4" and nid = 257 and normalized = "MD4" and algType = "HASH" + or + name = "md5" and nid = 4 and normalized = "MD5" and algType = "HASH" + or + name = "sha224" and nid = 675 and normalized = "SHA224" and algType = "HASH" + or + name = "sha256" and nid = 672 and normalized = "SHA256" and algType = "HASH" + or + name = "sha384" and nid = 673 and normalized = "SHA384" and algType = "HASH" + or + name = "sha512" and nid = 674 and normalized = "SHA512" and algType = "HASH" + or + name = "sha512-224" and nid = 1094 and normalized = "SHA512224" and algType = "HASH" + or + name = "sha512-256" and nid = 1095 and normalized = "SHA512256" and algType = "HASH" + or + name = "sha3-224" and nid = 1096 and normalized = "SHA3224" and algType = "HASH" + or + name = "sha3-256" and nid = 1097 and normalized = "SHA3256" and algType = "HASH" + or + name = "sha3-384" and nid = 1098 and normalized = "SHA3384" and algType = "HASH" + or + name = "sha3-512" and nid = 1099 and normalized = "SHA3512" and algType = "HASH" + or + name = "shake128" and nid = 1100 and normalized = "SHAKE128" and algType = "HASH" + or + name = "shake256" and nid = 1101 and normalized = "SHAKE256" and algType = "HASH" + or + name = "mdc2" and nid = 95 and normalized = "MDC2" and algType = "HASH" + or + name = "blake2b512" and nid = 1056 and normalized = "BLAKE2B" and algType = "HASH" + or + name = "blake2s256" and nid = 1057 and normalized = "BLAKE2S" and algType = "HASH" + or + name = "sm3" and nid = 1143 and normalized = "SM3" and algType = "HASH" + or + name = "aes-128-cbc" and nid = 419 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-cbc" and nid = 419 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "aes-128-ecb" and nid = 418 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-ecb" and nid = 418 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "aes-192-cbc" and nid = 423 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-192-cbc" and nid = 423 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "aes-192-ecb" and nid = 422 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-192-ecb" and nid = 422 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "aes-256-cbc" and nid = 427 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-256-cbc" and nid = 427 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "aes-256-ecb" and nid = 426 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-256-ecb" and nid = 426 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "aria-128-cbc" and nid = 1066 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "aria-128-cbc" and nid = 1066 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-128-cfb" and nid = 1067 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "aria-128-cfb" and nid = 1067 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-128-ctr" and nid = 1069 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "aria-128-ctr" and nid = 1069 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-128-ecb" and nid = 1065 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "aria-128-ecb" and nid = 1065 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-128-ofb" and nid = 1068 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "aria-128-ofb" and nid = 1068 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-128-cfb1" and nid = 1080 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "aria-128-cfb1" and nid = 1080 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-128-cfb8" and nid = 1083 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-128-cfb8" and nid = 1083 and normalized = "CFB8" and algType = "BLOCK_MODE" + or + name = "aria-192-cbc" and nid = 1071 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "aria-192-cbc" and nid = 1071 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-192-cfb" and nid = 1072 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "aria-192-cfb" and nid = 1072 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-192-ctr" and nid = 1074 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "aria-192-ctr" and nid = 1074 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-192-ecb" and nid = 1070 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "aria-192-ecb" and nid = 1070 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-192-ofb" and nid = 1073 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "aria-192-ofb" and nid = 1073 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-192-cfb1" and nid = 1081 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "aria-192-cfb1" and nid = 1081 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-192-cfb8" and nid = 1084 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-192-cfb8" and nid = 1084 and normalized = "CFB8" and algType = "BLOCK_MODE" + or + name = "aria-256-cbc" and nid = 1076 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "aria-256-cbc" and nid = 1076 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-256-cfb" and nid = 1077 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "aria-256-cfb" and nid = 1077 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-256-ctr" and nid = 1079 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "aria-256-ctr" and nid = 1079 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-256-ecb" and nid = 1075 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "aria-256-ecb" and nid = 1075 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-256-ofb" and nid = 1078 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "aria-256-ofb" and nid = 1078 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-256-cfb1" and nid = 1082 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "aria-256-cfb1" and nid = 1082 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-256-cfb8" and nid = 1085 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-256-cfb8" and nid = 1085 and normalized = "CFB8" and algType = "BLOCK_MODE" + or + name = "camellia-128-cbc" and + nid = 751 and + normalized = "CAMELLIA128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-128-cbc" and nid = 751 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "camellia-128-ecb" and + nid = 754 and + normalized = "CAMELLIA128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-128-ecb" and nid = 754 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "camellia-192-cbc" and + nid = 752 and + normalized = "CAMELLIA192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-192-cbc" and nid = 752 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "camellia-192-ecb" and + nid = 755 and + normalized = "CAMELLIA192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-192-ecb" and nid = 755 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "camellia-256-cbc" and + nid = 753 and + normalized = "CAMELLIA256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-256-cbc" and nid = 753 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "camellia-256-ecb" and + nid = 756 and + normalized = "CAMELLIA256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-256-ecb" and nid = 756 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "rc4" and nid = 5 and normalized = "RC4" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "rc4-40" and nid = 97 and normalized = "RC4" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-ecb" and nid = 29 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-ecb" and nid = 29 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "des-ede" and nid = 32 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-ede3" and nid = 33 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-ede3" and nid = 33 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "des-cbc" and nid = 31 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-cbc" and nid = 31 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "des-ede-cbc" and nid = 43 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-ede-cbc" and nid = 43 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "des-ede-cbc" and nid = 43 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "des-ede3-cbc" and nid = 44 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-ede3-cbc" and nid = 44 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "des-cfb" and nid = 30 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-cfb" and nid = 30 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "des-ede-cfb" and nid = 60 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-ede-cfb" and nid = 60 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "des-ede3-cfb" and nid = 61 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-ede3-cfb" and nid = 61 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "des-ofb" and nid = 45 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-ofb" and nid = 45 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "des-ede-ofb" and nid = 62 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-ede-ofb" and nid = 62 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "des-ede3-ofb" and nid = 63 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-ede3-ofb" and nid = 63 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "idea-cbc" and nid = 34 and normalized = "IDEA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "idea-cbc" and nid = 34 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "idea-ecb" and nid = 36 and normalized = "IDEA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "idea-ecb" and nid = 36 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "idea-cfb" and nid = 35 and normalized = "IDEA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "idea-cfb" and nid = 35 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "idea-ofb" and nid = 46 and normalized = "IDEA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "idea-ofb" and nid = 46 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "seed-cbc" and nid = 777 and normalized = "SEED" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "seed-cbc" and nid = 777 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "seed-ecb" and nid = 776 and normalized = "SEED" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "seed-ecb" and nid = 776 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "seed-cfb" and nid = 779 and normalized = "SEED" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "seed-cfb" and nid = 779 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "seed-ofb" and nid = 778 and normalized = "SEED" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "seed-ofb" and nid = 778 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "rc2-cbc" and nid = 37 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "rc2-cbc" and nid = 37 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "rc2-ecb" and nid = 38 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "rc2-ecb" and nid = 38 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "rc2-cfb" and nid = 39 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "rc2-cfb" and nid = 39 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "rc2-ofb" and nid = 40 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "rc2-ofb" and nid = 40 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "rc2-64-cbc" and nid = 166 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "rc2-64-cbc" and nid = 166 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "rc2-40-cbc" and nid = 98 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "rc2-40-cbc" and nid = 98 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "bf-cbc" and nid = 91 and normalized = "BF" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "bf-cbc" and nid = 91 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "bf-ecb" and nid = 92 and normalized = "BF" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "bf-ecb" and nid = 92 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "bf-cfb" and nid = 93 and normalized = "BF" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "bf-cfb" and nid = 93 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "bf-ofb" and nid = 94 and normalized = "BF" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "bf-ofb" and nid = 94 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "cast5-cbc" and nid = 108 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "cast5-cbc" and nid = 108 and normalized = "CAST5" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "cast5-ecb" and nid = 109 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "cast5-ecb" and nid = 109 and normalized = "CAST5" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "cast5-cfb" and nid = 110 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "cast5-cfb" and nid = 110 and normalized = "CAST5" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "cast5-ofb" and nid = 111 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "cast5-ofb" and nid = 111 and normalized = "CAST5" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "sm4-cbc" and nid = 1134 and normalized = "SM4" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "sm4-cbc" and nid = 1134 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "sm4-ecb" and nid = 1133 and normalized = "SM4" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "sm4-ecb" and nid = 1133 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "sm4-cfb" and nid = 1137 and normalized = "SM4" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "sm4-cfb" and nid = 1137 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "sm4-ofb" and nid = 1135 and normalized = "SM4" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "sm4-ofb" and nid = 1135 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "sm4-ctr" and nid = 1139 and normalized = "SM4" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "sm4-ctr" and nid = 1139 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "aes-128-gcm" and nid = 895 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-gcm" and nid = 895 and normalized = "GCM" and algType = "BLOCK_MODE" + or + name = "secp160r1" and nid = 709 and normalized = "SECP160R1" and algType = "ELLIPTIC_CURVE" + or + name = "ripemd160" and nid = 117 and normalized = "RIPEMD160" and algType = "HASH" + or + name = "whirlpool" and nid = 804 and normalized = "WHIRLPOOL" and algType = "HASH" + or + name = "rc5-cbc" and nid = 120 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "rc5-cbc" and nid = 120 and normalized = "RC5" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "pss" and nid = 435 and normalized = "PSS" and algType = "ASYMMETRIC_PADDING" + or + name = "id-aes128-wrap" and + nid = 788 and + normalized = "AES128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-aes192-wrap" and + nid = 789 and + normalized = "AES192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-aes256-wrap" and + nid = 790 and + normalized = "AES256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-aes128-wrap-pad" and + nid = 897 and + normalized = "AES128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-aes192-wrap-pad" and + nid = 900 and + normalized = "AES192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-aes256-wrap-pad" and + nid = 903 and + normalized = "AES256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "chacha20" and nid = 1019 and normalized = "CHACHA20" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "secp112r1" and nid = 704 and normalized = "SECP112R1" and algType = "ELLIPTIC_CURVE" + or + name = "secp112r2" and nid = 705 and normalized = "SECP112R2" and algType = "ELLIPTIC_CURVE" + or + name = "secp128r1" and nid = 706 and normalized = "SECP128R1" and algType = "ELLIPTIC_CURVE" + or + name = "secp128r2" and nid = 707 and normalized = "SECP128R2" and algType = "ELLIPTIC_CURVE" + or + name = "secp160k1" and nid = 708 and normalized = "SECP160K1" and algType = "ELLIPTIC_CURVE" + or + name = "secp160r2" and nid = 710 and normalized = "SECP160R2" and algType = "ELLIPTIC_CURVE" + or + name = "secp192k1" and nid = 711 and normalized = "SECP192K1" and algType = "ELLIPTIC_CURVE" + or + name = "secp224k1" and nid = 712 and normalized = "SECP224K1" and algType = "ELLIPTIC_CURVE" + or + name = "secp224r1" and nid = 713 and normalized = "SECP224R1" and algType = "ELLIPTIC_CURVE" + or + name = "secp256k1" and nid = 714 and normalized = "SECP256K1" and algType = "ELLIPTIC_CURVE" + or + name = "secp384r1" and nid = 715 and normalized = "SECP384R1" and algType = "ELLIPTIC_CURVE" + or + name = "secp521r1" and nid = 716 and normalized = "SECP521R1" and algType = "ELLIPTIC_CURVE" + or + name = "prime192v2" and nid = 410 and normalized = "PRIME192V2" and algType = "ELLIPTIC_CURVE" + or + name = "prime192v3" and nid = 411 and normalized = "PRIME192V3" and algType = "ELLIPTIC_CURVE" + or + name = "prime239v1" and nid = 412 and normalized = "PRIME239V1" and algType = "ELLIPTIC_CURVE" + or + name = "prime239v2" and nid = 413 and normalized = "PRIME239V2" and algType = "ELLIPTIC_CURVE" + or + name = "prime239v3" and nid = 414 and normalized = "PRIME239V3" and algType = "ELLIPTIC_CURVE" + or + name = "sect113r1" and nid = 717 and normalized = "SECT113R1" and algType = "ELLIPTIC_CURVE" + or + name = "sect113r2" and nid = 718 and normalized = "SECT113R2" and algType = "ELLIPTIC_CURVE" + or + name = "sect131r1" and nid = 719 and normalized = "SECT131R1" and algType = "ELLIPTIC_CURVE" + or + name = "sect131r2" and nid = 720 and normalized = "SECT131R2" and algType = "ELLIPTIC_CURVE" + or + name = "sect163k1" and nid = 721 and normalized = "SECT163K1" and algType = "ELLIPTIC_CURVE" + or + name = "sect163r1" and nid = 722 and normalized = "SECT163R1" and algType = "ELLIPTIC_CURVE" + or + name = "sect163r2" and nid = 723 and normalized = "SECT163R2" and algType = "ELLIPTIC_CURVE" + or + name = "sect193r1" and nid = 724 and normalized = "SECT193R1" and algType = "ELLIPTIC_CURVE" + or + name = "sect193r2" and nid = 725 and normalized = "SECT193R2" and algType = "ELLIPTIC_CURVE" + or + name = "sect233k1" and nid = 726 and normalized = "SECT233K1" and algType = "ELLIPTIC_CURVE" + or + name = "sect233r1" and nid = 727 and normalized = "SECT233R1" and algType = "ELLIPTIC_CURVE" + or + name = "sect239k1" and nid = 728 and normalized = "SECT239K1" and algType = "ELLIPTIC_CURVE" + or + name = "sect283k1" and nid = 729 and normalized = "SECT283K1" and algType = "ELLIPTIC_CURVE" + or + name = "sect283r1" and nid = 730 and normalized = "SECT283R1" and algType = "ELLIPTIC_CURVE" + or + name = "sect409k1" and nid = 731 and normalized = "SECT409K1" and algType = "ELLIPTIC_CURVE" + or + name = "sect409r1" and nid = 732 and normalized = "SECT409R1" and algType = "ELLIPTIC_CURVE" + or + name = "sect571k1" and nid = 733 and normalized = "SECT571K1" and algType = "ELLIPTIC_CURVE" + or + name = "sect571r1" and nid = 734 and normalized = "SECT571R1" and algType = "ELLIPTIC_CURVE" + or + name = "c2pnb163v1" and nid = 684 and normalized = "C2PNB163V1" and algType = "ELLIPTIC_CURVE" + or + name = "c2pnb163v2" and nid = 685 and normalized = "C2PNB163V2" and algType = "ELLIPTIC_CURVE" + or + name = "c2pnb163v3" and nid = 686 and normalized = "C2PNB163V3" and algType = "ELLIPTIC_CURVE" + or + name = "c2pnb176v1" and nid = 687 and normalized = "C2PNB176V1" and algType = "ELLIPTIC_CURVE" + or + name = "c2tnb191v1" and nid = 688 and normalized = "C2TNB191V1" and algType = "ELLIPTIC_CURVE" + or + name = "c2tnb191v2" and nid = 689 and normalized = "C2TNB191V2" and algType = "ELLIPTIC_CURVE" + or + name = "c2tnb191v3" and nid = 690 and normalized = "C2TNB191V3" and algType = "ELLIPTIC_CURVE" + or + name = "c2pnb208w1" and nid = 693 and normalized = "C2PNB208W1" and algType = "ELLIPTIC_CURVE" + or + name = "c2tnb239v1" and nid = 694 and normalized = "C2TNB239V1" and algType = "ELLIPTIC_CURVE" + or + name = "c2tnb239v2" and nid = 695 and normalized = "C2TNB239V2" and algType = "ELLIPTIC_CURVE" + or + name = "c2tnb239v3" and nid = 696 and normalized = "C2TNB239V3" and algType = "ELLIPTIC_CURVE" + or + name = "c2pnb272w1" and nid = 699 and normalized = "C2PNB272W1" and algType = "ELLIPTIC_CURVE" + or + name = "c2pnb304w1" and nid = 700 and normalized = "C2PNB304W1" and algType = "ELLIPTIC_CURVE" + or + name = "c2tnb359v1" and nid = 701 and normalized = "C2TNB359V1" and algType = "ELLIPTIC_CURVE" + or + name = "c2pnb368w1" and nid = 702 and normalized = "C2PNB368W1" and algType = "ELLIPTIC_CURVE" + or + name = "c2tnb431r1" and nid = 703 and normalized = "C2TNB431R1" and algType = "ELLIPTIC_CURVE" + or + name = "pkcs5" and nid = 187 and normalized = "PKCS5" and algType = "KEY_DERIVATION" + or + name = "aes-256-gcm" and nid = 901 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-256-gcm" and nid = 901 and normalized = "GCM" and algType = "BLOCK_MODE" + or + name = "chacha20-poly1305" and nid = 1018 and normalized = "POLY1305" and algType = "HASH" + or + name = "chacha20-poly1305" and + nid = 1018 and + normalized = "CHACHA20POLY1305" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "rsadsi" and nid = 1 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "pkcs7-data" and nid = 21 and normalized = "PKCS7" and algType = "SYMMETRIC_PADDING" + or + name = "desx-cbc" and nid = 80 and normalized = "DESX" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "desx-cbc" and nid = 80 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "md5-sha1" and nid = 114 and normalized = "SHA1" and algType = "HASH" + or + name = "rc5-ecb" and nid = 121 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "rc5-ecb" and nid = 121 and normalized = "RC5" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "rc5-cfb" and nid = 122 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "rc5-cfb" and nid = 122 and normalized = "RC5" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "rc5-ofb" and nid = 123 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "rc5-ofb" and nid = 123 and normalized = "RC5" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-alg-des40" and nid = 323 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-alg-dh-sig-hmac-sha1" and nid = 325 and normalized = "SHA1" and algType = "HASH" + or + name = "aes-128-ofb" and nid = 420 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-ofb" and nid = 420 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "aes-128-cfb" and nid = 421 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-cfb" and nid = 421 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "aes-192-ofb" and nid = 424 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-192-ofb" and nid = 424 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "aes-192-cfb" and nid = 425 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-192-cfb" and nid = 425 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "aes-256-ofb" and nid = 428 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-256-ofb" and nid = 428 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "aes-256-cfb" and nid = 429 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-256-cfb" and nid = 429 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "des-cdmf" and nid = 643 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-cfb1" and nid = 650 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-cfb1" and nid = 650 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "aes-192-cfb1" and nid = 651 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-192-cfb1" and nid = 651 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "aes-256-cfb1" and nid = 652 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-256-cfb1" and nid = 652 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "aes-128-cfb8" and nid = 653 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-cfb8" and nid = 653 and normalized = "CFB8" and algType = "BLOCK_MODE" + or + name = "aes-192-cfb8" and nid = 654 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-192-cfb8" and nid = 654 and normalized = "CFB8" and algType = "BLOCK_MODE" + or + name = "aes-256-cfb8" and nid = 655 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-256-cfb8" and nid = 655 and normalized = "CFB8" and algType = "BLOCK_MODE" + or + name = "des-cfb1" and nid = 656 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-cfb1" and nid = 656 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "des-cfb8" and nid = 657 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-cfb8" and nid = 657 and normalized = "CFB8" and algType = "BLOCK_MODE" + or + name = "des-ede3-cfb1" and nid = 658 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-ede3-cfb1" and nid = 658 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "des-ede3-cfb8" and nid = 659 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "des-ede3-cfb8" and nid = 659 and normalized = "CFB8" and algType = "BLOCK_MODE" + or + name = "c2onb191v4" and nid = 691 and normalized = "C2ONB191V4" and algType = "ELLIPTIC_CURVE" + or + name = "c2onb191v5" and nid = 692 and normalized = "C2ONB191V5" and algType = "ELLIPTIC_CURVE" + or + name = "c2onb239v4" and nid = 697 and normalized = "C2ONB239V4" and algType = "ELLIPTIC_CURVE" + or + name = "c2onb239v5" and nid = 698 and normalized = "C2ONB239V5" and algType = "ELLIPTIC_CURVE" + or + name = "camellia-128-cfb" and + nid = 757 and + normalized = "CAMELLIA128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-128-cfb" and nid = 757 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "camellia-192-cfb" and + nid = 758 and + normalized = "CAMELLIA192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-192-cfb" and nid = 758 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "camellia-256-cfb" and + nid = 759 and + normalized = "CAMELLIA256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-256-cfb" and nid = 759 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "camellia-128-cfb1" and + nid = 760 and + normalized = "CAMELLIA128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-128-cfb1" and nid = 760 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "camellia-192-cfb1" and + nid = 761 and + normalized = "CAMELLIA192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-192-cfb1" and nid = 761 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "camellia-256-cfb1" and + nid = 762 and + normalized = "CAMELLIA256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-256-cfb1" and nid = 762 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "camellia-128-cfb8" and + nid = 763 and + normalized = "CAMELLIA128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-128-cfb8" and nid = 763 and normalized = "CFB8" and algType = "BLOCK_MODE" + or + name = "camellia-192-cfb8" and + nid = 764 and + normalized = "CAMELLIA192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-192-cfb8" and nid = 764 and normalized = "CFB8" and algType = "BLOCK_MODE" + or + name = "camellia-256-cfb8" and + nid = 765 and + normalized = "CAMELLIA256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-256-cfb8" and nid = 765 and normalized = "CFB8" and algType = "BLOCK_MODE" + or + name = "camellia-128-ofb" and + nid = 766 and + normalized = "CAMELLIA128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-128-ofb" and nid = 766 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "camellia-192-ofb" and + nid = 767 and + normalized = "CAMELLIA192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-192-ofb" and nid = 767 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "camellia-256-ofb" and + nid = 768 and + normalized = "CAMELLIA256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-256-ofb" and nid = 768 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "hmac-md5" and nid = 780 and normalized = "MD5" and algType = "HASH" + or + name = "hmac-sha1" and nid = 781 and normalized = "SHA1" and algType = "HASH" + or + name = "md_gost94" and nid = 809 and normalized = "GOST94" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost94" and nid = 812 and normalized = "GOST94" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost89" and nid = 813 and normalized = "GOST89" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost89-cnt" and nid = 814 and normalized = "GOST89" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost-mac" and nid = 815 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "prf-gostr3411-94" and + nid = 816 and + normalized = "GOSTR341194" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost94cc" and nid = 850 and normalized = "GOST94" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost2001cc" and nid = 851 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-ccm" and nid = 896 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-ccm" and nid = 896 and normalized = "CCM" and algType = "BLOCK_MODE" + or + name = "aes-192-gcm" and nid = 898 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-192-gcm" and nid = 898 and normalized = "GCM" and algType = "BLOCK_MODE" + or + name = "aes-192-ccm" and nid = 899 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-192-ccm" and nid = 899 and normalized = "CCM" and algType = "BLOCK_MODE" + or + name = "aes-256-ccm" and nid = 902 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-256-ccm" and nid = 902 and normalized = "CCM" and algType = "BLOCK_MODE" + or + name = "aes-128-ctr" and nid = 904 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-ctr" and nid = 904 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "aes-192-ctr" and nid = 905 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-192-ctr" and nid = 905 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "aes-256-ctr" and nid = 906 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-256-ctr" and nid = 906 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "id-camellia128-wrap" and + nid = 907 and + normalized = "CAMELLIA128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-camellia192-wrap" and + nid = 908 and + normalized = "CAMELLIA192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-camellia256-wrap" and + nid = 909 and + normalized = "CAMELLIA256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "mgf1" and nid = 911 and normalized = "MGF1" and algType = "HASH" + or + name = "aes-128-xts" and nid = 913 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-xts" and nid = 913 and normalized = "XTS" and algType = "BLOCK_MODE" + or + name = "aes-256-xts" and nid = 914 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-256-xts" and nid = 914 and normalized = "XTS" and algType = "BLOCK_MODE" + or + name = "rc4-hmac-md5" and nid = 915 and normalized = "MD5" and algType = "HASH" + or + name = "rc4-hmac-md5" and nid = 915 and normalized = "RC4" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-cbc-hmac-sha1" and nid = 916 and normalized = "SHA1" and algType = "HASH" + or + name = "aes-128-cbc-hmac-sha1" and + nid = 916 and + normalized = "AES128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-cbc-hmac-sha1" and nid = 916 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "aes-192-cbc-hmac-sha1" and nid = 917 and normalized = "SHA1" and algType = "HASH" + or + name = "aes-192-cbc-hmac-sha1" and + nid = 917 and + normalized = "AES192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-192-cbc-hmac-sha1" and nid = 917 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "aes-256-cbc-hmac-sha1" and + nid = 918 and + normalized = "AES256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-256-cbc-hmac-sha1" and nid = 918 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "aes-128-cbc-hmac-sha256" and nid = 948 and normalized = "SHA256" and algType = "HASH" + or + name = "aes-128-cbc-hmac-sha256" and + nid = 948 and + normalized = "AES128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-cbc-hmac-sha256" and nid = 948 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "aes-192-cbc-hmac-sha256" and nid = 949 and normalized = "SHA256" and algType = "HASH" + or + name = "aes-192-cbc-hmac-sha256" and + nid = 949 and + normalized = "AES192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-192-cbc-hmac-sha256" and nid = 949 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "aes-256-cbc-hmac-sha256" and nid = 950 and normalized = "SHA256" and algType = "HASH" + or + name = "aes-256-cbc-hmac-sha256" and + nid = 950 and + normalized = "AES256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-256-cbc-hmac-sha256" and nid = 950 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "aes-128-ocb" and nid = 958 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-192-ocb" and nid = 959 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-256-ocb" and nid = 960 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-128-gcm" and + nid = 961 and + normalized = "CAMELLIA128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-128-gcm" and nid = 961 and normalized = "GCM" and algType = "BLOCK_MODE" + or + name = "camellia-128-ccm" and + nid = 962 and + normalized = "CAMELLIA128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-128-ccm" and nid = 962 and normalized = "CCM" and algType = "BLOCK_MODE" + or + name = "camellia-128-ctr" and + nid = 963 and + normalized = "CAMELLIA128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-128-ctr" and nid = 963 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "camellia-128-cmac" and + nid = 964 and + normalized = "CAMELLIA128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-192-gcm" and + nid = 965 and + normalized = "CAMELLIA192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-192-gcm" and nid = 965 and normalized = "GCM" and algType = "BLOCK_MODE" + or + name = "camellia-192-ccm" and + nid = 966 and + normalized = "CAMELLIA192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-192-ccm" and nid = 966 and normalized = "CCM" and algType = "BLOCK_MODE" + or + name = "camellia-192-ctr" and + nid = 967 and + normalized = "CAMELLIA192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-192-ctr" and nid = 967 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "camellia-192-cmac" and + nid = 968 and + normalized = "CAMELLIA192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-256-gcm" and + nid = 969 and + normalized = "CAMELLIA256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-256-gcm" and nid = 969 and normalized = "GCM" and algType = "BLOCK_MODE" + or + name = "camellia-256-ccm" and + nid = 970 and + normalized = "CAMELLIA256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-256-ccm" and nid = 970 and normalized = "CCM" and algType = "BLOCK_MODE" + or + name = "camellia-256-ctr" and + nid = 971 and + normalized = "CAMELLIA256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "camellia-256-ctr" and nid = 971 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "camellia-256-cmac" and + nid = 972 and + normalized = "CAMELLIA256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-scrypt" and nid = 973 and normalized = "SCRYPT" and algType = "KEY_DERIVATION" + or + name = "gost89-cnt-12" and + nid = 975 and + normalized = "GOST89" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost-mac-12" and nid = 976 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "md_gost12_256" and nid = 982 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "md_gost12_512" and nid = 983 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-signwithdigest-gost3410-2012-256" and + nid = 985 and + normalized = "GOST34102012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-signwithdigest-gost3410-2012-512" and + nid = 986 and + normalized = "GOST34102012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-hmac-gost-3411-2012-256" and + nid = 988 and + normalized = "GOST34112012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-hmac-gost-3411-2012-512" and + nid = 989 and + normalized = "GOST34112012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-agreement-gost-3410-2012-256" and + nid = 992 and + normalized = "GOST34102012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-agreement-gost-3410-2012-512" and + nid = 993 and + normalized = "GOST34102012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-gost-3410-2012-512-constants" and + nid = 996 and + normalized = "GOST34102012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-gost-28147-constants" and + nid = 1002 and + normalized = "GOST28147" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost89-cbc" and nid = 1009 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "gost89-cbc" and nid = 1009 and normalized = "GOST89" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost89-ecb" and nid = 1010 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "gost89-ecb" and nid = 1010 and normalized = "GOST89" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost89-ctr" and nid = 1011 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "gost89-ctr" and nid = 1011 and normalized = "GOST89" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "kuznyechik-ecb" and nid = 1012 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "kuznyechik-ecb" and + nid = 1012 and + normalized = "KUZNYECHIK" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "kuznyechik-ctr" and nid = 1013 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "kuznyechik-ctr" and + nid = 1013 and + normalized = "KUZNYECHIK" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "kuznyechik-ofb" and nid = 1014 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "kuznyechik-ofb" and + nid = 1014 and + normalized = "KUZNYECHIK" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "kuznyechik-cbc" and nid = 1015 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "kuznyechik-cbc" and + nid = 1015 and + normalized = "KUZNYECHIK" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "kuznyechik-cfb" and nid = 1016 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "kuznyechik-cfb" and + nid = 1016 and + normalized = "KUZNYECHIK" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "kuznyechik-mac" and + nid = 1017 and + normalized = "KUZNYECHIK" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "hkdf" and nid = 1036 and normalized = "HKDF" and algType = "KEY_DERIVATION" + or + name = "kx-rsa" and nid = 1037 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "kx-ecdhe" and nid = 1038 and normalized = "ECDH" and algType = "KEY_EXCHANGE" + or + name = "kx-ecdhe-psk" and nid = 1040 and normalized = "ECDH" and algType = "KEY_EXCHANGE" + or + name = "kx-rsa-psk" and nid = 1042 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "kx-gost" and nid = 1045 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "auth-rsa" and nid = 1046 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "auth-ecdsa" and nid = 1047 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "auth-gost01" and nid = 1050 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "auth-gost12" and nid = 1051 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "poly1305" and nid = 1061 and normalized = "POLY1305" and algType = "HASH" + or + name = "hmac-sha3-224" and nid = 1102 and normalized = "SHA3224" and algType = "HASH" + or + name = "hmac-sha3-256" and nid = 1103 and normalized = "SHA3256" and algType = "HASH" + or + name = "hmac-sha3-384" and nid = 1104 and normalized = "SHA3384" and algType = "HASH" + or + name = "hmac-sha3-512" and nid = 1105 and normalized = "SHA3512" and algType = "HASH" + or + name = "id-dsa-with-sha384" and nid = 1106 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "id-dsa-with-sha384" and nid = 1106 and normalized = "SHA384" and algType = "HASH" + or + name = "id-dsa-with-sha512" and nid = 1107 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "id-dsa-with-sha512" and nid = 1107 and normalized = "SHA512" and algType = "HASH" + or + name = "id-dsa-with-sha3-224" and nid = 1108 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "id-dsa-with-sha3-224" and nid = 1108 and normalized = "SHA3224" and algType = "HASH" + or + name = "id-dsa-with-sha3-256" and nid = 1109 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "id-dsa-with-sha3-256" and nid = 1109 and normalized = "SHA3256" and algType = "HASH" + or + name = "id-dsa-with-sha3-384" and nid = 1110 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "id-dsa-with-sha3-384" and nid = 1110 and normalized = "SHA3384" and algType = "HASH" + or + name = "id-dsa-with-sha3-512" and nid = 1111 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "id-dsa-with-sha3-512" and nid = 1111 and normalized = "SHA3512" and algType = "HASH" + or + name = "id-ecdsa-with-sha3-224" and nid = 1112 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "id-ecdsa-with-sha3-224" and nid = 1112 and normalized = "SHA3224" and algType = "HASH" + or + name = "id-ecdsa-with-sha3-256" and nid = 1113 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "id-ecdsa-with-sha3-256" and nid = 1113 and normalized = "SHA3256" and algType = "HASH" + or + name = "id-ecdsa-with-sha3-384" and nid = 1114 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "id-ecdsa-with-sha3-384" and nid = 1114 and normalized = "SHA3384" and algType = "HASH" + or + name = "id-ecdsa-with-sha3-512" and nid = 1115 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "id-ecdsa-with-sha3-512" and nid = 1115 and normalized = "SHA3512" and algType = "HASH" + or + name = "id-rsassa-pkcs1-v1_5-with-sha3-224" and + nid = 1116 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "id-rsassa-pkcs1-v1_5-with-sha3-224" and + nid = 1116 and + normalized = "PKCS1V15" and + algType = "ASYMMETRIC_PADDING" + or + name = "id-rsassa-pkcs1-v1_5-with-sha3-224" and + nid = 1116 and + normalized = "SHA3224" and + algType = "HASH" + or + name = "id-rsassa-pkcs1-v1_5-with-sha3-256" and + nid = 1117 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "id-rsassa-pkcs1-v1_5-with-sha3-256" and + nid = 1117 and + normalized = "PKCS1V15" and + algType = "ASYMMETRIC_PADDING" + or + name = "id-rsassa-pkcs1-v1_5-with-sha3-256" and + nid = 1117 and + normalized = "SHA3256" and + algType = "HASH" + or + name = "id-rsassa-pkcs1-v1_5-with-sha3-384" and + nid = 1118 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "id-rsassa-pkcs1-v1_5-with-sha3-384" and + nid = 1118 and + normalized = "PKCS1V15" and + algType = "ASYMMETRIC_PADDING" + or + name = "id-rsassa-pkcs1-v1_5-with-sha3-384" and + nid = 1118 and + normalized = "SHA3384" and + algType = "HASH" + or + name = "id-rsassa-pkcs1-v1_5-with-sha3-512" and + nid = 1119 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "id-rsassa-pkcs1-v1_5-with-sha3-512" and + nid = 1119 and + normalized = "PKCS1V15" and + algType = "ASYMMETRIC_PADDING" + or + name = "id-rsassa-pkcs1-v1_5-with-sha3-512" and + nid = 1119 and + normalized = "SHA3512" and + algType = "HASH" + or + name = "aria-128-ccm" and nid = 1120 and normalized = "CCM" and algType = "BLOCK_MODE" + or + name = "aria-128-ccm" and nid = 1120 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-192-ccm" and nid = 1121 and normalized = "CCM" and algType = "BLOCK_MODE" + or + name = "aria-192-ccm" and nid = 1121 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-256-ccm" and nid = 1122 and normalized = "CCM" and algType = "BLOCK_MODE" + or + name = "aria-256-ccm" and nid = 1122 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-128-gcm" and nid = 1123 and normalized = "GCM" and algType = "BLOCK_MODE" + or + name = "aria-128-gcm" and nid = 1123 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-192-gcm" and nid = 1124 and normalized = "GCM" and algType = "BLOCK_MODE" + or + name = "aria-192-gcm" and nid = 1124 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aria-256-gcm" and nid = 1125 and normalized = "GCM" and algType = "BLOCK_MODE" + or + name = "aria-256-gcm" and nid = 1125 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "sm4-cfb1" and nid = 1136 and normalized = "SM4" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "sm4-cfb1" and nid = 1136 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "sm4-cfb8" and nid = 1138 and normalized = "SM4" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "sm4-cfb8" and nid = 1138 and normalized = "CFB8" and algType = "BLOCK_MODE" + or + name = "id-tc26-gost-3410-2012-256-constants" and + nid = 1147 and + normalized = "GOST34102012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "dstu28147-ofb" and nid = 1153 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "dstu28147-cfb" and nid = 1154 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "id-tc26-cipher-gostr3412-2015-magma" and + nid = 1173 and + normalized = "MAGMA" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "magma-ctr-acpkm" and nid = 1174 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "magma-ctr-acpkm" and + nid = 1174 and + normalized = "MAGMA" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "magma-ctr-acpkm-omac" and nid = 1175 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "magma-ctr-acpkm-omac" and + nid = 1175 and + normalized = "MAGMA" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-cipher-gostr3412-2015-kuznyechik" and + nid = 1176 and + normalized = "KUZNYECHIK" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "kuznyechik-ctr-acpkm" and nid = 1177 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "kuznyechik-ctr-acpkm" and + nid = 1177 and + normalized = "KUZNYECHIK" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "kuznyechik-ctr-acpkm-omac" and + nid = 1178 and + normalized = "CTR" and + algType = "BLOCK_MODE" + or + name = "kuznyechik-ctr-acpkm-omac" and + nid = 1178 and + normalized = "KUZNYECHIK" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-wrap-gostr3412-2015-magma" and + nid = 1180 and + normalized = "MAGMA" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "magma-kexp15" and nid = 1181 and normalized = "MAGMA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-wrap-gostr3412-2015-kuznyechik" and + nid = 1182 and + normalized = "KUZNYECHIK" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "kuznyechik-kexp15" and + nid = 1183 and + normalized = "KUZNYECHIK" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "magma-ecb" and nid = 1187 and normalized = "ECB" and algType = "BLOCK_MODE" + or + name = "magma-ecb" and nid = 1187 and normalized = "MAGMA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "magma-ctr" and nid = 1188 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "magma-ctr" and nid = 1188 and normalized = "MAGMA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "magma-ofb" and nid = 1189 and normalized = "OFB" and algType = "BLOCK_MODE" + or + name = "magma-ofb" and nid = 1189 and normalized = "MAGMA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "magma-cbc" and nid = 1190 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "magma-cbc" and nid = 1190 and normalized = "MAGMA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "magma-cfb" and nid = 1191 and normalized = "CFB" and algType = "BLOCK_MODE" + or + name = "magma-cfb" and nid = 1191 and normalized = "MAGMA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "magma-mac" and nid = 1192 and normalized = "MAGMA" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-siv" and nid = 1198 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-128-siv" and nid = 1198 and normalized = "SIV" and algType = "BLOCK_MODE" + or + name = "aes-192-siv" and nid = 1199 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-192-siv" and nid = 1199 and normalized = "SIV" and algType = "BLOCK_MODE" + or + name = "aes-256-siv" and nid = 1200 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "aes-256-siv" and nid = 1200 and normalized = "SIV" and algType = "BLOCK_MODE" + or + name = "blake2bmac" and nid = 1201 and normalized = "BLAKE2B" and algType = "HASH" + or + name = "blake2smac" and nid = 1202 and normalized = "BLAKE2S" and algType = "HASH" + or + name = "sshkdf" and nid = 1203 and normalized = "HKDF" and algType = "KEY_DERIVATION" + or + name = "x963kdf" and nid = 1206 and normalized = "X963KDF" and algType = "KEY_DERIVATION" + or + name = "kx-gost18" and nid = 1218 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "sm4-gcm" and nid = 1248 and normalized = "SM4" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "sm4-gcm" and nid = 1248 and normalized = "GCM" and algType = "BLOCK_MODE" + or + name = "sm4-ccm" and nid = 1249 and normalized = "SM4" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "sm4-ccm" and nid = 1249 and normalized = "CCM" and algType = "BLOCK_MODE" + or + name = "sm4-xts" and nid = 1290 and normalized = "SM4" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "sm4-xts" and nid = 1290 and normalized = "XTS" and algType = "BLOCK_MODE" + or + name = "x448" and nid = 1035 and normalized = "X448" and algType = "ELLIPTIC_CURVE" + or + name = "x25519" and nid = 1034 and normalized = "X25519" and algType = "ELLIPTIC_CURVE" + or + name = "authecdsa" and nid = 1047 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "authgost01" and nid = 1050 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "authgost12" and nid = 1051 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "authrsa" and nid = 1046 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "brainpoolp160r1" and + nid = 921 and + normalized = "BRAINPOOLP160R1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp160t1" and + nid = 922 and + normalized = "BRAINPOOLP160T1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp192r1" and + nid = 923 and + normalized = "BRAINPOOLP192R1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp192t1" and + nid = 924 and + normalized = "BRAINPOOLP192T1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp224r1" and + nid = 925 and + normalized = "BRAINPOOLP224R1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp224t1" and + nid = 926 and + normalized = "BRAINPOOLP224T1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp256r1" and + nid = 927 and + normalized = "BRAINPOOLP256R1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp256r1tls13" and + nid = 1285 and + normalized = "BRAINPOOLP256R1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp256t1" and + nid = 928 and + normalized = "BRAINPOOLP256T1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp320r1" and + nid = 929 and + normalized = "BRAINPOOLP320R1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp320t1" and + nid = 930 and + normalized = "BRAINPOOLP320T1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp384r1" and + nid = 931 and + normalized = "BRAINPOOLP384R1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp384r1tls13" and + nid = 1286 and + normalized = "BRAINPOOLP384R1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp384t1" and + nid = 932 and + normalized = "BRAINPOOLP384T1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp512r1" and + nid = 933 and + normalized = "BRAINPOOLP512R1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp512r1tls13" and + nid = 1287 and + normalized = "BRAINPOOLP512R1" and + algType = "ELLIPTIC_CURVE" + or + name = "brainpoolp512t1" and + nid = 934 and + normalized = "BRAINPOOLP512T1" and + algType = "ELLIPTIC_CURVE" + or + name = "dhsinglepass-cofactordh-sha1kdf-scheme" and + nid = 941 and + normalized = "SHA1" and + algType = "HASH" + or + name = "dhsinglepass-cofactordh-sha224kdf-scheme" and + nid = 942 and + normalized = "SHA224" and + algType = "HASH" + or + name = "dhsinglepass-cofactordh-sha256kdf-scheme" and + nid = 943 and + normalized = "SHA256" and + algType = "HASH" + or + name = "dhsinglepass-cofactordh-sha384kdf-scheme" and + nid = 944 and + normalized = "SHA384" and + algType = "HASH" + or + name = "dhsinglepass-cofactordh-sha512kdf-scheme" and + nid = 945 and + normalized = "SHA512" and + algType = "HASH" + or + name = "dhsinglepass-stddh-sha1kdf-scheme" and + nid = 936 and + normalized = "SHA1" and + algType = "HASH" + or + name = "dhsinglepass-stddh-sha224kdf-scheme" and + nid = 937 and + normalized = "SHA224" and + algType = "HASH" + or + name = "dhsinglepass-stddh-sha256kdf-scheme" and + nid = 938 and + normalized = "SHA256" and + algType = "HASH" + or + name = "dhsinglepass-stddh-sha384kdf-scheme" and + nid = 939 and + normalized = "SHA384" and + algType = "HASH" + or + name = "dhsinglepass-stddh-sha512kdf-scheme" and + nid = 940 and + normalized = "SHA512" and + algType = "HASH" + or + name = "dsa-old" and nid = 67 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsa-sha" and nid = 66 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsa-sha" and nid = 66 and normalized = "SHA" and algType = "HASH" + or + name = "dsa-sha1" and nid = 113 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsa-sha1" and nid = 113 and normalized = "SHA1" and algType = "HASH" + or + name = "dsa-sha1-old" and nid = 70 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsa-sha1-old" and nid = 70 and normalized = "SHA1" and algType = "HASH" + or + name = "dsa_with_sha224" and nid = 802 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsa_with_sha224" and nid = 802 and normalized = "SHA224" and algType = "HASH" + or + name = "dsa_with_sha256" and nid = 803 and normalized = "SHA256" and algType = "HASH" + or + name = "dsa_with_sha256" and nid = 803 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsa_with_sha3-224" and nid = 1108 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsa_with_sha3-224" and nid = 1108 and normalized = "SHA3224" and algType = "HASH" + or + name = "dsa_with_sha3-256" and nid = 1109 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsa_with_sha3-256" and nid = 1109 and normalized = "SHA3256" and algType = "HASH" + or + name = "dsa_with_sha3-384" and nid = 1110 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsa_with_sha3-384" and nid = 1110 and normalized = "SHA3384" and algType = "HASH" + or + name = "dsa_with_sha3-512" and nid = 1111 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsa_with_sha3-512" and nid = 1111 and normalized = "SHA3512" and algType = "HASH" + or + name = "dsa_with_sha384" and nid = 1106 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsa_with_sha384" and nid = 1106 and normalized = "SHA384" and algType = "HASH" + or + name = "dsa_with_sha512" and nid = 1107 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsa_with_sha512" and nid = 1107 and normalized = "SHA512" and algType = "HASH" + or + name = "dsaencryption" and nid = 116 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsaencryption-old" and nid = 67 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsaquality" and nid = 495 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsawithsha" and nid = 66 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsawithsha" and nid = 66 and normalized = "SHA" and algType = "HASH" + or + name = "dsawithsha1" and nid = 113 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsawithsha1" and nid = 113 and normalized = "SHA1" and algType = "HASH" + or + name = "dsawithsha1-old" and nid = 70 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "dsawithsha1-old" and nid = 70 and normalized = "SHA1" and algType = "HASH" + or + name = "dstu gost 28147-2009 cfb mode" and + nid = 1154 and + normalized = "CFB" and + algType = "BLOCK_MODE" + or + name = "dstu gost 28147-2009 cfb mode" and + nid = 1154 and + normalized = "GOST28147" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "dstu gost 28147-2009 ofb mode" and + nid = 1153 and + normalized = "OFB" and + algType = "BLOCK_MODE" + or + name = "dstu gost 28147-2009 ofb mode" and + nid = 1153 and + normalized = "GOST28147" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "ecdsa-with-recommended" and nid = 791 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "ecdsa-with-sha1" and nid = 416 and normalized = "SHA1" and algType = "HASH" + or + name = "ecdsa-with-sha1" and nid = 416 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "ecdsa-with-sha224" and nid = 793 and normalized = "SHA224" and algType = "HASH" + or + name = "ecdsa-with-sha224" and nid = 793 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "ecdsa-with-sha256" and nid = 794 and normalized = "SHA256" and algType = "HASH" + or + name = "ecdsa-with-sha256" and nid = 794 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "ecdsa-with-sha384" and nid = 795 and normalized = "SHA384" and algType = "HASH" + or + name = "ecdsa-with-sha384" and nid = 795 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "ecdsa-with-sha512" and nid = 796 and normalized = "SHA512" and algType = "HASH" + or + name = "ecdsa-with-sha512" and nid = 796 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "ecdsa-with-specified" and nid = 792 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "ecdsa_with_sha3-224" and nid = 1112 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "ecdsa_with_sha3-224" and nid = 1112 and normalized = "SHA3224" and algType = "HASH" + or + name = "ecdsa_with_sha3-256" and nid = 1113 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "ecdsa_with_sha3-256" and nid = 1113 and normalized = "SHA3256" and algType = "HASH" + or + name = "ecdsa_with_sha3-384" and nid = 1114 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "ecdsa_with_sha3-384" and nid = 1114 and normalized = "SHA3384" and algType = "HASH" + or + name = "ecdsa_with_sha3-512" and nid = 1115 and normalized = "ECDSA" and algType = "SIGNATURE" + or + name = "ecdsa_with_sha3-512" and nid = 1115 and normalized = "SHA3512" and algType = "HASH" + or + name = "gost 28147-89" and + nid = 813 and + normalized = "GOST2814789" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost 28147-89 cryptocom paramset" and + nid = 849 and + normalized = "GOST2814789" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost 28147-89 mac" and + nid = 815 and + normalized = "GOST2814789" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost 28147-89 tc26 parameter set" and + nid = 1003 and + normalized = "GOST2814789" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost 34.10-2001 cryptocom" and + nid = 851 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost 34.10-94 cryptocom" and + nid = 850 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-2001" and + nid = 811 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-2001 dh" and + nid = 817 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-2012 (256 bit) paramset a" and + nid = 1148 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-2012 (256 bit) paramset b" and + nid = 1184 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-2012 (256 bit) paramset c" and + nid = 1185 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-2012 (256 bit) paramset d" and + nid = 1186 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-2012 (512 bit) paramset a" and + nid = 998 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-2012 (512 bit) paramset b" and + nid = 999 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-2012 (512 bit) paramset c" and + nid = 1149 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-2012 (512 bit) testing parameter set" and + nid = 997 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-2012 with 256 bit modulus" and + nid = 979 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-2012 with 512 bit modulus" and + nid = 980 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-2012 with gost r 34.11-2012 (256 bit)" and + nid = 985 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-2012 with gost r 34.11-2012 (512 bit)" and + nid = 986 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-94" and + nid = 812 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.10-94 dh" and + nid = 818 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.11-2012 with 256 bit hash" and + nid = 982 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.11-2012 with 512 bit hash" and + nid = 983 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.11-94" and + nid = 809 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.11-94 prf" and + nid = 816 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.11-94 with gost r 34.10-2001" and + nid = 807 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.11-94 with gost r 34.10-2001 cryptocom" and + nid = 853 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.11-94 with gost r 34.10-94" and + nid = 808 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 34.11-94 with gost r 34.10-94 cryptocom" and + nid = 852 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "gost r 3410-2001 parameter set cryptocom" and + nid = 854 and + normalized = "GOSTR34102001" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "hmac gost 34.11-2012 256 bit" and + nid = 988 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "hmac gost 34.11-2012 512 bit" and + nid = 989 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "hmac gost 34.11-94" and + nid = 810 and + normalized = "GOST" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "hmacwithmd5" and nid = 797 and normalized = "MD5" and algType = "HASH" + or + name = "hmacwithsha1" and nid = 163 and normalized = "SHA1" and algType = "HASH" + or + name = "hmacwithsha224" and nid = 798 and normalized = "SHA224" and algType = "HASH" + or + name = "hmacwithsha256" and nid = 799 and normalized = "SHA256" and algType = "HASH" + or + name = "hmacwithsha384" and nid = 800 and normalized = "SHA384" and algType = "HASH" + or + name = "hmacwithsha512" and nid = 801 and normalized = "SHA512" and algType = "HASH" + or + name = "hmacwithsha512-224" and nid = 1193 and normalized = "SHA512224" and algType = "HASH" + or + name = "hmacwithsha512-256" and nid = 1194 and normalized = "SHA512256" and algType = "HASH" + or + name = "hmacwithsm3" and nid = 1281 and normalized = "SM3" and algType = "HASH" + or + name = "id-aes128-ccm" and + nid = 896 and + normalized = "AES128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-aes128-ccm" and nid = 896 and normalized = "CCM" and algType = "BLOCK_MODE" + or + name = "id-aes128-gcm" and + nid = 895 and + normalized = "AES128" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-aes128-gcm" and nid = 895 and normalized = "GCM" and algType = "BLOCK_MODE" + or + name = "id-aes192-ccm" and + nid = 899 and + normalized = "AES192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-aes192-ccm" and nid = 899 and normalized = "CCM" and algType = "BLOCK_MODE" + or + name = "id-aes192-gcm" and + nid = 898 and + normalized = "AES192" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-aes192-gcm" and nid = 898 and normalized = "GCM" and algType = "BLOCK_MODE" + or + name = "id-aes256-ccm" and + nid = 902 and + normalized = "AES256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-aes256-ccm" and nid = 902 and normalized = "CCM" and algType = "BLOCK_MODE" + or + name = "id-aes256-gcm" and + nid = 901 and + normalized = "AES256" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-aes256-gcm" and nid = 901 and normalized = "GCM" and algType = "BLOCK_MODE" + or + name = "id-gost28147-89-cc" and + nid = 849 and + normalized = "GOST2814789" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gost28147-89-cryptopro-a-paramset" and + nid = 824 and + normalized = "GOST2814789" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gost28147-89-cryptopro-b-paramset" and + nid = 825 and + normalized = "GOST2814789" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gost28147-89-cryptopro-c-paramset" and + nid = 826 and + normalized = "GOST2814789" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gost28147-89-cryptopro-d-paramset" and + nid = 827 and + normalized = "GOST2814789" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gost28147-89-cryptopro-keymeshing" and + nid = 819 and + normalized = "GOST2814789" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gost28147-89-cryptopro-oscar-1-0-paramset" and + nid = 829 and + normalized = "GOST2814789" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gost28147-89-cryptopro-oscar-1-1-paramset" and + nid = 828 and + normalized = "GOST2814789" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gost28147-89-cryptopro-ric-1-paramset" and + nid = 830 and + normalized = "GOST2814789" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gost28147-89-none-keymeshing" and + nid = 820 and + normalized = "GOST2814789" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gost28147-89-testparamset" and + nid = 823 and + normalized = "GOST2814789" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-2001-cryptopro-a-paramset" and + nid = 840 and + normalized = "GOSTR34102001" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-2001-cryptopro-b-paramset" and + nid = 841 and + normalized = "GOSTR34102001" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-2001-cryptopro-c-paramset" and + nid = 842 and + normalized = "GOSTR34102001" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-2001-cryptopro-xcha-paramset" and + nid = 843 and + normalized = "GOSTR34102001" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-2001-cryptopro-xchb-paramset" and + nid = 844 and + normalized = "GOSTR34102001" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-2001-paramset-cc" and + nid = 854 and + normalized = "GOSTR34102001" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-2001-testparamset" and + nid = 839 and + normalized = "GOSTR34102001" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-2001dh" and + nid = 817 and + normalized = "GOSTR34102001" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-94-a" and + nid = 845 and + normalized = "GOSTR341094" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-94-abis" and + nid = 846 and + normalized = "GOSTR341094" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-94-b" and + nid = 847 and + normalized = "GOSTR341094" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-94-bbis" and + nid = 848 and + normalized = "GOSTR341094" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-94-cryptopro-a-paramset" and + nid = 832 and + normalized = "GOSTR341094" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-94-cryptopro-b-paramset" and + nid = 833 and + normalized = "GOSTR341094" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-94-cryptopro-c-paramset" and + nid = 834 and + normalized = "GOSTR341094" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-94-cryptopro-d-paramset" and + nid = 835 and + normalized = "GOSTR341094" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-94-cryptopro-xcha-paramset" and + nid = 836 and + normalized = "GOSTR341094" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-94-cryptopro-xchb-paramset" and + nid = 837 and + normalized = "GOSTR341094" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-94-cryptopro-xchc-paramset" and + nid = 838 and + normalized = "GOSTR341094" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-94-testparamset" and + nid = 831 and + normalized = "GOSTR341094" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3410-94dh" and + nid = 818 and + normalized = "GOSTR341094" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3411-94-cryptoproparamset" and + nid = 822 and + normalized = "GOSTR341194" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3411-94-testparamset" and + nid = 821 and + normalized = "GOSTR341194" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3411-94-with-gostr3410-2001" and + nid = 807 and + normalized = "GOSTR34102001" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3411-94-with-gostr3410-2001-cc" and + nid = 853 and + normalized = "GOSTR34102001" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3411-94-with-gostr3410-94" and + nid = 808 and + normalized = "GOSTR341094" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3411-94-with-gostr3410-94" and + nid = 808 and + normalized = "GOSTR341194" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3411-94-with-gostr3410-94-cc" and + nid = 852 and + normalized = "GOSTR341094" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-gostr3411-94-with-gostr3410-94-cc" and + nid = 852 and + normalized = "GOSTR341194" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-hmacgostr3411-94" and + nid = 810 and + normalized = "GOSTR341194" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-hmacwithsha3-224" and nid = 1102 and normalized = "SHA3224" and algType = "HASH" + or + name = "id-hmacwithsha3-256" and nid = 1103 and normalized = "SHA3256" and algType = "HASH" + or + name = "id-hmacwithsha3-384" and nid = 1104 and normalized = "SHA3384" and algType = "HASH" + or + name = "id-hmacwithsha3-512" and nid = 1105 and normalized = "SHA3512" and algType = "HASH" + or + name = "id-regctrl" and nid = 313 and normalized = "CTR" and algType = "BLOCK_MODE" + or + name = "id-smime-alg-3deswrap" and + nid = 243 and + normalized = "3DES" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-smime-alg-cms3deswrap" and nid = 246 and normalized = "GCM" and algType = "BLOCK_MODE" + or + name = "id-smime-alg-cms3deswrap" and + nid = 246 and + normalized = "3DES" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-smime-alg-cmsrc2wrap" and + nid = 247 and + normalized = "RC2" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-smime-alg-cmsrc2wrap" and nid = 247 and normalized = "GCM" and algType = "BLOCK_MODE" + or + name = "id-smime-alg-esdhwith3des" and + nid = 241 and + normalized = "3DES" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-smime-alg-esdhwithrc2" and + nid = 242 and + normalized = "RC2" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-smime-alg-rc2wrap" and + nid = 244 and + normalized = "RC2" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-gost-28147-param-z" and + nid = 1003 and + normalized = "GOST28147" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-gost-3410-2012-256-paramseta" and + nid = 1148 and + normalized = "GOST34102012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-gost-3410-2012-256-paramsetb" and + nid = 1184 and + normalized = "GOST34102012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-gost-3410-2012-256-paramsetc" and + nid = 1185 and + normalized = "GOST34102012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-gost-3410-2012-256-paramsetd" and + nid = 1186 and + normalized = "GOST34102012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-gost-3410-2012-512-paramseta" and + nid = 998 and + normalized = "GOST34102012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-gost-3410-2012-512-paramsetb" and + nid = 999 and + normalized = "GOST34102012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-gost-3410-2012-512-paramsetc" and + nid = 1149 and + normalized = "GOST34102012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "id-tc26-gost-3410-2012-512-paramsettest" and + nid = 997 and + normalized = "GOST34102012" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "kxecdhe" and nid = 1038 and normalized = "ECDH" and algType = "KEY_EXCHANGE" + or + name = "kxecdhe-psk" and nid = 1040 and normalized = "ECDH" and algType = "KEY_EXCHANGE" + or + name = "kxgost" and nid = 1045 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "kxgost18" and nid = 1218 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "kxrsa" and nid = 1037 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "kxrsa_psk" and nid = 1042 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "md2withrsaencryption" and + nid = 7 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "md2withrsaencryption" and nid = 7 and normalized = "MD2" and algType = "HASH" + or + name = "md4withrsaencryption" and + nid = 396 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "md4withrsaencryption" and nid = 396 and normalized = "MD4" and algType = "HASH" + or + name = "md5withrsa" and nid = 104 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "md5withrsa" and nid = 104 and normalized = "MD5" and algType = "HASH" + or + name = "md5withrsaencryption" and + nid = 8 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "md5withrsaencryption" and nid = 8 and normalized = "MD5" and algType = "HASH" + or + name = "mdc2withrsa" and nid = 96 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "mdc2withrsa" and nid = 96 and normalized = "MDC2" and algType = "HASH" + or + name = "pbe-md2-des" and nid = 9 and normalized = "MD2" and algType = "HASH" + or + name = "pbe-md2-des" and nid = 9 and normalized = "2DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbe-md2-rc2-64" and nid = 168 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbe-md2-rc2-64" and nid = 168 and normalized = "MD2" and algType = "HASH" + or + name = "pbe-md5-des" and nid = 10 and normalized = "MD5" and algType = "HASH" + or + name = "pbe-md5-des" and nid = 10 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbe-md5-rc2-64" and nid = 169 and normalized = "MD5" and algType = "HASH" + or + name = "pbe-md5-rc2-64" and nid = 169 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbe-sha1-2des" and nid = 147 and normalized = "SHA1" and algType = "HASH" + or + name = "pbe-sha1-2des" and nid = 147 and normalized = "2DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbe-sha1-3des" and nid = 146 and normalized = "SHA1" and algType = "HASH" + or + name = "pbe-sha1-3des" and nid = 146 and normalized = "3DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbe-sha1-des" and nid = 170 and normalized = "SHA1" and algType = "HASH" + or + name = "pbe-sha1-des" and nid = 170 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbe-sha1-rc2-128" and nid = 148 and normalized = "SHA1" and algType = "HASH" + or + name = "pbe-sha1-rc2-128" and + nid = 148 and + normalized = "RC2" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbe-sha1-rc2-40" and nid = 149 and normalized = "SHA1" and algType = "HASH" + or + name = "pbe-sha1-rc2-40" and nid = 149 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbe-sha1-rc2-64" and nid = 68 and normalized = "SHA1" and algType = "HASH" + or + name = "pbe-sha1-rc2-64" and nid = 68 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbe-sha1-rc4-128" and nid = 144 and normalized = "SHA1" and algType = "HASH" + or + name = "pbe-sha1-rc4-128" and + nid = 144 and + normalized = "RC4" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbe-sha1-rc4-40" and nid = 145 and normalized = "SHA1" and algType = "HASH" + or + name = "pbe-sha1-rc4-40" and nid = 145 and normalized = "RC4" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbewithmd2anddes-cbc" and + nid = 9 and + normalized = "DES" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbewithmd2anddes-cbc" and nid = 9 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "pbewithmd2anddes-cbc" and nid = 9 and normalized = "MD2" and algType = "HASH" + or + name = "pbewithmd2andrc2-cbc" and + nid = 168 and + normalized = "RC2" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbewithmd2andrc2-cbc" and nid = 168 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "pbewithmd2andrc2-cbc" and nid = 168 and normalized = "MD2" and algType = "HASH" + or + name = "pbewithmd5andcast5cbc" and nid = 112 and normalized = "MD5" and algType = "HASH" + or + name = "pbewithmd5andcast5cbc" and nid = 112 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "pbewithmd5andcast5cbc" and + nid = 112 and + normalized = "CAST5" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbewithmd5anddes-cbc" and nid = 10 and normalized = "MD5" and algType = "HASH" + or + name = "pbewithmd5anddes-cbc" and + nid = 10 and + normalized = "DES" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbewithmd5anddes-cbc" and nid = 10 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "pbewithmd5andrc2-cbc" and nid = 169 and normalized = "MD5" and algType = "HASH" + or + name = "pbewithmd5andrc2-cbc" and + nid = 169 and + normalized = "RC2" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbewithmd5andrc2-cbc" and nid = 169 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "pbewithsha1and128bitrc2-cbc" and nid = 148 and normalized = "SHA1" and algType = "HASH" + or + name = "pbewithsha1and128bitrc2-cbc" and + nid = 148 and + normalized = "RC2" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbewithsha1and128bitrc2-cbc" and + nid = 148 and + normalized = "CBC" and + algType = "BLOCK_MODE" + or + name = "pbewithsha1and128bitrc4" and nid = 144 and normalized = "SHA1" and algType = "HASH" + or + name = "pbewithsha1and128bitrc4" and + nid = 144 and + normalized = "RC4" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbewithsha1and2-keytripledes-cbc" and + nid = 147 and + normalized = "SHA1" and + algType = "HASH" + or + name = "pbewithsha1and2-keytripledes-cbc" and + nid = 147 and + normalized = "CBC" and + algType = "BLOCK_MODE" + or + name = "pbewithsha1and2-keytripledes-cbc" and + nid = 147 and + normalized = "TRIPLEDES" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbewithsha1and3-keytripledes-cbc" and + nid = 146 and + normalized = "SHA1" and + algType = "HASH" + or + name = "pbewithsha1and3-keytripledes-cbc" and + nid = 146 and + normalized = "CBC" and + algType = "BLOCK_MODE" + or + name = "pbewithsha1and3-keytripledes-cbc" and + nid = 146 and + normalized = "TRIPLEDES" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbewithsha1and40bitrc2-cbc" and nid = 149 and normalized = "SHA1" and algType = "HASH" + or + name = "pbewithsha1and40bitrc2-cbc" and + nid = 149 and + normalized = "RC2" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbewithsha1and40bitrc2-cbc" and + nid = 149 and + normalized = "CBC" and + algType = "BLOCK_MODE" + or + name = "pbewithsha1and40bitrc4" and nid = 145 and normalized = "SHA1" and algType = "HASH" + or + name = "pbewithsha1and40bitrc4" and + nid = 145 and + normalized = "RC4" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbewithsha1anddes-cbc" and nid = 170 and normalized = "SHA1" and algType = "HASH" + or + name = "pbewithsha1anddes-cbc" and + nid = 170 and + normalized = "DES" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbewithsha1anddes-cbc" and nid = 170 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "pbewithsha1andrc2-cbc" and nid = 68 and normalized = "SHA1" and algType = "HASH" + or + name = "pbewithsha1andrc2-cbc" and + nid = 68 and + normalized = "RC2" and + algType = "SYMMETRIC_ENCRYPTION" + or + name = "pbewithsha1andrc2-cbc" and nid = 68 and normalized = "CBC" and algType = "BLOCK_MODE" + or + name = "pilotdsa" and nid = 456 and normalized = "DSA" and algType = "SIGNATURE" + or + name = "pkcs7-digestdata" and nid = 25 and normalized = "PKCS7" and algType = "SYMMETRIC_PADDING" + or + name = "pkcs7-encrypteddata" and + nid = 26 and + normalized = "PKCS7" and + algType = "SYMMETRIC_PADDING" + or + name = "pkcs7-envelopeddata" and + nid = 23 and + normalized = "PKCS7" and + algType = "SYMMETRIC_PADDING" + or + name = "pkcs7-signedandenvelopeddata" and + nid = 24 and + normalized = "PKCS7" and + algType = "SYMMETRIC_PADDING" + or + name = "pkcs7-signeddata" and nid = 22 and normalized = "PKCS7" and algType = "SYMMETRIC_PADDING" + or + name = "ripemd160withrsa" and + nid = 119 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "ripemd160withrsa" and nid = 119 and normalized = "RIPEMD160" and algType = "HASH" + or + name = "rsa-md2" and nid = 7 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-md2" and nid = 7 and normalized = "MD2" and algType = "HASH" + or + name = "rsa-md4" and nid = 396 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-md4" and nid = 396 and normalized = "MD4" and algType = "HASH" + or + name = "rsa-md5" and nid = 8 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-md5" and nid = 8 and normalized = "MD5" and algType = "HASH" + or + name = "rsa-mdc2" and nid = 96 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-mdc2" and nid = 96 and normalized = "MDC2" and algType = "HASH" + or + name = "rsa-np-md5" and nid = 104 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-np-md5" and nid = 104 and normalized = "MD5" and algType = "HASH" + or + name = "rsa-ripemd160" and nid = 119 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-ripemd160" and nid = 119 and normalized = "RIPEMD160" and algType = "HASH" + or + name = "rsa-sha" and nid = 42 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-sha" and nid = 42 and normalized = "SHA" and algType = "HASH" + or + name = "rsa-sha1" and nid = 65 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-sha1" and nid = 65 and normalized = "SHA1" and algType = "HASH" + or + name = "rsa-sha1-2" and nid = 115 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-sha1-2" and nid = 115 and normalized = "SHA1" and algType = "HASH" + or + name = "rsa-sha224" and nid = 671 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-sha224" and nid = 671 and normalized = "SHA224" and algType = "HASH" + or + name = "rsa-sha256" and nid = 668 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-sha256" and nid = 668 and normalized = "SHA256" and algType = "HASH" + or + name = "rsa-sha3-224" and nid = 1116 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-sha3-224" and nid = 1116 and normalized = "SHA3224" and algType = "HASH" + or + name = "rsa-sha3-256" and nid = 1117 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-sha3-256" and nid = 1117 and normalized = "SHA3256" and algType = "HASH" + or + name = "rsa-sha3-384" and nid = 1118 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-sha3-384" and nid = 1118 and normalized = "SHA3384" and algType = "HASH" + or + name = "rsa-sha3-512" and nid = 1119 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-sha3-512" and nid = 1119 and normalized = "SHA3512" and algType = "HASH" + or + name = "rsa-sha384" and nid = 669 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-sha384" and nid = 669 and normalized = "SHA384" and algType = "HASH" + or + name = "rsa-sha512" and nid = 670 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-sha512" and nid = 670 and normalized = "SHA512" and algType = "HASH" + or + name = "rsa-sha512/224" and + nid = 1145 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-sha512/224" and nid = 1145 and normalized = "SHA512224" and algType = "HASH" + or + name = "rsa-sha512/256" and + nid = 1146 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-sha512/256" and nid = 1146 and normalized = "SHA512256" and algType = "HASH" + or + name = "rsa-sm3" and nid = 1144 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsa-sm3" and nid = 1144 and normalized = "SM3" and algType = "HASH" + or + name = "rsaencryption" and nid = 6 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsaes-oaep" and nid = 919 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsaes-oaep" and nid = 919 and normalized = "AES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "rsaes-oaep" and nid = 919 and normalized = "OAEP" and algType = "ASYMMETRIC_PADDING" + or + name = "rsaesoaep" and nid = 919 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsaesoaep" and nid = 919 and normalized = "AES" and algType = "SYMMETRIC_ENCRYPTION" + or + name = "rsaesoaep" and nid = 919 and normalized = "OAEP" and algType = "ASYMMETRIC_PADDING" + or + name = "rsaoaepencryptionset" and + nid = 644 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsaoaepencryptionset" and + nid = 644 and + normalized = "OAEP" and + algType = "ASYMMETRIC_PADDING" + or + name = "rsasignature" and nid = 377 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsassa-pss" and nid = 912 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsassa-pss" and nid = 912 and normalized = "PSS" and algType = "ASYMMETRIC_PADDING" + or + name = "rsassapss" and nid = 912 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "rsassapss" and nid = 912 and normalized = "PSS" and algType = "ASYMMETRIC_PADDING" + or + name = "sha1withrsa" and nid = 115 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" + or + name = "sha1withrsa" and nid = 115 and normalized = "SHA1" and algType = "HASH" + or + name = "sha1withrsaencryption" and + nid = 65 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "sha1withrsaencryption" and nid = 65 and normalized = "SHA1" and algType = "HASH" + or + name = "sha224withrsaencryption" and + nid = 671 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "sha224withrsaencryption" and nid = 671 and normalized = "SHA224" and algType = "HASH" + or + name = "sha256withrsaencryption" and + nid = 668 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "sha256withrsaencryption" and nid = 668 and normalized = "SHA256" and algType = "HASH" + or + name = "sha384withrsaencryption" and + nid = 669 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "sha384withrsaencryption" and nid = 669 and normalized = "SHA384" and algType = "HASH" + or + name = "sha512-224withrsaencryption" and + nid = 1145 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "sha512-224withrsaencryption" and + nid = 1145 and + normalized = "SHA512224" and + algType = "HASH" + or + name = "sha512-256withrsaencryption" and + nid = 1146 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "sha512-256withrsaencryption" and + nid = 1146 and + normalized = "SHA512256" and + algType = "HASH" + or + name = "sha512withrsaencryption" and + nid = 670 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "sha512withrsaencryption" and nid = 670 and normalized = "SHA512" and algType = "HASH" + or + name = "shawithrsaencryption" and + nid = 42 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "shawithrsaencryption" and nid = 42 and normalized = "SHA" and algType = "HASH" + or + name = "sm2" and nid = 1172 and normalized = "SM2" and algType = "ELLIPTIC_CURVE" + or + name = "sm2-sm3" and nid = 1204 and normalized = "SM3" and algType = "HASH" + or + name = "sm2-sm3" and nid = 1204 and normalized = "SM2" and algType = "ELLIPTIC_CURVE" + or + name = "sm2-with-sm3" and nid = 1204 and normalized = "SM3" and algType = "HASH" + or + name = "sm2-with-sm3" and nid = 1204 and normalized = "SM2" and algType = "ELLIPTIC_CURVE" + or + name = "sm3withrsaencryption" and + nid = 1144 and + normalized = "RSA" and + algType = "ASYMMETRIC_ENCRYPTION" + or + name = "sm3withrsaencryption" and nid = 1144 and normalized = "SM3" and algType = "HASH" +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll new file mode 100644 index 000000000000..54be40729b6f --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll @@ -0,0 +1,82 @@ +import semmle.code.cpp.dataflow.new.DataFlow + +class CTXType extends Type { + CTXType() { + // TODO: should we limit this to an openssl path? + this.getUnspecifiedType().stripType().getName().matches("evp_%ctx_%st") + } +} + +class CTXPointerExpr extends Expr { + CTXPointerExpr() { + this.getType() instanceof CTXType and + this.getType() instanceof PointerType + } +} + +class CTXPointerArgument extends CTXPointerExpr { + CTXPointerArgument() { + + exists(Call c | c.getAnArgument() = this) + } + + Call getCall() { result.getAnArgument() = this } +} + +class CTXClearCall extends Call { + CTXClearCall() { + this.getTarget().getName().toLowerCase().matches(["%free%", "%reset%"]) and + this.getAnArgument() instanceof CTXPointerArgument + } +} + +class CTXCopyOutArgCall extends Call { + CTXCopyOutArgCall() { + this.getTarget().getName().toLowerCase().matches(["%copy%"]) and + this.getAnArgument() instanceof CTXPointerArgument + } +} + +class CTXCopyReturnCall extends Call { + CTXCopyReturnCall() { + this.getTarget().getName().toLowerCase().matches(["%dup%"]) and + this.getAnArgument() instanceof CTXPointerArgument and + this instanceof CTXPointerExpr + } +} + +module OpenSSLCTXArgumentFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr() instanceof CTXPointerArgument } + + predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof CTXPointerArgument } + + predicate isBarrier(DataFlow::Node node) { + exists(CTXClearCall c | c.getAnArgument() = node.asExpr()) + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + exists(CTXCopyOutArgCall c | + c.getAnArgument() = node1.asExpr() and + c.getAnArgument() = node2.asExpr() and + node1.asExpr() != node2.asExpr() and + node2.asExpr().getType() instanceof CTXType + ) + or + exists(CTXCopyReturnCall c | + c.getAnArgument() = node1.asExpr() and + c = node2.asExpr() and + node1.asExpr() != node2.asExpr() and + node2.asExpr().getType() instanceof CTXType + ) + } +} + +module OpenSSLCTXArgumentFlow = DataFlow::Global; + +predicate ctxFlowsTo(CTXPointerArgument source, CTXPointerArgument sink) { + exists(DataFlow::Node a, DataFlow::Node b | + OpenSSLCTXArgumentFlow::flow(a, b) and + a.asExpr() = source and + b.asExpr() = sink + ) +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll new file mode 100644 index 000000000000..ceabae77374c --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll @@ -0,0 +1,25 @@ +import EVPCipherInitializer +import EVPCipherOperation +import AlgorithmSource + + +class EVP_Cipher_Initializer_Algorithm_Consumer extends Crypto::AlgorithmConsumer instanceof EVPCipherInitializerAlgorithmArgument +{ + override DataFlow::Node getInputNode() { result.asExpr() = this } + + override Crypto::AlgorithmElement getAKnownAlgorithmSource() { + result.(CipherLiteralAlgorithmInstance).getConsumer() = this + } +} +// //TODO: need a key consumer +// class EVP_Initializer_Key_Consumer extends Crypto::KeyConsumer instanceof EVP_Cipher_Inititalizer isntanceof InitializerKeyArgument{ +// } +class EVP_Cipher_Initializer_IV_Consumer extends Crypto::NonceArtifactConsumer instanceof EVPCipherInitializerIVArgument{ + override DataFlow::Node getInputNode() { result.asExpr() = this } +} + +class EVP_Cipher_Input_Consumer extends Crypto::CipherInputConsumer instanceof EVPCipherInputArgument{ + + override DataFlow::Node getInputNode() { result.asExpr() = this } +} + diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherInitializer.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherInitializer.qll new file mode 100644 index 000000000000..12cbe4da650a --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherInitializer.qll @@ -0,0 +1,153 @@ +import experimental.Quantum.Language +import CtxFlow as CTXFlow + +module EncValToInitEncArgConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr().getValue().toInt() in [0, 1] } + + predicate isSink(DataFlow::Node sink) { + exists(EVP_Cipher_Inititalizer initCall | sink.asExpr() = initCall.getOperataionSubtypeArg()) + } +} + +module EncValToInitEncArgFlow = DataFlow::Global; + +int getEncConfigValue(Expr e) { + exists(EVP_Cipher_Inititalizer initCall | e = initCall.getOperataionSubtypeArg()) and + exists(DataFlow::Node a, DataFlow::Node b | + EncValToInitEncArgFlow::flow(a, b) and b.asExpr() = e and result = a.asExpr().getValue().toInt() + ) +} + +bindingset[i] +Crypto::CipherOperationSubtype intToCipherOperationSubtype(int i) { + if i = 0 + then result instanceof Crypto::EncryptionSubtype + else + if i = 1 + then result instanceof Crypto::DecryptionSubtype + else result instanceof Crypto::UnknownCipherOperationSubtype +} + +// TODO: need to add key consumer +abstract class EVP_Cipher_Inititalizer extends Call { + Expr getContextArg() { result = this.(Call).getArgument(0) } + + Expr getAlgorithmArg() { result = this.(Call).getArgument(1) } + + abstract Expr getKeyArg(); + + abstract Expr getIVArg(); + +// abstract Crypto::CipherOperationSubtype getCipherOperationSubtype(); + + abstract Expr getOperataionSubtypeArg(); + +Crypto::CipherOperationSubtype getCipherOperationSubtype() { + if this.(Call).getTarget().getName().toLowerCase().matches("%encrypt%") + then result instanceof Crypto::EncryptionSubtype + else + if this.(Call).getTarget().getName().toLowerCase().matches("%decrypt%") + then result instanceof Crypto::DecryptionSubtype + else + if exists(getEncConfigValue(this.getOperataionSubtypeArg())) + then result = intToCipherOperationSubtype(getEncConfigValue(this.getOperataionSubtypeArg())) + else result instanceof Crypto::UnknownCipherOperationSubtype + } +} + +abstract class EVP_EX_Initializer extends EVP_Cipher_Inititalizer { + override Expr getKeyArg() { result = this.(Call).getArgument(3) } + + override Expr getIVArg() { result = this.(Call).getArgument(4) } +} + +abstract class EVP_EX2_Initializer extends EVP_Cipher_Inititalizer { + override Expr getKeyArg() { result = this.(Call).getArgument(2) } + + override Expr getIVArg() { result = this.(Call).getArgument(3) } +} + +class EVP_Cipher_EX_Init_Call extends EVP_EX_Initializer { + EVP_Cipher_EX_Init_Call() { + this.(Call).getTarget().getName() in [ + "EVP_EncryptInit_ex", "EVP_DecryptInit_ex", "EVP_CipherInit_ex" + ] + } + + override Expr getOperataionSubtypeArg() { + this.(Call).getTarget().getName().toLowerCase().matches("%cipherinit%") and + result = this.(Call).getArgument(5) + } +} + +// abstract class EVP_CipherInit extends EVP_Cipher_Inititalizer{ +// abstract Expr getOperataionSubtypeArg(); +// } +// class EVP_CipherInit_ex_Call extends EVP_EX_Initializer, EVP_CipherInit { +// EVP_CipherInit_ex_Call() { this.(Call).getTarget().getName() = "EVP_CipherInit_ex" } +// override Crypto::CipherOperationSubtype getCipherOperationSubtype() { +// result instanceof Crypto::EncryptionSubtype +// } +// override Expr getOperataionSubtypeArg(){ +// result = this.(Call).getArgument(5) +// } +// } +// class EVP_CipherInit_ex2_Call extends EVP_EX_Initializer, EVP_CipherInit { +// EVP_CipherInit_ex2_Call() { this.(Call).getTarget().getName() = "EVP_CipherInit_ex2" } +// override Crypto::CipherOperationSubtype getCipherOperationSubtype() { +// result instanceof Crypto::EncryptionSubtype +// } +// override Expr getOperataionSubtypeArg(){ +// result = this.(Call).getArgument(4) +// } +// } +class EVP_Cipher_EX2_or_Simple_Init_Call extends EVP_EX2_Initializer { + EVP_Cipher_EX2_or_Simple_Init_Call() { + this.(Call).getTarget().getName() in [ + "EVP_EncryptInit_ex2", "EVP_DecryptInit_ex2", "EVP_CipherInit_ex2", + "EVP_EncryptInit", "EVP_DecryptInit", "EVP_CipherInit" + ] + } + + + override Expr getOperataionSubtypeArg() { + this.(Call).getTarget().getName().toLowerCase().matches("%cipherinit%") and + result = this.(Call).getArgument(4) + } +} + +class EVP_CipherInit_SKEY_Call extends EVP_EX2_Initializer { + EVP_CipherInit_SKEY_Call() { + this.(Call).getTarget().getName() in [ + "EVP_CipherInit_SKEY" + ] + } + + override Expr getOperataionSubtypeArg() { + result = this.(Call).getArgument(5) + } +} + + +// class EVP_CipherInit extends EVP_Cipher_Inititalizer { +// EVP_CipherInit() { this.(Call).getTarget().getName() = "EVP_CipherInit" } +// override Expr getKeyArg() { result = this.(Call).getArgument(2) } +// override Expr getIVArg() { result = this.(Call).getArgument(3) } +// override Crypto::CipherOperationSubtype getCipherOperationSubtype() { +// result instanceof Crypto::EncryptionSubtype +// } +// } +class EVPCipherInitializerAlgorithmArgument extends Expr { + EVPCipherInitializerAlgorithmArgument() { + exists(EVP_Cipher_Inititalizer initCall | this = initCall.getAlgorithmArg()) + } +} +class EVPCipherInitializerKeyArgument extends Expr { + EVPCipherInitializerKeyArgument() { + exists(EVP_Cipher_Inititalizer initCall | this = initCall.getKeyArg()) + } +} +class EVPCipherInitializerIVArgument extends Expr { + EVPCipherInitializerIVArgument() { exists(EVP_Cipher_Inititalizer initCall | this = initCall.getIVArg()) } +} + diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll new file mode 100644 index 000000000000..4913d2763e96 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll @@ -0,0 +1,87 @@ +import experimental.Quantum.Language +import CtxFlow as CTXFlow +import EVPCipherInitializer +import EVPCipherConsumers + +//https://docs.openssl.org/master/man3/EVP_EncryptInit/#synopsis +abstract class EVP_Cipher_Operation extends Crypto::CipherOperationInstance instanceof Call { + Expr getContextArg() { result = this.(Call).getArgument(0) } + + abstract Expr getInputArg(); + + Expr getOutputArg() { result = this.(Call).getArgument(1) } + + override Crypto::CipherOperationSubtype getCipherOperationSubtype() { + result instanceof Crypto::EncryptionSubtype and + this.(Call).getTarget().getName().toLowerCase().matches("%encrypt%") + or + result instanceof Crypto::DecryptionSubtype and + this.(Call).getTarget().getName().toLowerCase().matches("%decrypt%") + or + result = this.getInitCall().getCipherOperationSubtype() and + this.(Call).getTarget().getName().toLowerCase().matches("%cipher%") + } + + EVP_Cipher_Inititalizer getInitCall() { + CTXFlow::ctxFlowsTo(result.getContextArg(), this.getContextArg()) + } + + override Crypto::NonceArtifactConsumer getNonceConsumer() { + this.getInitCall().getIVArg() = result + } + + override Crypto::CipherInputConsumer getInputConsumer() { this.getInputArg() = result } + + override Crypto::CipherOutputArtifactInstance getOutputArtifact() { this.getOutputArg() = result } + + override Crypto::AlgorithmConsumer getAlgorithmConsumer() { + this.getInitCall().getAlgorithmArg() = result + } +} + +abstract class EVP_Update_Call extends EVP_Cipher_Operation { } + +abstract class EVP_Final_Call extends EVP_Cipher_Operation { + override Expr getInputArg() { none() } +} + +class EVP_Cipher_Call extends EVP_Cipher_Operation { + // TODO/QUESTION: what is the better way to do this? + EVP_Cipher_Call() { this.(Call).getTarget().getName() = "EVP_Cipher" } + + override Expr getInputArg() { result = this.(Call).getArgument(2) } +} + +class EVP_Encrypt_Decrypt_or_Cipher_Update_Call extends EVP_Update_Call { + // TODO/QUESTION: what is the better way to do this? + EVP_Encrypt_Decrypt_or_Cipher_Update_Call() { + this.(Call).getTarget().getName() in [ + "EVP_EncryptUpdate", "EVP_DecryptUpdate", "EVP_CipherUpdate" + ] + } + + override Expr getInputArg() { result = this.(Call).getArgument(3) } +} + +class EVP_Encrypt_Decrypt_or_Cipher_Final_Call extends EVP_Final_Call { + // TODO/QUESTION: what is the better way to do this? + EVP_Encrypt_Decrypt_or_Cipher_Final_Call() { + this.(Call).getTarget().getName() in + [ + "EVP_EncryptFinal_ex", "EVP_DecryptFinal_ex", "EVP_CipherFinal_ex", "EVP_EncryptFinal", + "EVP_DecryptFinal", "EVP_CipherFinal" + ] + } +} + +class EVPCipherOutput extends CipherOutputArtifact { + EVPCipherOutput() { exists(EVP_Cipher_Operation op | op.getOutputArg() = this) } + + override DataFlow::Node getOutputNode(){ + result.asExpr() = this + } +} + +class EVPCipherInputArgument extends Expr { + EVPCipherInputArgument() { exists(EVP_Cipher_Operation op | op.getInputArg() = this) } +} \ No newline at end of file diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll new file mode 100644 index 000000000000..f942f4687da5 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll @@ -0,0 +1,357 @@ +import cpp +import semmle.code.cpp.dataflow.new.DataFlow + +module OpenSSLModel { + import experimental.Quantum.Language + import experimental.Quantum.OpenSSL.EVPCipherOperation + +// // TODO: trace CTX from init variants to the context arg of EVP update calls +// //https://docs.openssl.org/master/man3/EVP_EncryptInit/#synopsis +// abstract class EVP_Cipher_Init_Call extends Call { +// Expr getContextArg() { result = this.getArgument(0) } +// abstract Expr getKeyArg(); + +// abstract Expr getIVArg(); + +// abstract Crypto::CipherOperationSubtype getCipherOperationSubtype(); +// } + +// abstract class EVP_Cipher_EX_Init_Call extends EVP_Cipher_Init_Call { +// override Expr getKeyArg() { result = this.getArgument(3) } + +// override Expr getIVArg() { result = this.getArgument(4) } +// } + +// abstract class EVP_Cipher_EX2_Init_Call extends EVP_Cipher_Init_Call { +// override Expr getKeyArg() { result = this.getArgument(2) } + +// override Expr getIVArg() { result = this.getArgument(3) } +// } + +// abstract class EVP_Cipher_Operation_Call extends Crypto::CipherOperationInstance instanceof Call { +// Expr getContextArg() { result = this.(Call).getArgument(0) } +// abstract Expr getInputArg(); +// Expr getOutputArg() { result = this.(Call).getArgument(1) } +// abstract Expr getInitCall(); +// } + +// abstract class EVP_Update_Call extends EVP_Cipher_Operation_Call { +// override Expr getInputArg() { result = this.(Call).getArgument(3) } + +// } + +// abstract class EVP_Final_Call extends EVP_Cipher_Operation_Call{ +// override Expr getInputArg() { none() } + +// } + +// class EVP_Cipher_Call extends EVP_Cipher_Operation_Call{ +// // TODO/QUESTION: what is the better way to do this? +// EVP_Cipher_Call() { this.(Call).getTarget().getName() = "EVP_Cipher" } + +// override Expr getInputArg() { result = this.(Call).getArgument(2) } + +// override Expr getOutputArg() { result = this.(Call).getArgument(1) } + +// override Crypto::CipherOperationSubtype getCipherOperationSubtype(){ +// result instanceof Crypto::EncryptionSubtype +// } + +// override Expr getInitCall(){ +// //TODO: +// none() +// } + +// override Crypto::NonceArtifactConsumer getNonceConsumer(){ +// none() +// } + +// override Crypto::CipherInputConsumer getInputConsumer(){ +// none() +// } + +// override Crypto::CipherOutputArtifactInstance getOutputArtifact(){ +// none() +// } + +// override Crypto::AlgorithmConsumer getAlgorithmConsumer(){ +// none() +// } +// } + + + //TODO: what about EVP_CIpher + + + // class EVP_EncryptUpdateCall extends Crypto::CipherOperationInstance instanceof Call { + // // NICK QUESTION: is there a better way to tie this to openssl? + // EVP_EncryptUpdateCall() { this.getTarget().getName() = "EVP_EncryptUpdate" } + + // Expr getContextArg() { result = super.getArgument(0) } + + // Expr getInputArg() { result = super.getArgument(3) } + + // Expr getOutputArg() { result = super.getArgument(1) } + + // override Crypto::CipherOperationSubtype getCipherOperationSubtype(){ + // result instanceof Crypto::EncryptionSubtype + // } + + // override Crypto::NonceArtifactConsumer getNonceConsumer(){ + // none() + // } + + // override Crypto::CipherInputConsumer getInputConsumer(){ + // none() + // } + + // override Crypto::CipherOutputArtifactInstance getOutputArtifact(){ + // none() + // } + + // override Crypto::AlgorithmConsumer getAlgorithmConsumer(){ + // none() + // } + + // } + + //EVP_EncryptUpdate + + // /** + // * Hash function references in OpenSSL. + // */ + // predicate hash_ref_type_mapping_known(string name, Crypto::THashType algo) { + // // `ma` name has an LN_ or SN_ prefix, which we want to ignore + // // capture any name after the _ prefix using regex matching + // name = ["sha1", "sha160"] and algo instanceof Crypto::SHA1 + // or + // name = ["sha224", "sha256", "sha384", "sha512"] and algo instanceof Crypto::SHA2 + // or + // name = ["sha3-224", "sha3-256", "sha3-384", "sha3-512"] and algo instanceof Crypto::SHA3 + // or + // name = "md2" and algo instanceof Crypto::MD2 + // or + // name = "md4" and algo instanceof Crypto::MD4 + // or + // name = "md5" and algo instanceof Crypto::MD5 + // or + // name = "ripemd160" and algo instanceof Crypto::RIPEMD160 + // or + // name = "whirlpool" and algo instanceof Crypto::WHIRLPOOL + // } + + // predicate hash_ref_type_mapping(FunctionCallOrMacroAccess ref, string name, Crypto::THashType algo) { + // name = ref.getTargetName().regexpCapture("(?:SN_|LN_|EVP_)([a-z0-9]+)", 1) and + // hash_ref_type_mapping_known(name, algo) + // } + + // class FunctionCallOrMacroAccess extends Element { + // FunctionCallOrMacroAccess() { this instanceof FunctionCall or this instanceof MacroAccess } + + // string getTargetName() { + // result = this.(FunctionCall).getTarget().getName() + // or + // result = this.(MacroAccess).getMacroName() + // } + // } + + // class HashAlgorithmCallOrMacro extends Crypto::HashAlgorithmInstance instanceof FunctionCallOrMacroAccess + // { + // HashAlgorithmCallOrMacro() { hash_ref_type_mapping(this, _, _) } + + // string getTargetName() { result = this.(FunctionCallOrMacroAccess).getTargetName() } + // } + + // class HashAlgorithm extends Crypto::HashAlgorithm { + // HashAlgorithmCallOrMacro instance; + + // HashAlgorithm() { this = Crypto::THashAlgorithm(instance) } + + // override string getSHA2OrSHA3DigestSize(Location location) { + // ( + // this.getHashType() instanceof Crypto::SHA2 or + // this.getHashType() instanceof Crypto::SHA3 + // ) and + // exists(string name | + // hash_ref_type_mapping(instance, name, this.getHashType()) and + // result = name.regexpFind("\\d{3}", 0, _) and + // location = instance.getLocation() + // ) + // } + + // override string getRawAlgorithmName() { result = instance.getTargetName() } + + // override Crypto::THashType getHashType() { hash_ref_type_mapping(instance, _, result) } + + // Element getInstance() { result = instance } + + // override Location getLocation() { result = instance.getLocation() } + // } + + // /** + // * Data-flow configuration for key derivation algorithm flow to EVP_KDF_derive. + // */ + // module AlgorithmToEVPKeyDeriveConfig implements DataFlow::ConfigSig { + // predicate isSource(DataFlow::Node source) { + // source.asExpr() = any(KeyDerivationAlgorithm a).getInstance() + // } + + // predicate isSink(DataFlow::Node sink) { + // exists(EVP_KDF_derive kdo | + // sink.asExpr() = kdo.getCall().getAlgorithmArg() + // or + // sink.asExpr() = kdo.getCall().getContextArg() // via `EVP_KDF_CTX_set_params` + // ) + // } + + // predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + // none() // TODO + // } + // } + + // module AlgorithmToEVPKeyDeriveFlow = DataFlow::Global; + + // predicate algorithm_to_EVP_KDF_derive(KeyDerivationAlgorithm algo, EVP_KDF_derive derive) { + // none() + // } + + // /** + // * Key derivation operation (e.g., `EVP_KDF_derive`) + // */ + // class EVP_KDF_derive_FunctionCall extends Crypto::KeyDerivationOperationInstance instanceof FunctionCall + // { + // EVP_KDF_derive_FunctionCall() { this.getTarget().getName() = "EVP_KDF_derive" } + + // Expr getAlgorithmArg() { result = super.getArgument(3) } + + // Expr getContextArg() { result = super.getArgument(0) } + // } + + // class EVP_KDF_derive extends Crypto::KeyDerivationOperation { + // EVP_KDF_derive_FunctionCall instance; + + // EVP_KDF_derive() { this = Crypto::TKeyDerivationOperation(instance) } + + // override Crypto::Algorithm getAlgorithm() { algorithm_to_EVP_KDF_derive(result, this) } + + // EVP_KDF_derive_FunctionCall getCall() { result = instance } + // } + + // /** + // * Key derivation algorithm nodes + // */ + // abstract class KeyDerivationAlgorithm extends Crypto::KeyDerivationAlgorithm { + // abstract Expr getInstance(); + // } + + // /** + // * `EVP_KDF_fetch` returns a key derivation algorithm. + // */ + // class EVP_KDF_fetch_Call extends FunctionCall { + // EVP_KDF_fetch_Call() { this.getTarget().getName() = "EVP_KDF_fetch" } + + // Expr getAlgorithmArg() { result = this.getArgument(1) } + // } + + // class EVP_KDF_fetch_AlgorithmArg extends Crypto::KeyDerivationAlgorithmInstance instanceof Expr { + // EVP_KDF_fetch_AlgorithmArg() { exists(EVP_KDF_fetch_Call call | this = call.getAlgorithmArg()) } + // } + + // predicate kdf_names(string algo) { algo = ["HKDF", "PKCS12KDF", "PBKDF2"] } + + // class KDFAlgorithmStringLiteral extends StringLiteral { + // KDFAlgorithmStringLiteral() { kdf_names(this.getValue().toUpperCase()) } + // } + + // private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { + // predicate isSource(DataFlow::Node src) { src.asExpr() instanceof KDFAlgorithmStringLiteral } + + // predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof EVP_KDF_fetch_AlgorithmArg } + // } + + // module AlgorithmStringToFetchFlow = DataFlow::Global; + + // predicate algorithmStringToKDFFetchArgFlow( + // string name, KDFAlgorithmStringLiteral origin, EVP_KDF_fetch_AlgorithmArg arg + // ) { + // origin.getValue().toUpperCase() = name and + // AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), DataFlow::exprNode(arg)) + // } + + // /** + // * HKDF key derivation algorithm. + // */ + // class HKDF extends KeyDerivationAlgorithm, Crypto::HKDF { + // KDFAlgorithmStringLiteral origin; + // EVP_KDF_fetch_AlgorithmArg instance; + + // HKDF() { + // this = Crypto::TKeyDerivationAlgorithm(instance) and + // algorithmStringToKDFFetchArgFlow("HKDF", origin, instance) + // } + + // override string getRawAlgorithmName() { result = origin.getValue() } + + // override Crypto::HashAlgorithm getHashAlgorithm() { none() } + + // override Crypto::LocatableElement getOrigin(string name) { + // result = origin and name = origin.toString() + // } + + // override Expr getInstance() { result = origin } + // } + + // /** + // * PBKDF2 key derivation algorithm. + // */ + // class PBKDF2 extends KeyDerivationAlgorithm, Crypto::PBKDF2 { + // KDFAlgorithmStringLiteral origin; + // EVP_KDF_fetch_AlgorithmArg instance; + + // PBKDF2() { + // this = Crypto::TKeyDerivationAlgorithm(instance) and + // algorithmStringToKDFFetchArgFlow("PBKDF2", origin, instance) + // } + + // override string getRawAlgorithmName() { result = origin.getValue() } + + // override string getIterationCount(Location location) { none() } // TODO + + // override string getKeyLength(Location location) { none() } // TODO + + // override Crypto::HashAlgorithm getHashAlgorithm() { none() } // TODO + + // override Crypto::LocatableElement getOrigin(string name) { + // result = origin and name = origin.toString() + // } + + // override Expr getInstance() { result = instance } + // } + + // /** + // * PKCS12KDF key derivation algorithm. + // */ + // class PKCS12KDF extends KeyDerivationAlgorithm, Crypto::PKCS12KDF { + // KDFAlgorithmStringLiteral origin; + // EVP_KDF_fetch_AlgorithmArg instance; + + // PKCS12KDF() { + // this = Crypto::TKeyDerivationAlgorithm(instance) and + // algorithmStringToKDFFetchArgFlow("PKCS12KDF", origin, instance) + // } + + // override string getRawAlgorithmName() { result = origin.getValue() } + + // override string getIterationCount(Location location) { none() } // TODO + + // override string getIDByte(Location location) { none() } // TODO + + // override Crypto::HashAlgorithm getHashAlgorithm() { none() } // TODO + + // override Crypto::LocatableElement getOrigin(string name) { + // result = origin and name = origin.toString() + // } + + // override Expr getInstance() { result = instance } + // } +} From de3ff45cba87043af0709026cdc9eccda4404710 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Wed, 5 Mar 2025 15:17:52 -0500 Subject: [PATCH 041/336] Misc updates for OpenSSL modeling to trace algorithm literals to known alg getters, and converting the literal to a TCipherType. --- cpp/ql/lib/experimental/Quantum/Language.qll | 22 +- .../experimental/Quantum/OpenSSL/CtxFlow.qll | 15 +- .../OpenSSL/EVPCipherAlgorithmSource.qll | 148 ++++++ .../Quantum/OpenSSL/EVPCipherConsumers.qll | 4 +- .../Quantum/OpenSSL/LibraryDetector.qll | 10 + .../OpenSSL/OpenSSLAlgorithmGetter.qll | 436 ++++++++++++++++++ ...qll => OpenSSLKnownAlgorithmConstants.qll} | 103 +---- .../codeql/cryptography/Model.qll | 62 +-- 8 files changed, 651 insertions(+), 149 deletions(-) create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/LibraryDetector.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll rename cpp/ql/lib/experimental/Quantum/OpenSSL/{AlgorithmSource.qll => OpenSSLKnownAlgorithmConstants.qll} (96%) diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index 3f1d9aa9bdf3..5d4ff4bc6863 100644 --- a/cpp/ql/lib/experimental/Quantum/Language.qll +++ b/cpp/ql/lib/experimental/Quantum/Language.qll @@ -49,19 +49,19 @@ module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { -// TODO: I think this will be inefficient, no? -class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource instanceof Literal { - override DataFlow::Node getOutputNode() { - result.asExpr() = this - } +// // TODO: I think this will be inefficient, no? +// class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource instanceof Literal { +// override DataFlow::Node getOutputNode() { +// result.asExpr() = this +// } - override predicate flowsTo(Crypto::FlowAwareElement other) { - // TODO: separate config to avoid blowing up data-flow analysis - GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) - } +// override predicate flowsTo(Crypto::FlowAwareElement other) { +// // TODO: separate config to avoid blowing up data-flow analysis +// GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) +// } - override string getAdditionalDescription() { result = this.toString() } -} +// override string getAdditionalDescription() { result = this.toString() } +// } /** * Definitions of various generic data sources diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll index 54be40729b6f..e1b08c9652d8 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll @@ -8,17 +8,14 @@ class CTXType extends Type { } class CTXPointerExpr extends Expr { - CTXPointerExpr() { - this.getType() instanceof CTXType and - this.getType() instanceof PointerType + CTXPointerExpr() { + this.getType() instanceof CTXType and + this.getType() instanceof PointerType } } class CTXPointerArgument extends CTXPointerExpr { - CTXPointerArgument() { - - exists(Call c | c.getAnArgument() = this) - } + CTXPointerArgument() { exists(Call c | c.getAnArgument() = this) } Call getCall() { result.getAnArgument() = this } } @@ -31,14 +28,14 @@ class CTXClearCall extends Call { } class CTXCopyOutArgCall extends Call { - CTXCopyOutArgCall() { + CTXCopyOutArgCall() { this.getTarget().getName().toLowerCase().matches(["%copy%"]) and this.getAnArgument() instanceof CTXPointerArgument } } class CTXCopyReturnCall extends Call { - CTXCopyReturnCall() { + CTXCopyReturnCall() { this.getTarget().getName().toLowerCase().matches(["%dup%"]) and this.getAnArgument() instanceof CTXPointerArgument and this instanceof CTXPointerExpr diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll new file mode 100644 index 000000000000..046abf3f43a9 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll @@ -0,0 +1,148 @@ +import cpp +import experimental.Quantum.Language +import EVPCipherConsumers +import OpenSSLAlgorithmGetter + +predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) { + exists(string name, string algType | algType.toLowerCase().matches("%encryption") | + resolveAlgorithmFromLiteral(e, name, algType) and + ( + name.matches("AES%") and type instanceof Crypto::AES + or + name.matches("ARIA") and type instanceof Crypto::ARIA + or + name.matches("BLOWFISH") and type instanceof Crypto::BLOWFISH + or + name.matches("BF") and type instanceof Crypto::BLOWFISH + or + name.matches("CAMELLIA%") and type instanceof Crypto::CAMELLIA + or + name.matches("CHACHA20") and type instanceof Crypto::CHACHA20 + or + name.matches("CAST5") and type instanceof Crypto::CAST5 + or + name.matches("2DES") and type instanceof Crypto::DOUBLEDES + or + name.matches(["3DES", "TRIPLEDES"]) and type instanceof Crypto::TRIPLEDES + or + name.matches("DES") and type instanceof Crypto::DES + or + name.matches("DESX") and type instanceof Crypto::DESX + or + name.matches("GOST%") and type instanceof Crypto::GOST + or + name.matches("IDEA") and type instanceof Crypto::IDEA + or + name.matches("KUZNYECHIK") and type instanceof Crypto::KUZNYECHIK + or + name.matches("MAGMA") and type instanceof Crypto::MAGMA + or + name.matches("RC2") and type instanceof Crypto::RC2 + or + name.matches("RC4") and type instanceof Crypto::RC4 + or + name.matches("RC5") and type instanceof Crypto::RC5 + or + name.matches("RSA") and type instanceof Crypto::RSA + or + name.matches("SEED") and type instanceof Crypto::SEED + or + name.matches("SM4") and type instanceof Crypto::SM4 + ) + ) +} + +class CipherKnownAlgorithmLiteralAlgorithmInstance extends Crypto::CipherAlgorithmInstance instanceof Literal +{ + CipherKnownAlgorithmLiteralAlgorithmInstance() { + exists(EVPCipherGetterCall c, DataFlow::Node src, DataFlow::Node sink | + sink = c.getValueArgNode() and + src.asExpr() = this and + KnownAlgorithmLiteralToAlgorithmGetterFlow::flow(src, sink) and + // Not just any known value, but specifically a known cipher operation + exists(string algType | + resolveAlgorithmFromLiteral(src.asExpr(), _, algType) and + algType.toLowerCase().matches("%encryption") + ) + ) + } + + Crypto::AlgorithmConsumer getConsumer() { none() } //result = consumer } + + override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { + none() // TODO: provider defaults + } + + override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { none() } + + override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } + + override Crypto::TCipherType getCipherFamily() { literalToCipherFamilyType(this, result) } +} +// override Crypto::TCipherType getCipherFamily() { +// if this.cipherNameMappingKnown(_, super.getAlgorithmName()) +// then this.cipherNameMappingKnown(result, super.getAlgorithmName()) +// else result instanceof Crypto::OtherCipherType +// } +// bindingset[name] +// private predicate cipherNameMappingKnown(Crypto::TCipherType type, string name) { +// name = "AES" and +// type instanceof Crypto::AES +// or +// name = "DES" and +// type instanceof Crypto::DES +// or +// name = "TripleDES" and +// type instanceof Crypto::TripleDES +// or +// name = "IDEA" and +// type instanceof Crypto::IDEA +// or +// name = "CAST5" and +// type instanceof Crypto::CAST5 +// or +// name = "ChaCha20" and +// type instanceof Crypto::ChaCha20 +// or +// name = "RC4" and +// type instanceof Crypto::RC4 +// or +// name = "RC5" and +// type instanceof Crypto::RC5 +// or +// name = "RSA" and +// type instanceof Crypto::RSA +// } +// private predicate modeToNameMappingKnown(Crypto::TBlockCipherModeOperationType type, string name) { +// type instanceof Crypto::ECB and name = "ECB" +// or +// type instanceof Crypto::CBC and name = "CBC" +// or +// type instanceof Crypto::GCM and name = "GCM" +// or +// type instanceof Crypto::CTR and name = "CTR" +// or +// type instanceof Crypto::XTS and name = "XTS" +// or +// type instanceof Crypto::CCM and name = "CCM" +// or +// type instanceof Crypto::SIV and name = "SIV" +// or +// type instanceof Crypto::OCB and name = "OCB" +// } +// override Crypto::TBlockCipherModeOperationType getModeType() { +// if this.modeToNameMappingKnown(_, super.getMode()) +// then this.modeToNameMappingKnown(result, super.getMode()) +// else result instanceof Crypto::OtherMode +// } +// override string getRawModeAlgorithmName() { result = super.getMode() } +// override string getRawPaddingAlgorithmName() { result = super.getPadding() } +// bindingset[name] +// private predicate paddingToNameMappingKnown(Crypto::TPaddingType type, string name) { +// type instanceof Crypto::NoPadding and name = "NOPADDING" +// or +// type instanceof Crypto::PKCS7 and name = ["PKCS5Padding", "PKCS7Padding"] // TODO: misnomer in the JCA? +// or +// type instanceof Crypto::OAEP and name.matches("OAEP%") // TODO: handle OAEPWith% +// } +// } diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll index ceabae77374c..8717a857385a 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll @@ -1,6 +1,6 @@ import EVPCipherInitializer import EVPCipherOperation -import AlgorithmSource +import EVPCipherAlgorithmSource class EVP_Cipher_Initializer_Algorithm_Consumer extends Crypto::AlgorithmConsumer instanceof EVPCipherInitializerAlgorithmArgument @@ -8,7 +8,7 @@ class EVP_Cipher_Initializer_Algorithm_Consumer extends Crypto::AlgorithmConsume override DataFlow::Node getInputNode() { result.asExpr() = this } override Crypto::AlgorithmElement getAKnownAlgorithmSource() { - result.(CipherLiteralAlgorithmInstance).getConsumer() = this + result.(CipherKnownAlgorithmLiteralAlgorithmInstance).getConsumer() = this } } // //TODO: need a key consumer diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/LibraryDetector.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/LibraryDetector.qll new file mode 100644 index 000000000000..3cd359ce58b3 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/LibraryDetector.qll @@ -0,0 +1,10 @@ +import cpp + +predicate isPossibleOpenSSLFunction(Function f) { + isPossibleOpenSSLLocation(f.getADeclarationLocation()) + } + +predicate isPossibleOpenSSLLocation(Location l){ + l.toString().toLowerCase().matches("%openssl%") +} + \ No newline at end of file diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll new file mode 100644 index 000000000000..79491ca2a09d --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll @@ -0,0 +1,436 @@ +import cpp +import semmle.code.cpp.dataflow.new.DataFlow +import LibraryDetector +import OpenSSLKnownAlgorithmConstants + +abstract class AlgorithmPassthroughCall extends Call { + abstract DataFlow::Node getInNode(); + + abstract DataFlow::Node getOutNode(); +} + +class CopyAndDupAlgorithmPassthroughCall extends AlgorithmPassthroughCall { + DataFlow::Node inNode; + DataFlow::Node outNode; + + CopyAndDupAlgorithmPassthroughCall() { + // Flow out through any return or other argument of the same type + // Assume flow in and out is asIndirectExpr or asDefinitingArgument since a pointer is assumed + // to be involved + // NOTE: not attempting to detect openssl specific copy/dup functions, but anything suspected to be copy/dup + this.getTarget().getName().toLowerCase().matches(["%_dup", "%_copy"]) and + exists(Expr inArg, Type t | + inArg = this.getAnArgument() and t = inArg.getUnspecifiedType().stripType() + | + inNode.asIndirectExpr() = inArg and + ( + // Case 1: flow through another argument as an out arg of the same type + exists(Expr outArg | + outArg = this.getAnArgument() and + outArg != inArg and + outArg.getUnspecifiedType().stripType() = t + | + outNode.asDefiningArgument() = outArg + ) + or + // Case 2: flow through the return value if the result is the same as the intput type + exists(Expr outArg | outArg = this and outArg.getUnspecifiedType().stripType() = t | + outNode.asIndirectExpr() = outArg + ) + ) + ) + } + + override DataFlow::Node getInNode() { result = inNode } + + override DataFlow::Node getOutNode() { result = outNode } +} + +class NIDToPointerPassthroughCall extends AlgorithmPassthroughCall { + DataFlow::Node inNode; + DataFlow::Node outNode; + + NIDToPointerPassthroughCall() { + this.getTarget().getName() in ["OBJ_nid2obj", "OBJ_nid2ln", "OBJ_nid2sn"] and + inNode.asExpr() = this.getArgument(0) and + outNode.asExpr() = this + //outNode.asIndirectExpr() = this + } + + override DataFlow::Node getInNode() { result = inNode } + + override DataFlow::Node getOutNode() { result = outNode } +} + +class PointerToPointerPassthroughCall extends AlgorithmPassthroughCall { + DataFlow::Node inNode; + DataFlow::Node outNode; + + PointerToPointerPassthroughCall() { + this.getTarget().getName() = "OBJ_txt2obj" and + inNode.asIndirectExpr() = this.getArgument(0) and + outNode.asIndirectExpr() = this + or + //outNode.asExpr() = this + this.getTarget().getName() in ["OBJ_obj2txt", "i2t_ASN1_OBJECT"] and + inNode.asIndirectExpr() = this.getArgument(2) and + outNode.asDefiningArgument() = this.getArgument(0) + } + + override DataFlow::Node getInNode() { result = inNode } + + override DataFlow::Node getOutNode() { result = outNode } +} + +class PointerToNIDPassthroughCall extends AlgorithmPassthroughCall { + DataFlow::Node inNode; + DataFlow::Node outNode; + + PointerToNIDPassthroughCall() { + this.getTarget().getName() in ["OBJ_obj2nid", "OBJ_ln2nid", "OBJ_sn2nid", "OBJ_txt2nid"] and + ( + inNode.asIndirectExpr() = this.getArgument(0) + or + inNode.asExpr() = this.getArgument(0) + ) and + outNode.asExpr() = this + } + + override DataFlow::Node getInNode() { result = inNode } + + override DataFlow::Node getOutNode() { result = outNode } +} + +predicate knownPassThroughStep(DataFlow::Node node1, DataFlow::Node node2) { + exists(AlgorithmPassthroughCall c | c.getInNode() = node1 and c.getOutNode() = node2) +} + +abstract class OpenSSLAlgorithmGetterCall extends Call { + abstract DataFlow::Node getValueArgNode(); + + abstract DataFlow::Node getResultNode(); + + abstract Expr getValueArgExpr(); + + abstract Expr getResultExpr(); +} + +module KnownAlgorithmLiteralToAlgorithmGetterConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + ( + source.asExpr() instanceof Literal and + // 0 sources, for nid are unknown, and 0 otherwise represents a null assignment (ignore as unknown) + exists(source.asExpr().(Literal).getValue().toInt()) implies source.asExpr().(Literal).getValue().toInt() != 0 + //resolveAlgorithmFromLiteral(source.asExpr(),_,_) + ) + } + + predicate isSink(DataFlow::Node sink) { + exists(OpenSSLAlgorithmGetterCall c | c.getValueArgNode() = sink) + } + + predicate isBarrier(DataFlow::Node node) { + // False positive reducer, don't flow out through argv + exists(VariableAccess va, Variable v | + v.getAnAccess() = va and va = node.asExpr() + or + va = node.asIndirectExpr() + | + v.getName().matches("%argv") + ) + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + knownPassThroughStep(node1, node2) + } +} + +module KnownAlgorithmLiteralToAlgorithmGetterFlow = + DataFlow::Global; + +// https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html +class EVPCipherGetterCall extends OpenSSLAlgorithmGetterCall { + DataFlow::Node valueArgNode; + DataFlow::Node resultNode; + Expr valueArgExpr; + Expr resultExpr; + + EVPCipherGetterCall() { + // Flow out through the return pointer itself (trace the pointer, not what it is pointing to) + resultExpr = this and + resultNode.asExpr() = this and + ( + this.getTarget().getName() in ["EVP_get_cipherbyname", "EVP_get_cipherbyobj"] and + valueArgExpr = this.getArgument(0) and + valueArgNode.asExpr() = valueArgExpr + or + this.getTarget().getName() = "EVP_CIPHER_fetch" and + valueArgExpr = this.getArgument(1) and + valueArgNode.asExpr() = valueArgExpr + or + this.getTarget().getName() = "EVP_get_cipherbynid" and + valueArgExpr = this.getArgument(0) and + valueArgNode.asExpr() = valueArgExpr + ) + } + + override DataFlow::Node getValueArgNode() { result = valueArgNode } + + override DataFlow::Node getResultNode() { result = resultNode } + + override Expr getValueArgExpr() { result = valueArgExpr } + + override Expr getResultExpr() { result = resultExpr } +} +// /** +// * Predicates/classes for identifying algorithm sinks. +// * An Algorithm Sink is a function that takes an algorithm as an argument. +// * In particular, any function that takes in an algorithm that until the call +// * the algorithm is not definitely known to be an algorithm (e.g., an integer used as an identifier to fetch an algorithm) +// */ +// //TODO: enforce a hierarchy of AlgorithmSinkArgument, e.g., so I can get all Asymmetric SinkArguments that includes all the strictly RSA etc. +// import cpp +// // import experimental.cryptography.utils.OpenSSL.LibraryFunction +// // import experimental.cryptography.CryptoAlgorithmNames +// predicate isAlgorithmSink(AlgorithmSinkArgument arg, string algType) { arg.algType() = algType } +// abstract class AlgorithmSinkArgument extends Expr { +// AlgorithmSinkArgument() { +// exists(Call c | c.getAnArgument() = this and openSSLLibraryFunc(c.getTarget())) +// } +// /** +// * Gets the function call in which the argument exists +// */ +// Call getSinkCall() { result.getAnArgument() = this } +// abstract string algType(); +// } +// // https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html +// predicate cipherAlgorithmSink(string funcName, int argInd) { +// funcName in ["EVP_get_cipherbyname", "EVP_get_cipherbynid", "EVP_get_cipherbyobj"] and argInd = 0 +// or +// funcName = "EVP_CIPHER_fetch" and argInd = 1 +// } +// class CipherAlgorithmSink extends AlgorithmSinkArgument { +// CipherAlgorithmSink() { +// exists(Call c, string funcName, int argInd | +// funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// | +// cipherAlgorithmSink(funcName, argInd) +// ) +// } +// override string algType() { result = getSymmetricEncryptionType() } +// } +// // https://www.openssl.org/docs/manmaster/man3/EVP_MAC_fetch +// predicate macAlgorithmSink(string funcName, int argInd) { +// (funcName = "EVP_MAC_fetch" and argInd = 1) +// } +// class MACAlgorithmSink extends AlgorithmSinkArgument { +// MACAlgorithmSink() { +// exists(Call c, string funcName, int argInd | +// funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// | +// macAlgorithmSink(funcName, argInd) +// ) +// } +// override string algType() { result = "TBD" } +// } +// // https://www.openssl.org/docs/manmaster/man3/EVP_MD_fetch +// predicate messageDigestAlgorithmSink(string funcName, int argInd) { +// funcName in ["EVP_get_digestbyname", "EVP_get_digestbynid", "EVP_get_digestbyobj"] and argInd = 0 +// or +// funcName = "EVP_MD_fetch" and argInd = 1 +// } +// class MessageDigestAlgorithmSink extends AlgorithmSinkArgument { +// MessageDigestAlgorithmSink() { +// exists(Call c, string funcName, int argInd | +// funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// | +// messageDigestAlgorithmSink(funcName, argInd) +// ) +// } +// override string algType() { result = getHashType() } +// } +// // https://www.openssl.org/docs/manmaster/man3/EVP_KEYEXCH_fetch +// // https://www.openssl.org/docs/manmaster/man3/EVP_KEM_fetch +// predicate keyExchangeAlgorithmSink(string funcName, int argInd) { +// funcName = "EVP_KEYEXCH_fetch" and argInd = 1 +// or +// funcName = "EVP_KEM_fetch" and argInd = 1 +// } +// class KeyExchangeAlgorithmSink extends AlgorithmSinkArgument { +// KeyExchangeAlgorithmSink() { +// exists(Call c, string funcName, int argInd | +// funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// | +// keyExchangeAlgorithmSink(funcName, argInd) +// ) +// } +// override string algType() { result = getKeyExchangeType() } +// } +// // https://www.openssl.org/docs/manmaster/man3/EVP_KEYMGMT_fetch +// predicate keyManagementAlgorithmSink(string funcName, int argInd) { +// funcName = "EVP_KEYMGMT_fetch" and argInd = 1 +// } +// class KeyManagementAlgorithmSink extends AlgorithmSinkArgument { +// KeyManagementAlgorithmSink() { +// exists(Call c, string funcName, int argInd | +// funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// | +// keyManagementAlgorithmSink(funcName, argInd) +// ) +// } +// override string algType() { result = "TBD" } +// } +// // https://www.openssl.org/docs/manmaster/man3/EVP_KDF +// predicate keyDerivationAlgorithmSink(string funcName, int argInd) { +// funcName = "EVP_KDF_fetch" and argInd = 1 +// } +// class KeyDerivationAlgorithmSink extends AlgorithmSinkArgument { +// KeyDerivationAlgorithmSink() { +// exists(Call c, string funcName, int argInd | +// funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// | +// keyDerivationAlgorithmSink(funcName, argInd) +// ) +// } +// override string algType() { result = getKeyDerivationType() } +// } +// // https://www.openssl.org/docs/manmaster/man3/EVP_ASYM_CIPHER_fetch +// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_new_id +// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_new_CMAC_key.html +// predicate asymmetricCipherAlgorithmSink(string funcName, int argInd) { +// funcName = "EVP_ASYM_CIPHER_fetch" and argInd = 1 +// or +// funcName = "EVP_PKEY_new_CMAC_key" and argInd = 3 +// // NOTE: other cases are handled by AsymmetricAlgorithmSink +// } +// class AsymmetricCipherAlgorithmSink extends AlgorithmSinkArgument { +// AsymmetricCipherAlgorithmSink() { +// exists(Call c, string funcName, int argInd | +// funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// | +// asymmetricCipherAlgorithmSink(funcName, argInd) +// ) +// } +// override string algType() { result = "ASYMMETRIC_ENCRYPTION" } +// } +// class AsymmetricCipherAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument { +// AsymmetricCipherAlgorithmSink_EVP_PKEY_Q_keygen() { +// exists(Call c, string funcName | +// funcName = c.getTarget().getName() and +// this = c.getArgument(3) +// | +// funcName = "EVP_PKEY_Q_keygen" and +// c.getArgument(3).getType().getUnderlyingType() instanceof IntegralType +// ) +// } +// override string algType() { result = "ASYMMETRIC_ENCRYPTION" } +// } +// // https://www.openssl.org/docs/manmaster/man3/EVP_RAND_fetch +// predicate randomAlgorithmSink(string funcName, int argInd) { +// funcName = "EVP_RAND_fetch" and argInd = 1 +// } +// class RandomAlgorithmSink extends AlgorithmSinkArgument { +// RandomAlgorithmSink() { +// exists(Call c, string funcName, int argInd | +// funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// | +// randomAlgorithmSink(funcName, argInd) +// ) +// } +// override string algType() { result = "TBD" } +// } +// // https://www.openssl.org/docs/manmaster/man3/EVP_SIGNATURE_fetch +// predicate signatureAlgorithmSink(string funcName, int argInd) { +// funcName = "EVP_SIGNATURE_fetch" and argInd = 1 +// } +// class SignatureAlgorithmSink extends AlgorithmSinkArgument { +// SignatureAlgorithmSink() { +// exists(Call c, string funcName, int argInd | +// funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// | +// signatureAlgorithmSink(funcName, argInd) +// ) +// } +// override string algType() { result = getSignatureType() } +// } +// // https://www.openssl.org/docs/manmaster/man3/EC_KEY_new_by_curve_name.html +// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_ec_paramgen_curve_nid.html +// predicate ellipticCurveAlgorithmSink(string funcName, int argInd) { +// funcName in ["EC_KEY_new_by_curve_name", "EVP_EC_gen"] and argInd = 0 +// or +// funcName = "EC_KEY_new_by_curve_name_ex" and argInd = 2 +// or +// funcName in ["EVP_PKEY_CTX_set_ec_paramgen_curve_nid"] and argInd = 1 +// } +// class EllipticCurveAlgorithmSink extends AlgorithmSinkArgument { +// EllipticCurveAlgorithmSink() { +// exists(Call c, string funcName, int argInd | +// funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// | +// ellipticCurveAlgorithmSink(funcName, argInd) +// ) +// } +// override string algType() { result = getEllipticCurveType() } +// } +// /** +// * Special cased to address the fact that arg index 3 (zero offset based) is the curve name. +// * ASSUMPTION: if the arg ind 3 is a char* assume it is an elliptic curve +// */ +// class EllipticCurveAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument { +// EllipticCurveAlgorithmSink_EVP_PKEY_Q_keygen() { +// exists(Call c, string funcName | +// funcName = c.getTarget().getName() and +// this = c.getArgument(3) +// | +// funcName = "EVP_PKEY_Q_keygen" and +// c.getArgument(3).getType().getUnderlyingType() instanceof PointerType and +// c.getArgument(3).getType().getUnderlyingType().stripType() instanceof CharType +// ) +// } +// override string algType() { result = getEllipticCurveType() } +// } +// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_new_id.html +// // https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_new_raw_private_key.html +// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_new.html +// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_ctrl.html +// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_Q_keygen.html +// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_ctrl.html +// predicate asymmetricAlgorithmSink(string funcName, int argInd) { +// funcName = "EVP_PKEY_CTX_new_id" and argInd = 0 +// or +// funcName = "EVP_PKEY_CTX_new_from_name" and argInd = 1 +// or +// funcName in [ +// "EVP_PKEY_new_raw_private_key", "EVP_PKEY_new_raw_public_key", "EVP_PKEY_new_mac_key" +// ] and +// argInd = 0 +// or +// funcName in ["EVP_PKEY_new_raw_private_key_ex", "EVP_PKEY_new_raw_public_key_ex"] and argInd = 1 +// or +// // special casing this as arg index 3 must be specified depending on if RSA or ECC, and otherwise not specified for other algs +// // funcName = "EVP_PKEY_Q_keygen" and argInd = 2 +// funcName in ["EVP_PKEY_CTX_ctrl", "EVP_PKEY_CTX_set_group_name"] and argInd = 1 +// // TODO consider void cases EVP_PKEY_new +// } +// class AsymmetricAlgorithmSink extends AlgorithmSinkArgument { +// AsymmetricAlgorithmSink() { +// exists(Call c, string funcName, int argInd | +// funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// | +// asymmetricAlgorithmSink(funcName, argInd) +// ) +// } +// override string algType() { result = getAsymmetricType() } +// } +// class AsymmetricAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument { +// AsymmetricAlgorithmSink_EVP_PKEY_Q_keygen() { +// exists(Call c, string funcName | +// funcName = c.getTarget().getName() and +// this = c.getArgument(2) +// | +// funcName = "EVP_PKEY_Q_keygen" and +// not exists(c.getArgument(3)) +// ) +// } +// override string algType() { result = getAsymmetricType() } +// } diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll similarity index 96% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmSource.qll rename to cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll index f409578e98d2..dcf24d01ace8 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmSource.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll @@ -1,104 +1,5 @@ import cpp -import experimental.Quantum.Language -import EVPCipherConsumers -/** - * Note: padding and a mode of operation will only exist when the padding / mode (*and its type*) are determinable. - * This is because the mode will always be specified alongside the algorithm and never independently. - * Therefore, we can always assume that a determinable algorithm will have a determinable mode. - * - * In the case that only an algorithm is specified, e.g., "AES", the provider provides a default mode. - * - * TODO: Model the case of relying on a provider default, but alert on it as a bad practice. - */ -class CipherLiteralAlgorithmInstance extends Crypto::CipherAlgorithmInstance instanceof ConstantDataSource -{ - Crypto::AlgorithmConsumer consumer; // TODO: I need to make this an open SSL algorithm consumer specifically - - CipherLiteralAlgorithmInstance() { - GenericDataSourceUniversalFlow::flow(DataFlow::exprNode(this), DataFlow::exprNode(consumer)) - } - - Crypto::AlgorithmConsumer getConsumer() { result = consumer } - - override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { - none() // TODO: provider defaults - } - - override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { none() } - - override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } - - override Crypto::TCipherType getCipherFamily() { none() } -} - -// override Crypto::TCipherType getCipherFamily() { -// if this.cipherNameMappingKnown(_, super.getAlgorithmName()) -// then this.cipherNameMappingKnown(result, super.getAlgorithmName()) -// else result instanceof Crypto::OtherCipherType -// } -// bindingset[name] -// private predicate cipherNameMappingKnown(Crypto::TCipherType type, string name) { -// name = "AES" and -// type instanceof Crypto::AES -// or -// name = "DES" and -// type instanceof Crypto::DES -// or -// name = "TripleDES" and -// type instanceof Crypto::TripleDES -// or -// name = "IDEA" and -// type instanceof Crypto::IDEA -// or -// name = "CAST5" and -// type instanceof Crypto::CAST5 -// or -// name = "ChaCha20" and -// type instanceof Crypto::ChaCha20 -// or -// name = "RC4" and -// type instanceof Crypto::RC4 -// or -// name = "RC5" and -// type instanceof Crypto::RC5 -// or -// name = "RSA" and -// type instanceof Crypto::RSA -// } -// private predicate modeToNameMappingKnown(Crypto::TBlockCipherModeOperationType type, string name) { -// type instanceof Crypto::ECB and name = "ECB" -// or -// type instanceof Crypto::CBC and name = "CBC" -// or -// type instanceof Crypto::GCM and name = "GCM" -// or -// type instanceof Crypto::CTR and name = "CTR" -// or -// type instanceof Crypto::XTS and name = "XTS" -// or -// type instanceof Crypto::CCM and name = "CCM" -// or -// type instanceof Crypto::SIV and name = "SIV" -// or -// type instanceof Crypto::OCB and name = "OCB" -// } -// override Crypto::TBlockCipherModeOperationType getModeType() { -// if this.modeToNameMappingKnown(_, super.getMode()) -// then this.modeToNameMappingKnown(result, super.getMode()) -// else result instanceof Crypto::OtherMode -// } -// override string getRawModeAlgorithmName() { result = super.getMode() } -// override string getRawPaddingAlgorithmName() { result = super.getPadding() } -// bindingset[name] -// private predicate paddingToNameMappingKnown(Crypto::TPaddingType type, string name) { -// type instanceof Crypto::NoPadding and name = "NOPADDING" -// or -// type instanceof Crypto::PKCS7 and name = ["PKCS5Padding", "PKCS7Padding"] // TODO: misnomer in the JCA? -// or -// type instanceof Crypto::OAEP and name.matches("OAEP%") // TODO: handle OAEPWith% -// } -// } /** * Resolves literal `e` to a known algorithm name, nid, normalized name, and algType * if `e` resolves to a known algorithm. @@ -992,7 +893,7 @@ predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string or name = "hmac-sha1" and nid = 781 and normalized = "SHA1" and algType = "HASH" or - name = "md_gost94" and nid = 809 and normalized = "GOST94" and algType = "SYMMETRIC_ENCRYPTION" + name = "md_gost94" and nid = 809 and normalized = "GOST94" and algType = "HASH" or name = "gost94" and nid = 812 and normalized = "GOST94" and algType = "SYMMETRIC_ENCRYPTION" or @@ -2432,7 +2333,7 @@ predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string or name = "pbe-md2-des" and nid = 9 and normalized = "MD2" and algType = "HASH" or - name = "pbe-md2-des" and nid = 9 and normalized = "2DES" and algType = "SYMMETRIC_ENCRYPTION" + name = "pbe-md2-des" and nid = 9 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" or name = "pbe-md2-rc2-64" and nid = 168 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" or diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 243d52cd2e67..522ff3b27848 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -864,16 +864,26 @@ module CryptographyBase Input> { */ newtype TCipherType = AES() or - Camellia() or + ARIA() or + BLOWFISH() or + CAMELLIA() or + CAST5() or + CHACHA20() or DES() or - TripleDES() or + DESX() or + GOST() or IDEA() or - CAST5() or - ChaCha20() or + KUZNYECHIK() or + MAGMA() or + TRIPLEDES() or + DOUBLEDES() or + RC2() or RC4() or RC5() or RSA() or - OtherCipherType() + SEED() or + SM4() or + OTHERCIPHERTYPE() final class CipherAlgorithmNode extends AlgorithmNode, TCipherAlgorithm { CipherAlgorithmInstance instance; @@ -922,27 +932,27 @@ module CryptographyBase Input> { final private predicate cipherFamilyToNameAndStructure( TCipherType type, string name, TCipherStructureType s ) { - type instanceof AES and name = "AES" and s = Block() - or - type instanceof Camellia and name = "Camellia" and s = Block() - or - type instanceof DES and name = "DES" and s = Block() - or - type instanceof TripleDES and name = "TripleDES" and s = Block() - or - type instanceof IDEA and name = "IDEA" and s = Block() - or - type instanceof CAST5 and name = "CAST5" and s = Block() - or - type instanceof ChaCha20 and name = "ChaCha20" and s = Stream() - or - type instanceof RC4 and name = "RC4" and s = Stream() - or - type instanceof RC5 and name = "RC5" and s = Block() - or - type instanceof RSA and name = "RSA" and s = Asymmetric() - or - type instanceof OtherCipherType and + type instanceof AES and name = "AES" and s = Block() or + type instanceof ARIA and name = "ARIA" and s = Block() or + type instanceof BLOWFISH and name = "Blowfish" and s = Block() or + type instanceof CAMELLIA and name = "Camellia" and s = Block() or + type instanceof CAST5 and name = "CAST5" and s = Block() or + type instanceof CHACHA20 and name = "ChaCha20" and s = Stream() or + type instanceof DES and name = "DES" and s = Block() or + type instanceof DESX and name = "DESX" and s = Block() or + type instanceof GOST and name = "GOST" and s = Block() or + type instanceof IDEA and name = "IDEA" and s = Block() or + type instanceof KUZNYECHIK and name = "Kuznyechik" and s = Block() or + type instanceof MAGMA and name = "Magma" and s = Block() or + type instanceof TRIPLEDES and name = "TripleDES" and s = Block() or + type instanceof DOUBLEDES and name = "DoubleDES" and s = Block() or + type instanceof RC2 and name = "RC2" and s = Block() or + type instanceof RC4 and name = "RC4" and s = Stream() or + type instanceof RC5 and name = "RC5" and s = Block() or + type instanceof RSA and name = "RSA" and s = Asymmetric() or + type instanceof SEED and name = "SEED" and s = Block() or + type instanceof SM4 and name = "SM4" and s = Block() or + type instanceof OTHERCIPHERTYPE and name = this.getRawAlgorithmName() and s = UnknownCipherStructureType() } From 6083df2b7f22955bf123982f7a66760e3f756aa2 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Wed, 5 Mar 2025 15:48:08 -0500 Subject: [PATCH 042/336] Completed tying algorithm instances to consumers. Now the model should have known literals for cipher instances, and it traces those instances to consumers (inits) and those inits are traced to cipher operations. --- .../OpenSSL/EVPCipherAlgorithmSource.qll | 10 ++++++--- .../OpenSSL/OpenSSLAlgorithmGetter.qll | 22 ++++++++++++------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll index 046abf3f43a9..c6810c0ab396 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll @@ -52,11 +52,13 @@ predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) { ) } + class CipherKnownAlgorithmLiteralAlgorithmInstance extends Crypto::CipherAlgorithmInstance instanceof Literal { + OpenSSLAlgorithmGetterCall cipherGetterCall; CipherKnownAlgorithmLiteralAlgorithmInstance() { - exists(EVPCipherGetterCall c, DataFlow::Node src, DataFlow::Node sink | - sink = c.getValueArgNode() and + exists(DataFlow::Node src, DataFlow::Node sink | + sink = cipherGetterCall.getValueArgNode() and src.asExpr() = this and KnownAlgorithmLiteralToAlgorithmGetterFlow::flow(src, sink) and // Not just any known value, but specifically a known cipher operation @@ -67,7 +69,9 @@ class CipherKnownAlgorithmLiteralAlgorithmInstance extends Crypto::CipherAlgorit ) } - Crypto::AlgorithmConsumer getConsumer() { none() } //result = consumer } + Crypto::AlgorithmConsumer getConsumer() { + AlgGetterToAlgConsumerFlow::flow(cipherGetterCall.getResultNode(), DataFlow::exprNode(result)) + } override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { none() // TODO: provider defaults diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll index 79491ca2a09d..0b1f5546c4ba 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll @@ -2,6 +2,19 @@ import cpp import semmle.code.cpp.dataflow.new.DataFlow import LibraryDetector import OpenSSLKnownAlgorithmConstants +import experimental.Quantum.Language + +module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + exists(OpenSSLAlgorithmGetterCall c | c.getResultNode() = source) + } + + predicate isSink(DataFlow::Node sink) { + exists(Crypto::AlgorithmConsumer c | c.getInputNode() = sink) + } +} + +module AlgGetterToAlgConsumerFlow = DataFlow::Global; abstract class AlgorithmPassthroughCall extends Call { abstract DataFlow::Node getInNode(); @@ -116,14 +129,7 @@ abstract class OpenSSLAlgorithmGetterCall extends Call { } module KnownAlgorithmLiteralToAlgorithmGetterConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { - ( - source.asExpr() instanceof Literal and - // 0 sources, for nid are unknown, and 0 otherwise represents a null assignment (ignore as unknown) - exists(source.asExpr().(Literal).getValue().toInt()) implies source.asExpr().(Literal).getValue().toInt() != 0 - //resolveAlgorithmFromLiteral(source.asExpr(),_,_) - ) - } + predicate isSource(DataFlow::Node source) { resolveAlgorithmFromLiteral(source.asExpr(), _, _) } predicate isSink(DataFlow::Node sink) { exists(OpenSSLAlgorithmGetterCall c | c.getValueArgNode() = sink) From b9bd199432e19a8d3a8235aa479ee4eea33aebc7 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Thu, 6 Mar 2025 13:39:23 -0500 Subject: [PATCH 043/336] Regression fixes for JCA --- java/ql/lib/experimental/Quantum/JCA.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 5cb7bcf23dcb..5d5184fdda22 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -123,7 +123,7 @@ module JCAModel { override Crypto::TCipherType getCipherFamily() { if this.cipherNameMappingKnown(_, super.getAlgorithmName()) then this.cipherNameMappingKnown(result, super.getAlgorithmName()) - else result instanceof Crypto::OtherCipherType + else result instanceof Crypto::OTHERCIPHERTYPE } bindingset[name] @@ -135,7 +135,7 @@ module JCAModel { type instanceof Crypto::DES or name = "TripleDES" and - type instanceof Crypto::TripleDES + type instanceof Crypto::TRIPLEDES or name = "IDEA" and type instanceof Crypto::IDEA @@ -144,7 +144,7 @@ module JCAModel { type instanceof Crypto::CAST5 or name = "ChaCha20" and - type instanceof Crypto::ChaCha20 + type instanceof Crypto::CHACHA20 or name = "RC4" and type instanceof Crypto::RC4 From 32d29ffde3c1f0392c0b4e7fc72bc95d8a493806 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Fri, 7 Mar 2025 10:02:36 -0500 Subject: [PATCH 044/336] Changed casing on TCipherType, Added some initial fixes for hash support, started developing openssl hashing modeling. --- .../OpenSSL/EVPCipherAlgorithmSource.qll | 11 +- .../OpenSSL/EVPDigestAlgorithmSource.qll | 65 +++++++++++ .../Quantum/OpenSSL/EVPHashOperation.qll | 5 + .../OpenSSL/OpenSSLAlgorithmGetter.qll | 34 +++++- java/ql/lib/experimental/Quantum/JCA.qll | 4 +- .../codeql/cryptography/Model.qll | 108 ++++++++++++------ 6 files changed, 185 insertions(+), 42 deletions(-) create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPDigestAlgorithmSource.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashOperation.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll index c6810c0ab396..8aa4f88a81b8 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll @@ -3,7 +3,7 @@ import experimental.Quantum.Language import EVPCipherConsumers import OpenSSLAlgorithmGetter -predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) { +predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) { exists(string name, string algType | algType.toLowerCase().matches("%encryption") | resolveAlgorithmFromLiteral(e, name, algType) and ( @@ -21,9 +21,9 @@ predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) { or name.matches("CAST5") and type instanceof Crypto::CAST5 or - name.matches("2DES") and type instanceof Crypto::DOUBLEDES + name.matches("2DES") and type instanceof Crypto::DoubleDES or - name.matches(["3DES", "TRIPLEDES"]) and type instanceof Crypto::TRIPLEDES + name.matches(["3DES", "TRIPLEDES"]) and type instanceof Crypto::TripleDES or name.matches("DES") and type instanceof Crypto::DES or @@ -52,7 +52,6 @@ predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) { ) } - class CipherKnownAlgorithmLiteralAlgorithmInstance extends Crypto::CipherAlgorithmInstance instanceof Literal { OpenSSLAlgorithmGetterCall cipherGetterCall; @@ -81,7 +80,9 @@ class CipherKnownAlgorithmLiteralAlgorithmInstance extends Crypto::CipherAlgorit override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } - override Crypto::TCipherType getCipherFamily() { literalToCipherFamilyType(this, result) } + override Crypto::TCipherType getCipherFamily() { + literalToCipherFamilyType(this, result) + } } // override Crypto::TCipherType getCipherFamily() { // if this.cipherNameMappingKnown(_, super.getAlgorithmName()) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPDigestAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPDigestAlgorithmSource.qll new file mode 100644 index 000000000000..aa9c4008dd11 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPDigestAlgorithmSource.qll @@ -0,0 +1,65 @@ +import cpp +import experimental.Quantum.Language +import EVPCipherConsumers +import OpenSSLAlgorithmGetter + +predicate literalToHashFamilyType(Literal e, Crypto::THashType type) { + exists(string name, string algType | algType.toLowerCase().matches("%hash") | + resolveAlgorithmFromLiteral(e, name, algType) and + ( + name.matches("BLAKE2B") and type instanceof Crypto::BLAKE2B + or + name.matches("BLAKE2S") and type instanceof Crypto::BLAKE2S + or + name.matches("RIPEMD160") and type instanceof Crypto::RIPEMD160 + or + name.matches("MD2") and type instanceof Crypto::MD2 + or + name.matches("MD4") and type instanceof Crypto::MD4 + or + name.matches("MD5") and type instanceof Crypto::MD5 + or + name.matches("POLY1305") and type instanceof Crypto::POLY1305 + or + name.matches(["SHA1", "SHA"]) and type instanceof Crypto::SHA1 + or + name.matches("SHA2") and type instanceof Crypto::SHA2 + or + name.matches("SHA3") and type instanceof Crypto::SHA3 + or + name.matches("SHAKE") and type instanceof Crypto::SHAKE + or + name.matches("SM3") and type instanceof Crypto::SM3 + or + name.matches("WHIRLPOOL") and type instanceof Crypto::WHIRLPOOL + // TODO: what about MD_GOST? + ) + ) +} + +class HashKnownAlgorithmLiteralAlgorithmInstance extends Crypto::HashAlgorithmInstance instanceof Literal +{ + OpenSSLAlgorithmGetterCall cipherGetterCall; + + HashKnownAlgorithmLiteralAlgorithmInstance() { + exists(DataFlow::Node src, DataFlow::Node sink | + sink = cipherGetterCall.getValueArgNode() and + src.asExpr() = this and + KnownAlgorithmLiteralToAlgorithmGetterFlow::flow(src, sink) and + // Not just any known value, but specifically a known cipher operation + exists(string algType | + resolveAlgorithmFromLiteral(src.asExpr(), _, algType) and + algType.toLowerCase().matches("hash") + ) + ) + } + + // TODO: should this not be part of the abstract algorithm definition? + Crypto::AlgorithmConsumer getConsumer() { + AlgGetterToAlgConsumerFlow::flow(cipherGetterCall.getResultNode(), DataFlow::exprNode(result)) + } + + override Crypto::THashType getHashFamily() { literalToHashFamilyType(this, result) } + + override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashOperation.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashOperation.qll new file mode 100644 index 000000000000..91b3f2ea62b9 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashOperation.qll @@ -0,0 +1,5 @@ +import experimental.Quantum.Language +import CtxFlow as CTXFlow + + +//https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis \ No newline at end of file diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll index 0b1f5546c4ba..30ffd1e1f3e8 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll @@ -162,9 +162,9 @@ class EVPCipherGetterCall extends OpenSSLAlgorithmGetterCall { Expr resultExpr; EVPCipherGetterCall() { - // Flow out through the return pointer itself (trace the pointer, not what it is pointing to) resultExpr = this and resultNode.asExpr() = this and + isPossibleOpenSSLFunction(this.getTarget()) and ( this.getTarget().getName() in ["EVP_get_cipherbyname", "EVP_get_cipherbyobj"] and valueArgExpr = this.getArgument(0) and @@ -188,6 +188,38 @@ class EVPCipherGetterCall extends OpenSSLAlgorithmGetterCall { override Expr getResultExpr() { result = resultExpr } } + +class EVPDigestGetterCall extends OpenSSLAlgorithmGetterCall { + DataFlow::Node valueArgNode; + DataFlow::Node resultNode; + Expr valueArgExpr; + Expr resultExpr; + + EVPDigestGetterCall() { + resultExpr = this and + resultNode.asExpr() = this and + isPossibleOpenSSLFunction(this.getTarget()) and + ( + this.getTarget().getName() in [ + "EVP_get_digestbyname", "EVP_get_digestbyobj", "EVP_get_digestbynid" + ] and + valueArgExpr = this.getArgument(0) and + valueArgNode.asExpr() = valueArgExpr + or + this.getTarget().getName() = "EVP_MD_fetch" and + valueArgExpr = this.getArgument(1) and + valueArgNode.asExpr() = valueArgExpr + ) + } + + override DataFlow::Node getValueArgNode() { result = valueArgNode } + + override DataFlow::Node getResultNode() { result = resultNode } + + override Expr getValueArgExpr() { result = valueArgExpr } + + override Expr getResultExpr() { result = resultExpr } +} // /** // * Predicates/classes for identifying algorithm sinks. // * An Algorithm Sink is a function that takes an algorithm as an argument. diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 5d5184fdda22..b2698cabee24 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -123,7 +123,7 @@ module JCAModel { override Crypto::TCipherType getCipherFamily() { if this.cipherNameMappingKnown(_, super.getAlgorithmName()) then this.cipherNameMappingKnown(result, super.getAlgorithmName()) - else result instanceof Crypto::OTHERCIPHERTYPE + else result instanceof Crypto::OtherCipherType } bindingset[name] @@ -135,7 +135,7 @@ module JCAModel { type instanceof Crypto::DES or name = "TripleDES" and - type instanceof Crypto::TRIPLEDES + type instanceof Crypto::TripleDES or name = "IDEA" and type instanceof Crypto::IDEA diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 522ff3b27848..e3a1a6123ec6 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -140,7 +140,13 @@ module CryptographyBase Input> { /** * An element that represents a _known_ cryptographic algorithm. */ - abstract class AlgorithmElement extends KnownElement { } + abstract class AlgorithmElement extends KnownElement { + /** + * Gets the raw name as it appears in source, e.g., "AES/CBC/PKCS7Padding". + * This name is not parsed or formatted. + */ + abstract string getRawAlgorithmName(); + } /** * An element that represents a _known_ cryptographic artifact. @@ -286,12 +292,6 @@ module CryptographyBase Input> { } abstract class CipherAlgorithmInstance extends AlgorithmElement { - /** - * Gets the raw name as it appears in source, e.g., "AES/CBC/PKCS7Padding". - * This name is not parsed or formatted. - */ - abstract string getRawAlgorithmName(); - /** * Gets the type of this cipher, e.g., "AES" or "ChaCha20". */ @@ -358,7 +358,12 @@ module CryptographyBase Input> { abstract class HashOperationInstance extends KnownElement { } - abstract class HashAlgorithmInstance extends KnownElement { } + abstract class HashAlgorithmInstance extends AlgorithmElement { + /** + * Gets the type of this digest algorithm, e.g., "SHA1", "SHA2", "MD5" etc. + */ + abstract THashType getHashFamily(); + } abstract class KeyDerivationOperationInstance extends KnownElement { } @@ -875,15 +880,15 @@ module CryptographyBase Input> { IDEA() or KUZNYECHIK() or MAGMA() or - TRIPLEDES() or - DOUBLEDES() or + TripleDES() or + DoubleDES() or RC2() or RC4() or RC5() or RSA() or SEED() or SM4() or - OTHERCIPHERTYPE() + OtherCipherType() final class CipherAlgorithmNode extends AlgorithmNode, TCipherAlgorithm { CipherAlgorithmInstance instance; @@ -932,27 +937,47 @@ module CryptographyBase Input> { final private predicate cipherFamilyToNameAndStructure( TCipherType type, string name, TCipherStructureType s ) { - type instanceof AES and name = "AES" and s = Block() or - type instanceof ARIA and name = "ARIA" and s = Block() or - type instanceof BLOWFISH and name = "Blowfish" and s = Block() or - type instanceof CAMELLIA and name = "Camellia" and s = Block() or - type instanceof CAST5 and name = "CAST5" and s = Block() or - type instanceof CHACHA20 and name = "ChaCha20" and s = Stream() or - type instanceof DES and name = "DES" and s = Block() or - type instanceof DESX and name = "DESX" and s = Block() or - type instanceof GOST and name = "GOST" and s = Block() or - type instanceof IDEA and name = "IDEA" and s = Block() or - type instanceof KUZNYECHIK and name = "Kuznyechik" and s = Block() or - type instanceof MAGMA and name = "Magma" and s = Block() or - type instanceof TRIPLEDES and name = "TripleDES" and s = Block() or - type instanceof DOUBLEDES and name = "DoubleDES" and s = Block() or - type instanceof RC2 and name = "RC2" and s = Block() or - type instanceof RC4 and name = "RC4" and s = Stream() or - type instanceof RC5 and name = "RC5" and s = Block() or - type instanceof RSA and name = "RSA" and s = Asymmetric() or - type instanceof SEED and name = "SEED" and s = Block() or - type instanceof SM4 and name = "SM4" and s = Block() or - type instanceof OTHERCIPHERTYPE and + type instanceof AES and name = "AES" and s = Block() + or + type instanceof ARIA and name = "ARIA" and s = Block() + or + type instanceof BLOWFISH and name = "Blowfish" and s = Block() + or + type instanceof CAMELLIA and name = "Camellia" and s = Block() + or + type instanceof CAST5 and name = "CAST5" and s = Block() + or + type instanceof CHACHA20 and name = "ChaCha20" and s = Stream() + or + type instanceof DES and name = "DES" and s = Block() + or + type instanceof DESX and name = "DESX" and s = Block() + or + type instanceof GOST and name = "GOST" and s = Block() + or + type instanceof IDEA and name = "IDEA" and s = Block() + or + type instanceof KUZNYECHIK and name = "Kuznyechik" and s = Block() + or + type instanceof MAGMA and name = "Magma" and s = Block() + or + type instanceof TripleDES and name = "TripleDES" and s = Block() + or + type instanceof DoubleDES and name = "DoubleDES" and s = Block() + or + type instanceof RC2 and name = "RC2" and s = Block() + or + type instanceof RC4 and name = "RC4" and s = Stream() + or + type instanceof RC5 and name = "RC5" and s = Block() + or + type instanceof RSA and name = "RSA" and s = Asymmetric() + or + type instanceof SEED and name = "SEED" and s = Block() + or + type instanceof SM4 and name = "SM4" and s = Block() + or + type instanceof OtherCipherType and name = this.getRawAlgorithmName() and s = UnknownCipherStructureType() } @@ -1004,13 +1029,18 @@ module CryptographyBase Input> { } newtype THashType = + BLAKE2B() or + BLAKE2S() or + RIPEMD160() or MD2() or MD4() or MD5() or + POLY1305() or SHA1() or SHA2() or SHA3() or - RIPEMD160() or + SHAKE() or + SM3() or WHIRLPOOL() or OtherHashType() @@ -1021,19 +1051,29 @@ module CryptographyBase Input> { override string getInternalType() { result = "HashAlgorithm" } final predicate hashTypeToNameMapping(THashType type, string name) { + type instanceof BLAKE2B and name = "BLAKE2B" + or + type instanceof BLAKE2S and name = "BLAKE2S" + or + type instanceof RIPEMD160 and name = "RIPEMD160" + or type instanceof MD2 and name = "MD2" or type instanceof MD4 and name = "MD4" or type instanceof MD5 and name = "MD5" or + type instanceof POLY1305 and name = "POLY1305" + or type instanceof SHA1 and name = "SHA1" or type instanceof SHA2 and name = "SHA2" or type instanceof SHA3 and name = "SHA3" or - type instanceof RIPEMD160 and name = "RIPEMD160" + type instanceof SHAKE and name = "SHAKE" + or + type instanceof SM3 and name = "SM3" or type instanceof WHIRLPOOL and name = "WHIRLPOOL" or From cf72fde911b1d73047454009aa5bdb268f0dbabb Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Fri, 7 Mar 2025 12:11:12 -0500 Subject: [PATCH 045/336] Fixing cross product in getPropertyAsGraphString (parameter `root` not bound in all cases, fixing using a bindingetset) --- shared/cryptography/codeql/cryptography/Model.qll | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index e3a1a6123ec6..5a6cd3288fe7 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -32,13 +32,16 @@ module CryptographyBase Input> { UnknownPropertyValue() { this = "" } } + bindingset[root] private string getPropertyAsGraphString(NodeBase node, string key, Location root) { result = strictconcat(any(string value, Location location, string parsed | node.properties(key, value, location) and - if location = root or location instanceof UnknownLocation - then parsed = value - else parsed = "(" + value + "," + location.toString() + ")" + ( + if location = root or location instanceof UnknownLocation + then parsed = value + else parsed = "(" + value + "," + location.toString() + ")" + ) | parsed ), "," From 47affa0fed674e875699b0587f84a15bef683bbc Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Fri, 7 Mar 2025 18:30:58 +0100 Subject: [PATCH 046/336] Restore location output for nodes --- shared/cryptography/codeql/cryptography/Model.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 5a6cd3288fe7..433c97a83875 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -67,7 +67,7 @@ module CryptographyBase Input> { or // CodeQL's DGML output does not include a location key = "Location" and - value = "" // node.getLocation().toString() + value = node.getLocation().toString() or // Known unknown edges should be reported as properties rather than edges node = node.getChild(key) and From bac0a635f943abb9a1bf50f001364e3094f74d04 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Fri, 7 Mar 2025 14:24:01 -0500 Subject: [PATCH 047/336] Initial hash models for openssl. --- cpp/ql/lib/experimental/Quantum/Language.qll | 110 +++++++++--------- .../OpenSSL/EVPDigestAlgorithmSource.qll | 8 +- .../OpenSSL/EVPHashAlgorithmSource.qll | 70 +++++++++++ .../Quantum/OpenSSL/EVPHashConsumers.qll | 27 +++++ .../Quantum/OpenSSL/EVPHashInitializer.qll | 25 ++++ .../Quantum/OpenSSL/EVPHashOperation.qll | 80 ++++++++++++- .../OpenSSLKnownAlgorithmConstants.qll | 72 ++++++------ .../codeql/cryptography/Model.qll | 8 +- 8 files changed, 303 insertions(+), 97 deletions(-) create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashInitializer.qll diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index 5d4ff4bc6863..f0775df1b2e6 100644 --- a/cpp/ql/lib/experimental/Quantum/Language.qll +++ b/cpp/ql/lib/experimental/Quantum/Language.qll @@ -22,82 +22,82 @@ abstract class AdditionalFlowInputStep extends DataFlow::Node { } -/** - * Generic data source to node input configuration - */ -module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { - source = any(Crypto::GenericDataSourceInstance i).getOutputNode() - } +// /** +// * Generic data source to node input configuration +// */ +// module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { +// predicate isSource(DataFlow::Node source) { +// source = any(Crypto::GenericDataSourceInstance i).getOutputNode() +// } - predicate isSink(DataFlow::Node sink) { - sink = any(Crypto::FlowAwareElement other).getInputNode() - } +// predicate isSink(DataFlow::Node sink) { +// sink = any(Crypto::FlowAwareElement other).getInputNode() +// } - predicate isBarrierOut(DataFlow::Node node) { - node = any(Crypto::FlowAwareElement element).getInputNode() - } +// predicate isBarrierOut(DataFlow::Node node) { +// node = any(Crypto::FlowAwareElement element).getInputNode() +// } - predicate isBarrierIn(DataFlow::Node node) { - node = any(Crypto::FlowAwareElement element).getOutputNode() - } +// predicate isBarrierIn(DataFlow::Node node) { +// node = any(Crypto::FlowAwareElement element).getOutputNode() +// } - predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - node1.(AdditionalFlowInputStep).getOutput() = node2 - } -} +// predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { +// node1.(AdditionalFlowInputStep).getOutput() = node2 +// } +// } -// // TODO: I think this will be inefficient, no? -// class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource instanceof Literal { -// override DataFlow::Node getOutputNode() { -// result.asExpr() = this -// } +// // // TODO: I think this will be inefficient, no? +// // class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource instanceof Literal { +// // override DataFlow::Node getOutputNode() { +// // result.asExpr() = this +// // } -// override predicate flowsTo(Crypto::FlowAwareElement other) { -// // TODO: separate config to avoid blowing up data-flow analysis -// GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) -// } +// // override predicate flowsTo(Crypto::FlowAwareElement other) { +// // // TODO: separate config to avoid blowing up data-flow analysis +// // GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) +// // } -// override string getAdditionalDescription() { result = this.toString() } -// } +// // override string getAdditionalDescription() { result = this.toString() } +// // } -/** - * Definitions of various generic data sources - */ -// final class DefaultFlowSource = SourceNode; +// /** +// * Definitions of various generic data sources +// */ +// // final class DefaultFlowSource = SourceNode; -// final class DefaultRemoteFlowSource = RemoteFlowSource; +// // final class DefaultRemoteFlowSource = RemoteFlowSource; -// class GenericLocalDataSource extends Crypto::GenericLocalDataSource { -// GenericLocalDataSource() { -// any(DefaultFlowSource src | not src instanceof DefaultRemoteFlowSource).asExpr() = this -// } +// // class GenericLocalDataSource extends Crypto::GenericLocalDataSource { +// // GenericLocalDataSource() { +// // any(DefaultFlowSource src | not src instanceof DefaultRemoteFlowSource).asExpr() = this +// // } -// override DataFlow::Node getOutputNode() { result.asExpr() = this } +// // override DataFlow::Node getOutputNode() { result.asExpr() = this } -// override predicate flowsTo(Crypto::FlowAwareElement other) { -// GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) -// } +// // override predicate flowsTo(Crypto::FlowAwareElement other) { +// // GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) +// // } -// override string getAdditionalDescription() { result = this.toString() } -// } +// // override string getAdditionalDescription() { result = this.toString() } +// // } -// class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { -// GenericRemoteDataSource() { any(DefaultRemoteFlowSource src).asExpr() = this } +// // class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { +// // GenericRemoteDataSource() { any(DefaultRemoteFlowSource src).asExpr() = this } -// override DataFlow::Node getOutputNode() { result.asExpr() = this } +// // override DataFlow::Node getOutputNode() { result.asExpr() = this } -// override predicate flowsTo(Crypto::FlowAwareElement other) { -// GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) -// } +// // override predicate flowsTo(Crypto::FlowAwareElement other) { +// // GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) +// // } -// override string getAdditionalDescription() { result = this.toString() } -// } +// // override string getAdditionalDescription() { result = this.toString() } +// // } -module GenericDataSourceUniversalFlow = DataFlow::Global; +// module GenericDataSourceUniversalFlow = DataFlow::Global; module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPDigestAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPDigestAlgorithmSource.qll index aa9c4008dd11..7d132b22a3ac 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPDigestAlgorithmSource.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPDigestAlgorithmSource.qll @@ -39,11 +39,11 @@ predicate literalToHashFamilyType(Literal e, Crypto::THashType type) { class HashKnownAlgorithmLiteralAlgorithmInstance extends Crypto::HashAlgorithmInstance instanceof Literal { - OpenSSLAlgorithmGetterCall cipherGetterCall; + OpenSSLAlgorithmGetterCall getterCall; HashKnownAlgorithmLiteralAlgorithmInstance() { exists(DataFlow::Node src, DataFlow::Node sink | - sink = cipherGetterCall.getValueArgNode() and + sink = getterCall.getValueArgNode() and src.asExpr() = this and KnownAlgorithmLiteralToAlgorithmGetterFlow::flow(src, sink) and // Not just any known value, but specifically a known cipher operation @@ -56,10 +56,12 @@ class HashKnownAlgorithmLiteralAlgorithmInstance extends Crypto::HashAlgorithmIn // TODO: should this not be part of the abstract algorithm definition? Crypto::AlgorithmConsumer getConsumer() { - AlgGetterToAlgConsumerFlow::flow(cipherGetterCall.getResultNode(), DataFlow::exprNode(result)) + AlgGetterToAlgConsumerFlow::flow(getterCall.getResultNode(), DataFlow::exprNode(result)) } override Crypto::THashType getHashFamily() { literalToHashFamilyType(this, result) } + override int getHashSize() { none() } //TODO + override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } } diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll new file mode 100644 index 000000000000..ad2af7e05bed --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll @@ -0,0 +1,70 @@ +import cpp +import experimental.Quantum.Language +import EVPHashConsumers +import OpenSSLAlgorithmGetter + +predicate literalToHashFamilyType(Literal e, Crypto::THashType type) { + exists(string name, string algType | algType.toLowerCase().matches("hash") | + resolveAlgorithmFromLiteral(e, name, algType) and + ( + name.matches("BLAKE2B") and type instanceof Crypto::BLAKE2B + or + name.matches("BLAKE2S") and type instanceof Crypto::BLAKE2S + or + name.matches("MD2") and type instanceof Crypto::MD2 + or + name.matches("MD4") and type instanceof Crypto::MD4 + or + name.matches("MD5") and type instanceof Crypto::MD5 + or + name.matches("POLY1305") and type instanceof Crypto::POLY1305 + or + name.matches(["SHA", "SHA1"]) and type instanceof Crypto::SHA1 + or + name.matches("SHA+%") and not name.matches(["SHA1", "SHA3-"]) and type instanceof Crypto::SHA2 + or + name.matches("SHA3-%") and type instanceof Crypto::SHA3 + or + name.matches(["SHAKE"]) and type instanceof Crypto::SHAKE + or + name.matches("SM3") and type instanceof Crypto::SM3 + or + name.matches("RIPEMD160") and type instanceof Crypto::RIPEMD160 + or + //or + //TODO: need to handle MACs differently, including md_GOST94 + // name.matches("%GOST%") and type instanceof Crypto::GOST + name.matches("WHIRLPOOL") and type instanceof Crypto::WHIRLPOOL + ) + ) +} + +class HashKnownAlgorithmLiteralAlgorithmInstance extends Crypto::HashAlgorithmInstance instanceof Literal +{ + OpenSSLAlgorithmGetterCall cipherGetterCall; + + HashKnownAlgorithmLiteralAlgorithmInstance() { + exists(DataFlow::Node src, DataFlow::Node sink | + sink = cipherGetterCall.getValueArgNode() and + src.asExpr() = this and + KnownAlgorithmLiteralToAlgorithmGetterFlow::flow(src, sink) and + // Not just any known value, but specifically a known cipher operation + exists(string algType | + resolveAlgorithmFromLiteral(src.asExpr(), _, algType) and + algType.toLowerCase().matches("hash") + ) + ) + } + + Crypto::AlgorithmConsumer getConsumer() { + AlgGetterToAlgConsumerFlow::flow(cipherGetterCall.getResultNode(), DataFlow::exprNode(result)) + } + + override Crypto::THashType getHashFamily() { + literalToHashFamilyType(this, result) + } + + override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } + + override int getHashSize() {none() }//TODO +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll new file mode 100644 index 000000000000..31bf00ef94a5 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll @@ -0,0 +1,27 @@ +import EVPHashInitializer +import EVPHashOperation +import EVPHashAlgorithmSource + +class EVP_Digest_Initializer_Algorithm_Consumer extends Crypto::AlgorithmConsumer instanceof EVPDigestInitializerAlgorithmArgument{ + override DataFlow::Node getInputNode() { result.asExpr() = this } + + override Crypto::AlgorithmElement getAKnownAlgorithmSource() { + result.(HashKnownAlgorithmLiteralAlgorithmInstance).getConsumer() = this + } +} + +class EVP_Q_Digest_Algorithm_Consumer extends Crypto::AlgorithmConsumer instanceof EVP_Q_Digest_Algorithm_Argument{ + override DataFlow::Node getInputNode() { result.asExpr() = this } + + override Crypto::AlgorithmElement getAKnownAlgorithmSource() { + result.(HashKnownAlgorithmLiteralAlgorithmInstance).getConsumer() = this + } +} + +class EVP_Digest_Algorithm_Consumer extends Crypto::AlgorithmConsumer instanceof EVP_Digest_Algorithm_Argument{ + override DataFlow::Node getInputNode() { result.asExpr() = this } + + override Crypto::AlgorithmElement getAKnownAlgorithmSource() { + result.(HashKnownAlgorithmLiteralAlgorithmInstance).getConsumer() = this + } +} \ No newline at end of file diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashInitializer.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashInitializer.qll new file mode 100644 index 000000000000..16a9234d68ca --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashInitializer.qll @@ -0,0 +1,25 @@ +import cpp + +abstract class EVP_Hash_Inititalizer extends Call { + Expr getContextArg() { result = this.(Call).getArgument(0) } + + abstract Expr getAlgorithmArg(); +} + +class EVP_DigestInit_Variant_Calls extends EVP_Hash_Inititalizer { + EVP_DigestInit_Variant_Calls() { + this.(Call).getTarget().getName() in [ + "EVP_DigestInit", "EVP_DigestInit_ex", "EVP_DigestInit_ex2" + ] + } + + override Expr getAlgorithmArg() { result = this.(Call).getArgument(1) } + +} + + +class EVPDigestInitializerAlgorithmArgument extends Expr { + EVPDigestInitializerAlgorithmArgument() { + exists(EVP_Hash_Inititalizer initCall | this = initCall.getAlgorithmArg()) + } +} \ No newline at end of file diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashOperation.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashOperation.qll index 91b3f2ea62b9..7db90c4eccc0 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashOperation.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashOperation.qll @@ -1,5 +1,83 @@ import experimental.Quantum.Language import CtxFlow as CTXFlow +import LibraryDetector +import EVPHashInitializer +import EVPHashConsumers +abstract class EVP_Hash_Operation extends Crypto::HashOperationInstance instanceof Call { + Expr getContextArg() { result = this.(Call).getArgument(0) } -//https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis \ No newline at end of file + EVP_Hash_Inititalizer getInitCall() { + CTXFlow::ctxFlowsTo(result.getContextArg(), this.getContextArg()) + } +} + +//https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis +class EVP_Q_Digest_Operation extends EVP_Hash_Operation { + EVP_Q_Digest_Operation() { + this.(Call).getTarget().getName() = "EVP_Q_digest" and + isPossibleOpenSSLFunction(this.(Call).getTarget()) + } + + override Crypto::AlgorithmConsumer getAlgorithmConsumer() { this.(Call).getArgument(1) = result } + + override EVP_Hash_Inititalizer getInitCall() { + // This variant of digest does not use an init + // and even if it were used, the init would be ignored/undefined + none() + } +} + +class EVP_Q_Digest_Algorithm_Argument extends Expr { + EVP_Q_Digest_Algorithm_Argument() { + exists(EVP_Q_Digest_Operation op | this = op.(Call).getArgument(1)) + } +} + +class EVP_Digest_Operation extends EVP_Hash_Operation { + EVP_Digest_Operation() { + this.(Call).getTarget().getName() = "EVP_Digest" and + isPossibleOpenSSLFunction(this.(Call).getTarget()) + } + + // There is no context argument for this function + override Expr getContextArg() { none() } + + override Crypto::AlgorithmConsumer getAlgorithmConsumer() { this.(Call).getArgument(4) = result } + + override EVP_Hash_Inititalizer getInitCall() { + // This variant of digest does not use an init + // and even if it were used, the init would be ignored/undefined + none() + } +} + +class EVP_Digest_Algorithm_Argument extends Expr { + EVP_Digest_Algorithm_Argument() { + exists(EVP_Digest_Operation op | this = op.(Call).getArgument(4)) + } +} + +class EVP_DigestUpdate_Operation extends EVP_Hash_Operation { + EVP_DigestUpdate_Operation() { + this.(Call).getTarget().getName() = "EVP_DigestUpdate" and + isPossibleOpenSSLFunction(this.(Call).getTarget()) + } + + override Crypto::AlgorithmConsumer getAlgorithmConsumer() { + this.getInitCall().getAlgorithmArg() = result + } +} + +class EVP_DigestFinal_Variants_Operation extends EVP_Hash_Operation { + EVP_DigestFinal_Variants_Operation() { + this.(Call).getTarget().getName() in [ + "EVP_DigestFinal", "EVP_DigestFinal_ex", "EVP_DigestFinalXOF" + ] and + isPossibleOpenSSLFunction(this.(Call).getTarget()) + } + + override Crypto::AlgorithmConsumer getAlgorithmConsumer() { + this.getInitCall().getAlgorithmArg() = result + } +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll index dcf24d01ace8..76c6c172bf6e 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll @@ -212,13 +212,13 @@ predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string or name = "sha512-256" and nid = 1095 and normalized = "SHA512256" and algType = "HASH" or - name = "sha3-224" and nid = 1096 and normalized = "SHA3224" and algType = "HASH" + name = "sha3-224" and nid = 1096 and normalized = "SHA3-224" and algType = "HASH" or - name = "sha3-256" and nid = 1097 and normalized = "SHA3256" and algType = "HASH" + name = "sha3-256" and nid = 1097 and normalized = "SHA3-256" and algType = "HASH" or - name = "sha3-384" and nid = 1098 and normalized = "SHA3384" and algType = "HASH" + name = "sha3-384" and nid = 1098 and normalized = "SHA3-384" and algType = "HASH" or - name = "sha3-512" and nid = 1099 and normalized = "SHA3512" and algType = "HASH" + name = "sha3-512" and nid = 1099 and normalized = "SHA3-512" and algType = "HASH" or name = "shake128" and nid = 1100 and normalized = "SHAKE128" and algType = "HASH" or @@ -1232,13 +1232,13 @@ predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string or name = "poly1305" and nid = 1061 and normalized = "POLY1305" and algType = "HASH" or - name = "hmac-sha3-224" and nid = 1102 and normalized = "SHA3224" and algType = "HASH" + name = "hmac-sha3-224" and nid = 1102 and normalized = "SHA3-224" and algType = "HASH" or - name = "hmac-sha3-256" and nid = 1103 and normalized = "SHA3256" and algType = "HASH" + name = "hmac-sha3-256" and nid = 1103 and normalized = "SHA3-256" and algType = "HASH" or - name = "hmac-sha3-384" and nid = 1104 and normalized = "SHA3384" and algType = "HASH" + name = "hmac-sha3-384" and nid = 1104 and normalized = "SHA3-384" and algType = "HASH" or - name = "hmac-sha3-512" and nid = 1105 and normalized = "SHA3512" and algType = "HASH" + name = "hmac-sha3-512" and nid = 1105 and normalized = "SHA3-512" and algType = "HASH" or name = "id-dsa-with-sha384" and nid = 1106 and normalized = "DSA" and algType = "SIGNATURE" or @@ -1250,35 +1250,35 @@ predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string or name = "id-dsa-with-sha3-224" and nid = 1108 and normalized = "DSA" and algType = "SIGNATURE" or - name = "id-dsa-with-sha3-224" and nid = 1108 and normalized = "SHA3224" and algType = "HASH" + name = "id-dsa-with-sha3-224" and nid = 1108 and normalized = "SHA3-224" and algType = "HASH" or name = "id-dsa-with-sha3-256" and nid = 1109 and normalized = "DSA" and algType = "SIGNATURE" or - name = "id-dsa-with-sha3-256" and nid = 1109 and normalized = "SHA3256" and algType = "HASH" + name = "id-dsa-with-sha3-256" and nid = 1109 and normalized = "SHA3-256" and algType = "HASH" or name = "id-dsa-with-sha3-384" and nid = 1110 and normalized = "DSA" and algType = "SIGNATURE" or - name = "id-dsa-with-sha3-384" and nid = 1110 and normalized = "SHA3384" and algType = "HASH" + name = "id-dsa-with-sha3-384" and nid = 1110 and normalized = "SHA3-384" and algType = "HASH" or name = "id-dsa-with-sha3-512" and nid = 1111 and normalized = "DSA" and algType = "SIGNATURE" or - name = "id-dsa-with-sha3-512" and nid = 1111 and normalized = "SHA3512" and algType = "HASH" + name = "id-dsa-with-sha3-512" and nid = 1111 and normalized = "SHA3-512" and algType = "HASH" or name = "id-ecdsa-with-sha3-224" and nid = 1112 and normalized = "ECDSA" and algType = "SIGNATURE" or - name = "id-ecdsa-with-sha3-224" and nid = 1112 and normalized = "SHA3224" and algType = "HASH" + name = "id-ecdsa-with-sha3-224" and nid = 1112 and normalized = "SHA3-224" and algType = "HASH" or name = "id-ecdsa-with-sha3-256" and nid = 1113 and normalized = "ECDSA" and algType = "SIGNATURE" or - name = "id-ecdsa-with-sha3-256" and nid = 1113 and normalized = "SHA3256" and algType = "HASH" + name = "id-ecdsa-with-sha3-256" and nid = 1113 and normalized = "SHA3-256" and algType = "HASH" or name = "id-ecdsa-with-sha3-384" and nid = 1114 and normalized = "ECDSA" and algType = "SIGNATURE" or - name = "id-ecdsa-with-sha3-384" and nid = 1114 and normalized = "SHA3384" and algType = "HASH" + name = "id-ecdsa-with-sha3-384" and nid = 1114 and normalized = "SHA3-384" and algType = "HASH" or name = "id-ecdsa-with-sha3-512" and nid = 1115 and normalized = "ECDSA" and algType = "SIGNATURE" or - name = "id-ecdsa-with-sha3-512" and nid = 1115 and normalized = "SHA3512" and algType = "HASH" + name = "id-ecdsa-with-sha3-512" and nid = 1115 and normalized = "SHA3-512" and algType = "HASH" or name = "id-rsassa-pkcs1-v1_5-with-sha3-224" and nid = 1116 and @@ -1292,7 +1292,7 @@ predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string or name = "id-rsassa-pkcs1-v1_5-with-sha3-224" and nid = 1116 and - normalized = "SHA3224" and + normalized = "SHA3-224" and algType = "HASH" or name = "id-rsassa-pkcs1-v1_5-with-sha3-256" and @@ -1307,7 +1307,7 @@ predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string or name = "id-rsassa-pkcs1-v1_5-with-sha3-256" and nid = 1117 and - normalized = "SHA3256" and + normalized = "SHA3-256" and algType = "HASH" or name = "id-rsassa-pkcs1-v1_5-with-sha3-384" and @@ -1322,7 +1322,7 @@ predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string or name = "id-rsassa-pkcs1-v1_5-with-sha3-384" and nid = 1118 and - normalized = "SHA3384" and + normalized = "SHA3-384" and algType = "HASH" or name = "id-rsassa-pkcs1-v1_5-with-sha3-512" and @@ -1337,7 +1337,7 @@ predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string or name = "id-rsassa-pkcs1-v1_5-with-sha3-512" and nid = 1119 and - normalized = "SHA3512" and + normalized = "SHA3-512" and algType = "HASH" or name = "aria-128-ccm" and nid = 1120 and normalized = "CCM" and algType = "BLOCK_MODE" @@ -1666,19 +1666,19 @@ predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string or name = "dsa_with_sha3-224" and nid = 1108 and normalized = "DSA" and algType = "SIGNATURE" or - name = "dsa_with_sha3-224" and nid = 1108 and normalized = "SHA3224" and algType = "HASH" + name = "dsa_with_sha3-224" and nid = 1108 and normalized = "SHA3-224" and algType = "HASH" or name = "dsa_with_sha3-256" and nid = 1109 and normalized = "DSA" and algType = "SIGNATURE" or - name = "dsa_with_sha3-256" and nid = 1109 and normalized = "SHA3256" and algType = "HASH" + name = "dsa_with_sha3-256" and nid = 1109 and normalized = "SHA3-256" and algType = "HASH" or name = "dsa_with_sha3-384" and nid = 1110 and normalized = "DSA" and algType = "SIGNATURE" or - name = "dsa_with_sha3-384" and nid = 1110 and normalized = "SHA3384" and algType = "HASH" + name = "dsa_with_sha3-384" and nid = 1110 and normalized = "SHA3-384" and algType = "HASH" or name = "dsa_with_sha3-512" and nid = 1111 and normalized = "DSA" and algType = "SIGNATURE" or - name = "dsa_with_sha3-512" and nid = 1111 and normalized = "SHA3512" and algType = "HASH" + name = "dsa_with_sha3-512" and nid = 1111 and normalized = "SHA3-512" and algType = "HASH" or name = "dsa_with_sha384" and nid = 1106 and normalized = "DSA" and algType = "SIGNATURE" or @@ -1752,19 +1752,19 @@ predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string or name = "ecdsa_with_sha3-224" and nid = 1112 and normalized = "ECDSA" and algType = "SIGNATURE" or - name = "ecdsa_with_sha3-224" and nid = 1112 and normalized = "SHA3224" and algType = "HASH" + name = "ecdsa_with_sha3-224" and nid = 1112 and normalized = "SHA3-224" and algType = "HASH" or name = "ecdsa_with_sha3-256" and nid = 1113 and normalized = "ECDSA" and algType = "SIGNATURE" or - name = "ecdsa_with_sha3-256" and nid = 1113 and normalized = "SHA3256" and algType = "HASH" + name = "ecdsa_with_sha3-256" and nid = 1113 and normalized = "SHA3-256" and algType = "HASH" or name = "ecdsa_with_sha3-384" and nid = 1114 and normalized = "ECDSA" and algType = "SIGNATURE" or - name = "ecdsa_with_sha3-384" and nid = 1114 and normalized = "SHA3384" and algType = "HASH" + name = "ecdsa_with_sha3-384" and nid = 1114 and normalized = "SHA3-384" and algType = "HASH" or name = "ecdsa_with_sha3-512" and nid = 1115 and normalized = "ECDSA" and algType = "SIGNATURE" or - name = "ecdsa_with_sha3-512" and nid = 1115 and normalized = "SHA3512" and algType = "HASH" + name = "ecdsa_with_sha3-512" and nid = 1115 and normalized = "SHA3-512" and algType = "HASH" or name = "gost 28147-89" and nid = 813 and @@ -2201,13 +2201,13 @@ predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string normalized = "GOSTR341194" and algType = "SYMMETRIC_ENCRYPTION" or - name = "id-hmacwithsha3-224" and nid = 1102 and normalized = "SHA3224" and algType = "HASH" + name = "id-hmacwithsha3-224" and nid = 1102 and normalized = "SHA3-224" and algType = "HASH" or - name = "id-hmacwithsha3-256" and nid = 1103 and normalized = "SHA3256" and algType = "HASH" + name = "id-hmacwithsha3-256" and nid = 1103 and normalized = "SHA3-256" and algType = "HASH" or - name = "id-hmacwithsha3-384" and nid = 1104 and normalized = "SHA3384" and algType = "HASH" + name = "id-hmacwithsha3-384" and nid = 1104 and normalized = "SHA3-384" and algType = "HASH" or - name = "id-hmacwithsha3-512" and nid = 1105 and normalized = "SHA3512" and algType = "HASH" + name = "id-hmacwithsha3-512" and nid = 1105 and normalized = "SHA3-512" and algType = "HASH" or name = "id-regctrl" and nid = 313 and normalized = "CTR" and algType = "BLOCK_MODE" or @@ -2590,19 +2590,19 @@ predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string or name = "rsa-sha3-224" and nid = 1116 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "rsa-sha3-224" and nid = 1116 and normalized = "SHA3224" and algType = "HASH" + name = "rsa-sha3-224" and nid = 1116 and normalized = "SHA3-224" and algType = "HASH" or name = "rsa-sha3-256" and nid = 1117 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "rsa-sha3-256" and nid = 1117 and normalized = "SHA3256" and algType = "HASH" + name = "rsa-sha3-256" and nid = 1117 and normalized = "SHA3-256" and algType = "HASH" or name = "rsa-sha3-384" and nid = 1118 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "rsa-sha3-384" and nid = 1118 and normalized = "SHA3384" and algType = "HASH" + name = "rsa-sha3-384" and nid = 1118 and normalized = "SHA3-384" and algType = "HASH" or name = "rsa-sha3-512" and nid = 1119 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "rsa-sha3-512" and nid = 1119 and normalized = "SHA3512" and algType = "HASH" + name = "rsa-sha3-512" and nid = 1119 and normalized = "SHA3-512" and algType = "HASH" or name = "rsa-sha384" and nid = 669 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 5a6cd3288fe7..bc7631755899 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -359,13 +359,17 @@ module CryptographyBase Input> { abstract class EllipticCurveAlgorithmInstance extends LocatableElement { } - abstract class HashOperationInstance extends KnownElement { } + abstract class HashOperationInstance extends OperationElement { + // TODO: need input and outputs, but this should be universal to all Operations + } abstract class HashAlgorithmInstance extends AlgorithmElement { /** * Gets the type of this digest algorithm, e.g., "SHA1", "SHA2", "MD5" etc. */ abstract THashType getHashFamily(); + + abstract int getHashSize(); } abstract class KeyDerivationOperationInstance extends KnownElement { } @@ -1034,7 +1038,6 @@ module CryptographyBase Input> { newtype THashType = BLAKE2B() or BLAKE2S() or - RIPEMD160() or MD2() or MD4() or MD5() or @@ -1044,6 +1047,7 @@ module CryptographyBase Input> { SHA3() or SHAKE() or SM3() or + RIPEMD160() or WHIRLPOOL() or OtherHashType() From d99812a10d6a50371b70fd419038874acceb28ea Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 10 Mar 2025 09:59:28 -0400 Subject: [PATCH 048/336] Adding GOSTHash to THashType. --- shared/cryptography/codeql/cryptography/Model.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 25165cf5bf3a..bbe817e2110b 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -1038,6 +1038,7 @@ module CryptographyBase Input> { newtype THashType = BLAKE2B() or BLAKE2S() or + GOSTHash() or MD2() or MD4() or MD5() or From 3316d6135d29f0c64acabae614cdad553af18f45 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 10 Mar 2025 11:32:14 -0400 Subject: [PATCH 049/336] Ctx flow comments. --- .../experimental/Quantum/OpenSSL/CtxFlow.qll | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll index e1b08c9652d8..c07902022d89 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll @@ -1,3 +1,21 @@ +/** + * In OpenSSL, flow between 'context' parameters is often used to + * store state/config of how an operation will eventually be performed. + * Tracing algorithms and configurations to operations therefore + * requires tracing context parameters for many OpenSSL apis. + * + * This library provides a dataflow analysis to track context parameters + * between any two functions accepting openssl context parameters. + * The dataflow takes into consideration flowing through duplication and copy calls + * as well as flow through flow killers (free/reset calls). + * + * TODO: we may need to revisit 'free' as a dataflow killer, depending on how + * we want to model use after frees. + * + * This library also provides classes to represent context Types and relevant + * arguments/expressions. + */ + import semmle.code.cpp.dataflow.new.DataFlow class CTXType extends Type { From 6a4659fc7eaa067e79f07f517abdd32bada665da Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 10 Mar 2025 11:33:46 -0400 Subject: [PATCH 050/336] Updating known constants for OpenSSL to handle direct algorithm getters from older versions of openssl (e.g., EVP_md5()) --- .../OpenSSLKnownAlgorithmConstants.qll | 62 ++++++++++++++++--- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll index 76c6c172bf6e..063a7084d3db 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll @@ -1,4 +1,42 @@ import cpp +import LibraryDetector + +class KnownOpenSSLAlgorithmConstant extends Expr { + string normalizedName; + string algType; + + KnownOpenSSLAlgorithmConstant() { + resolveAlgorithmFromCall(this, normalizedName, algType) + or + resolveAlgorithmFromLiteral(this, normalizedName, algType) + } + + string getNormalizedName() { result = normalizedName } + + string getAlgType() { result = algType } +} + +/** + * Resolves a call to a 'direct algorithm getter', e.g., EVP_MD5() + * This approach to fetching algorithms was used in OpenSSL 1.0.2. + * The strategy for resolving these calls is to parse the target name + * and resolve the name as though it were a known literal. + * There are a few exceptions where the name doesn't directly match the + * known literal set. If that occurs, users must add the name to the + * set of aliases. E.g., EVP_dss() and EVP_dss1() needed such mappings + * alias = "dss" and target = "dsa" + * or + * alias = "dss1" and target = "dsaWithSHA1" + */ +predicate resolveAlgorithmFromCall(Call c, string normalized, string algType) { + isPossibleOpenSSLFunction(c.getTarget()) and + exists(string name, string parsedTargetName | + parsedTargetName = + c.getTarget().getName().replaceAll("EVP_", "").toLowerCase().replaceAll("_", "-") and + name = resolveAlgorithmAlias(parsedTargetName) and + knownOpenSSLAlgorithmLiteral(name, _, normalized, algType) + ) +} /** * Resolves literal `e` to a known algorithm name, nid, normalized name, and algType @@ -7,21 +45,23 @@ import cpp */ predicate resolveAlgorithmFromLiteral(Literal e, string normalized, string algType) { exists(int nid | - nid = getPossibleNidFromLiteral(e) and knownOpenSSLAlgorithm(_, nid, normalized, algType) + nid = getPossibleNidFromLiteral(e) and knownOpenSSLAlgorithmLiteral(_, nid, normalized, algType) ) or exists(string name | - name = resolveAlgorithmAlias(e) and knownOpenSSLAlgorithm(name, _, normalized, algType) + name = resolveAlgorithmAlias(e.getValue()) and + knownOpenSSLAlgorithmLiteral(name, _, normalized, algType) ) } -string resolveAlgorithmAlias(StringLiteral name) { - exists(string lower | lower = name.getValue().toLowerCase() | +bindingset[name] +string resolveAlgorithmAlias(string name) { + exists(string lower | lower = name.toLowerCase() | // The result is an alias algorithm name if known result = getAlgorithmAlias(lower) or // or the name is itself a known algorithm - knownOpenSSLAlgorithm(lower, _, _, _) and result = lower + knownOpenSSLAlgorithmLiteral(lower, _, _, _) and result = lower ) } @@ -133,6 +173,10 @@ predicate defaultAliases(string target, string alias) { or alias = "desx" and target = "desx-cbc" or + alias = "dss" and target = "dsa" + or + alias = "dss1" and target = "dsaWithSHA1" + or alias = "idea" and target = "idea-cbc" or alias = "rc2" and target = "rc2-cbc" @@ -165,7 +209,7 @@ predicate defaultAliases(string target, string alias) { * `normalized` is the normalized name of the algorithm (e.g., "AES128" for "aes-128-cbc") * `algType` is the type of algorithm (e.g., "SYMMETRIC_ENCRYPTION") */ -predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string algType) { +predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, string algType) { name = "rsa" and nid = 19 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or name = "prime192v1" and nid = 409 and normalized = "PRIME192V1" and algType = "ELLIPTIC_CURVE" @@ -895,7 +939,7 @@ predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string or name = "md_gost94" and nid = 809 and normalized = "GOST94" and algType = "HASH" or - name = "gost94" and nid = 812 and normalized = "GOST94" and algType = "SYMMETRIC_ENCRYPTION" + name = "gost94" and nid = 812 and normalized = "GOST94" and algType = "HASH" or name = "gost89" and nid = 813 and normalized = "GOST89" and algType = "SYMMETRIC_ENCRYPTION" or @@ -1114,9 +1158,9 @@ predicate knownOpenSSLAlgorithm(string name, int nid, string normalized, string or name = "gost-mac-12" and nid = 976 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" or - name = "md_gost12_256" and nid = 982 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + name = "md_gost12_256" and nid = 982 and normalized = "GOST" and algType = "HASH" or - name = "md_gost12_512" and nid = 983 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + name = "md_gost12_512" and nid = 983 and normalized = "GOST" and algType = "HASH" or name = "id-tc26-signwithdigest-gost3410-2012-256" and nid = 985 and From bd07b8a4c7946107db067d2b79a748e1105227b8 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 10 Mar 2025 11:34:26 -0400 Subject: [PATCH 051/336] Making getter flow through 'copy' more general (copy can appear in any part of the call name now. --- .../lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll index 30ffd1e1f3e8..cee5937d5516 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll @@ -31,7 +31,7 @@ class CopyAndDupAlgorithmPassthroughCall extends AlgorithmPassthroughCall { // Assume flow in and out is asIndirectExpr or asDefinitingArgument since a pointer is assumed // to be involved // NOTE: not attempting to detect openssl specific copy/dup functions, but anything suspected to be copy/dup - this.getTarget().getName().toLowerCase().matches(["%_dup", "%_copy"]) and + this.getTarget().getName().toLowerCase().matches(["%_dup%", "%_copy%"]) and exists(Expr inArg, Type t | inArg = this.getAnArgument() and t = inArg.getUnspecifiedType().stripType() | From 451808616e8746bc31dfd8f5b294fe4c58f77079 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 10 Mar 2025 11:35:16 -0400 Subject: [PATCH 052/336] Getting rid of commented out code. --- .../OpenSSL/EVPCipherAlgorithmSource.qll | 71 +------------------ 1 file changed, 1 insertion(+), 70 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll index 8aa4f88a81b8..4523bd860358 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll @@ -80,74 +80,5 @@ class CipherKnownAlgorithmLiteralAlgorithmInstance extends Crypto::CipherAlgorit override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } - override Crypto::TCipherType getCipherFamily() { - literalToCipherFamilyType(this, result) - } + override Crypto::TCipherType getCipherFamily() { literalToCipherFamilyType(this, result) } } -// override Crypto::TCipherType getCipherFamily() { -// if this.cipherNameMappingKnown(_, super.getAlgorithmName()) -// then this.cipherNameMappingKnown(result, super.getAlgorithmName()) -// else result instanceof Crypto::OtherCipherType -// } -// bindingset[name] -// private predicate cipherNameMappingKnown(Crypto::TCipherType type, string name) { -// name = "AES" and -// type instanceof Crypto::AES -// or -// name = "DES" and -// type instanceof Crypto::DES -// or -// name = "TripleDES" and -// type instanceof Crypto::TripleDES -// or -// name = "IDEA" and -// type instanceof Crypto::IDEA -// or -// name = "CAST5" and -// type instanceof Crypto::CAST5 -// or -// name = "ChaCha20" and -// type instanceof Crypto::ChaCha20 -// or -// name = "RC4" and -// type instanceof Crypto::RC4 -// or -// name = "RC5" and -// type instanceof Crypto::RC5 -// or -// name = "RSA" and -// type instanceof Crypto::RSA -// } -// private predicate modeToNameMappingKnown(Crypto::TBlockCipherModeOperationType type, string name) { -// type instanceof Crypto::ECB and name = "ECB" -// or -// type instanceof Crypto::CBC and name = "CBC" -// or -// type instanceof Crypto::GCM and name = "GCM" -// or -// type instanceof Crypto::CTR and name = "CTR" -// or -// type instanceof Crypto::XTS and name = "XTS" -// or -// type instanceof Crypto::CCM and name = "CCM" -// or -// type instanceof Crypto::SIV and name = "SIV" -// or -// type instanceof Crypto::OCB and name = "OCB" -// } -// override Crypto::TBlockCipherModeOperationType getModeType() { -// if this.modeToNameMappingKnown(_, super.getMode()) -// then this.modeToNameMappingKnown(result, super.getMode()) -// else result instanceof Crypto::OtherMode -// } -// override string getRawModeAlgorithmName() { result = super.getMode() } -// override string getRawPaddingAlgorithmName() { result = super.getPadding() } -// bindingset[name] -// private predicate paddingToNameMappingKnown(Crypto::TPaddingType type, string name) { -// type instanceof Crypto::NoPadding and name = "NOPADDING" -// or -// type instanceof Crypto::PKCS7 and name = ["PKCS5Padding", "PKCS7Padding"] // TODO: misnomer in the JCA? -// or -// type instanceof Crypto::OAEP and name.matches("OAEP%") // TODO: handle OAEPWith% -// } -// } From 06720278220acccc4c230196a1932a869d2c89b8 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 10 Mar 2025 11:46:26 -0400 Subject: [PATCH 053/336] Tracing new notion of known getters, which now includes direct getters for cipher and hash. Removed a redundant hash qll, and fixed misplacement of has type in model. --- .../OpenSSL/EVPCipherAlgorithmSource.qll | 47 ++++++++----- .../Quantum/OpenSSL/EVPCipherConsumers.qll | 24 +++---- .../OpenSSL/EVPDigestAlgorithmSource.qll | 67 ------------------- .../OpenSSL/EVPHashAlgorithmSource.qll | 48 +++++++------ .../Quantum/OpenSSL/EVPHashConsumers.qll | 6 +- .../OpenSSL/OpenSSLAlgorithmGetter.qll | 35 ++++++++-- .../codeql/cryptography/Model.qll | 1 + 7 files changed, 107 insertions(+), 121 deletions(-) delete mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPDigestAlgorithmSource.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll index 4523bd860358..2c1930698b12 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll @@ -3,7 +3,13 @@ import experimental.Quantum.Language import EVPCipherConsumers import OpenSSLAlgorithmGetter -predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) { +/** + * Given a literal `e`, converts this to a cipher family type. + * The literal must be a known literal representing a cipher algorithm. + * If the literal does not represent any known cipher algorithm, + * this predicate will not hold (i.e., it will not bind an unknown to an unknown cipher type) + */ +predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) { exists(string name, string algType | algType.toLowerCase().matches("%encryption") | resolveAlgorithmFromLiteral(e, name, algType) and ( @@ -52,25 +58,36 @@ predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) { ) } -class CipherKnownAlgorithmLiteralAlgorithmInstance extends Crypto::CipherAlgorithmInstance instanceof Literal +class KnownOpenSSLCipherConstantAlgorithmInstance extends Crypto::CipherAlgorithmInstance instanceof KnownOpenSSLAlgorithmConstant { - OpenSSLAlgorithmGetterCall cipherGetterCall; - CipherKnownAlgorithmLiteralAlgorithmInstance() { - exists(DataFlow::Node src, DataFlow::Node sink | - sink = cipherGetterCall.getValueArgNode() and - src.asExpr() = this and - KnownAlgorithmLiteralToAlgorithmGetterFlow::flow(src, sink) and - // Not just any known value, but specifically a known cipher operation - exists(string algType | - resolveAlgorithmFromLiteral(src.asExpr(), _, algType) and - algType.toLowerCase().matches("%encryption") + OpenSSLAlgorithmGetterCall getterCall; + + KnownOpenSSLCipherConstantAlgorithmInstance() { + // Not just any known value, but specifically a known cipher operation + this.(KnownOpenSSLAlgorithmConstant).getAlgType().toLowerCase().matches("%encryption") and + ( + // Two possibilities: + // 1) The source is a literal and flows to a getter, then we know we have an instance + // 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that + // Possibility 1: + this instanceof Literal and + exists(DataFlow::Node src, DataFlow::Node sink | + // Sink is an argument to a CipherGetterCall + sink = getterCall.(OpenSSLAlgorithmGetterCall).getValueArgNode() and + // Source is `this` + src.asExpr() = this and + // This traces to a getter + KnownOpenSSLAlgorithmToAlgorithmGetterFlow::flow(src, sink) ) + or + // Possibility 2: + this instanceof DirectGetterCall and getterCall = this ) } - Crypto::AlgorithmConsumer getConsumer() { - AlgGetterToAlgConsumerFlow::flow(cipherGetterCall.getResultNode(), DataFlow::exprNode(result)) - } + Crypto::AlgorithmConsumer getConsumer() { + AlgGetterToAlgConsumerFlow::flow(getterCall.getResultNode(), DataFlow::exprNode(result)) + } override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { none() // TODO: provider defaults diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll index 8717a857385a..4f8a5ccd354c 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll @@ -2,24 +2,24 @@ import EVPCipherInitializer import EVPCipherOperation import EVPCipherAlgorithmSource - class EVP_Cipher_Initializer_Algorithm_Consumer extends Crypto::AlgorithmConsumer instanceof EVPCipherInitializerAlgorithmArgument -{ - override DataFlow::Node getInputNode() { result.asExpr() = this } +{ + override DataFlow::Node getInputNode() { result.asExpr() = this } - override Crypto::AlgorithmElement getAKnownAlgorithmSource() { - result.(CipherKnownAlgorithmLiteralAlgorithmInstance).getConsumer() = this - } + override Crypto::AlgorithmElement getAKnownAlgorithmSource() { + result.(KnownOpenSSLCipherConstantAlgorithmInstance).getConsumer() = this + } } + // //TODO: need a key consumer // class EVP_Initializer_Key_Consumer extends Crypto::KeyConsumer instanceof EVP_Cipher_Inititalizer isntanceof InitializerKeyArgument{ // } -class EVP_Cipher_Initializer_IV_Consumer extends Crypto::NonceArtifactConsumer instanceof EVPCipherInitializerIVArgument{ - override DataFlow::Node getInputNode() { result.asExpr() = this } +class EVP_Cipher_Initializer_IV_Consumer extends Crypto::NonceArtifactConsumer instanceof EVPCipherInitializerIVArgument +{ + override DataFlow::Node getInputNode() { result.asExpr() = this } } -class EVP_Cipher_Input_Consumer extends Crypto::CipherInputConsumer instanceof EVPCipherInputArgument{ - - override DataFlow::Node getInputNode() { result.asExpr() = this } +class EVP_Cipher_Input_Consumer extends Crypto::CipherInputConsumer instanceof EVPCipherInputArgument +{ + override DataFlow::Node getInputNode() { result.asExpr() = this } } - diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPDigestAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPDigestAlgorithmSource.qll deleted file mode 100644 index 7d132b22a3ac..000000000000 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPDigestAlgorithmSource.qll +++ /dev/null @@ -1,67 +0,0 @@ -import cpp -import experimental.Quantum.Language -import EVPCipherConsumers -import OpenSSLAlgorithmGetter - -predicate literalToHashFamilyType(Literal e, Crypto::THashType type) { - exists(string name, string algType | algType.toLowerCase().matches("%hash") | - resolveAlgorithmFromLiteral(e, name, algType) and - ( - name.matches("BLAKE2B") and type instanceof Crypto::BLAKE2B - or - name.matches("BLAKE2S") and type instanceof Crypto::BLAKE2S - or - name.matches("RIPEMD160") and type instanceof Crypto::RIPEMD160 - or - name.matches("MD2") and type instanceof Crypto::MD2 - or - name.matches("MD4") and type instanceof Crypto::MD4 - or - name.matches("MD5") and type instanceof Crypto::MD5 - or - name.matches("POLY1305") and type instanceof Crypto::POLY1305 - or - name.matches(["SHA1", "SHA"]) and type instanceof Crypto::SHA1 - or - name.matches("SHA2") and type instanceof Crypto::SHA2 - or - name.matches("SHA3") and type instanceof Crypto::SHA3 - or - name.matches("SHAKE") and type instanceof Crypto::SHAKE - or - name.matches("SM3") and type instanceof Crypto::SM3 - or - name.matches("WHIRLPOOL") and type instanceof Crypto::WHIRLPOOL - // TODO: what about MD_GOST? - ) - ) -} - -class HashKnownAlgorithmLiteralAlgorithmInstance extends Crypto::HashAlgorithmInstance instanceof Literal -{ - OpenSSLAlgorithmGetterCall getterCall; - - HashKnownAlgorithmLiteralAlgorithmInstance() { - exists(DataFlow::Node src, DataFlow::Node sink | - sink = getterCall.getValueArgNode() and - src.asExpr() = this and - KnownAlgorithmLiteralToAlgorithmGetterFlow::flow(src, sink) and - // Not just any known value, but specifically a known cipher operation - exists(string algType | - resolveAlgorithmFromLiteral(src.asExpr(), _, algType) and - algType.toLowerCase().matches("hash") - ) - ) - } - - // TODO: should this not be part of the abstract algorithm definition? - Crypto::AlgorithmConsumer getConsumer() { - AlgGetterToAlgConsumerFlow::flow(getterCall.getResultNode(), DataFlow::exprNode(result)) - } - - override Crypto::THashType getHashFamily() { literalToHashFamilyType(this, result) } - - override int getHashSize() { none() } //TODO - - override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } -} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll index ad2af7e05bed..5fc61c7b6c57 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll @@ -1,6 +1,5 @@ import cpp import experimental.Quantum.Language -import EVPHashConsumers import OpenSSLAlgorithmGetter predicate literalToHashFamilyType(Literal e, Crypto::THashType type) { @@ -11,12 +10,16 @@ predicate literalToHashFamilyType(Literal e, Crypto::THashType type) { or name.matches("BLAKE2S") and type instanceof Crypto::BLAKE2S or + name.matches("GOST%") and type instanceof Crypto::GOSTHash + or name.matches("MD2") and type instanceof Crypto::MD2 or name.matches("MD4") and type instanceof Crypto::MD4 or name.matches("MD5") and type instanceof Crypto::MD5 or + name.matches("MDC2") and type instanceof Crypto::MDC2 + or name.matches("POLY1305") and type instanceof Crypto::POLY1305 or name.matches(["SHA", "SHA1"]) and type instanceof Crypto::SHA1 @@ -31,40 +34,45 @@ predicate literalToHashFamilyType(Literal e, Crypto::THashType type) { or name.matches("RIPEMD160") and type instanceof Crypto::RIPEMD160 or - //or - //TODO: need to handle MACs differently, including md_GOST94 - // name.matches("%GOST%") and type instanceof Crypto::GOST name.matches("WHIRLPOOL") and type instanceof Crypto::WHIRLPOOL ) ) } -class HashKnownAlgorithmLiteralAlgorithmInstance extends Crypto::HashAlgorithmInstance instanceof Literal +class KnownOpenSSLHashConstantAlgorithmInstance extends Crypto::HashAlgorithmInstance instanceof KnownOpenSSLAlgorithmConstant { - OpenSSLAlgorithmGetterCall cipherGetterCall; + OpenSSLAlgorithmGetterCall getterCall; - HashKnownAlgorithmLiteralAlgorithmInstance() { - exists(DataFlow::Node src, DataFlow::Node sink | - sink = cipherGetterCall.getValueArgNode() and - src.asExpr() = this and - KnownAlgorithmLiteralToAlgorithmGetterFlow::flow(src, sink) and - // Not just any known value, but specifically a known cipher operation - exists(string algType | - resolveAlgorithmFromLiteral(src.asExpr(), _, algType) and - algType.toLowerCase().matches("hash") + KnownOpenSSLHashConstantAlgorithmInstance() { + // Not just any known value, but specifically a known hash + this.(KnownOpenSSLAlgorithmConstant).getAlgType().toLowerCase().matches("hash") and + ( + // Two possibilities: + // 1) The source is a literal and flows to a getter, then we know we have an instance + // 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that + // Possibility 1: + this instanceof Literal and + exists(DataFlow::Node src, DataFlow::Node sink | + // Sink is an argument to a CipherGetterCall + sink = getterCall.(OpenSSLAlgorithmGetterCall).getValueArgNode() and + // Source is `this` + src.asExpr() = this and + // This traces to a getter + KnownOpenSSLAlgorithmToAlgorithmGetterFlow::flow(src, sink) ) + or + // Possibility 2: + this instanceof DirectGetterCall and getterCall = this ) } Crypto::AlgorithmConsumer getConsumer() { - AlgGetterToAlgConsumerFlow::flow(cipherGetterCall.getResultNode(), DataFlow::exprNode(result)) + AlgGetterToAlgConsumerFlow::flow(getterCall.getResultNode(), DataFlow::exprNode(result)) } - override Crypto::THashType getHashFamily() { - literalToHashFamilyType(this, result) - } + override Crypto::THashType getHashFamily() { literalToHashFamilyType(this, result) } override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } - override int getHashSize() {none() }//TODO + override int getHashSize() { none() } //TODO } diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll index 31bf00ef94a5..2edca9d5763b 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll @@ -6,7 +6,7 @@ class EVP_Digest_Initializer_Algorithm_Consumer extends Crypto::AlgorithmConsume override DataFlow::Node getInputNode() { result.asExpr() = this } override Crypto::AlgorithmElement getAKnownAlgorithmSource() { - result.(HashKnownAlgorithmLiteralAlgorithmInstance).getConsumer() = this + result.(KnownOpenSSLHashConstantAlgorithmInstance).getConsumer() = this } } @@ -14,7 +14,7 @@ class EVP_Q_Digest_Algorithm_Consumer extends Crypto::AlgorithmConsumer instance override DataFlow::Node getInputNode() { result.asExpr() = this } override Crypto::AlgorithmElement getAKnownAlgorithmSource() { - result.(HashKnownAlgorithmLiteralAlgorithmInstance).getConsumer() = this + result.(KnownOpenSSLHashConstantAlgorithmInstance).getConsumer() = this } } @@ -22,6 +22,6 @@ class EVP_Digest_Algorithm_Consumer extends Crypto::AlgorithmConsumer instanceof override DataFlow::Node getInputNode() { result.asExpr() = this } override Crypto::AlgorithmElement getAKnownAlgorithmSource() { - result.(HashKnownAlgorithmLiteralAlgorithmInstance).getConsumer() = this + result.(KnownOpenSSLHashConstantAlgorithmInstance).getConsumer() = this } } \ No newline at end of file diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll index cee5937d5516..689f022b56dc 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll @@ -128,8 +128,10 @@ abstract class OpenSSLAlgorithmGetterCall extends Call { abstract Expr getResultExpr(); } -module KnownAlgorithmLiteralToAlgorithmGetterConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { resolveAlgorithmFromLiteral(source.asExpr(), _, _) } +module KnownOpenSSLAlgorithmToAlgorithmGetterConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source.asExpr() instanceof KnownOpenSSLAlgorithmConstant + } predicate isSink(DataFlow::Node sink) { exists(OpenSSLAlgorithmGetterCall c | c.getValueArgNode() = sink) @@ -151,8 +153,33 @@ module KnownAlgorithmLiteralToAlgorithmGetterConfig implements DataFlow::ConfigS } } -module KnownAlgorithmLiteralToAlgorithmGetterFlow = - DataFlow::Global; +module KnownOpenSSLAlgorithmToAlgorithmGetterFlow = + DataFlow::Global; + +/** + * Cases like EVP_MD5(), + * there is no input, rather it directly gets an algorithm + * and returns it. + */ +class DirectGetterCall extends OpenSSLAlgorithmGetterCall { + DataFlow::Node resultNode; + Expr resultExpr; + + DirectGetterCall() { + this instanceof KnownOpenSSLAlgorithmConstant and + this instanceof Call and + resultExpr = this and + resultNode.asExpr() = resultExpr + } + + override DataFlow::Node getValueArgNode() { none() } + + override DataFlow::Node getResultNode() { result = resultNode } + + override Expr getValueArgExpr() { none() } + + override Expr getResultExpr() { result = resultExpr } +} // https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html class EVPCipherGetterCall extends OpenSSLAlgorithmGetterCall { diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index bbe817e2110b..298b270e6b62 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -1042,6 +1042,7 @@ module CryptographyBase Input> { MD2() or MD4() or MD5() or + MDC2() or POLY1305() or SHA1() or SHA2() or From 73368ea59abd9be8bc4df7df8dfd853dfcbde40c Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 10 Mar 2025 13:27:39 -0400 Subject: [PATCH 054/336] Adding hashes to openssl library import --- cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll index f942f4687da5..6c30bec16cdd 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll @@ -4,6 +4,10 @@ import semmle.code.cpp.dataflow.new.DataFlow module OpenSSLModel { import experimental.Quantum.Language import experimental.Quantum.OpenSSL.EVPCipherOperation + import experimental.Quantum.OpenSSL.EVPHashOperation + import experimental.Quantum.OpenSSL.EVPCipherAlgorithmSource + import experimental.Quantum.OpenSSL.EVPHashAlgorithmSource + // // TODO: trace CTX from init variants to the context arg of EVP update calls // //https://docs.openssl.org/master/man3/EVP_EncryptInit/#synopsis From fe52351aed103e958312521da6a386858606dfd0 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 10 Mar 2025 14:10:55 -0400 Subject: [PATCH 055/336] Stubbing out hash operation node, borrowing from cipher operaiton node --- .../codeql/cryptography/Model.qll | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 298b270e6b62..0e8a39596756 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -1031,8 +1031,29 @@ module CryptographyBase Input> { * This operation takes an input message of arbitrary content and length and produces a fixed-size * hash value as the output using a specified hashing algorithm. */ - abstract class HashOperationNode extends OperationNode, THashOperation { - abstract HashAlgorithmNode getAlgorithm(); + class HashOperationNode extends OperationNode, THashOperation { + HashAlgorithmInstance instance; + + HashOperationNode() { this = THashOperation(instance) } + + override string getInternalType() { result = "HashOperation" } + + override LocatableElement asElement() { result = instance } + + /** + * Gets the algorithm or unknown source nodes consumed as an algorithm associated with this operation. + */ + NodeBase getACipherAlgorithmOrUnknown() { + result = this.getAKnownCipherAlgorithm() or + result = this.asElement().(OperationElement).getAlgorithmConsumer().getAnUnknownSourceNode() + } + + /** + * Gets a known algorithm associated with this operation + */ + HashAlgorithmNode getAKnownCipherAlgorithm() { + result = this.asElement().(OperationElement).getAlgorithmConsumer().getAKnownSourceNode() + } } newtype THashType = From 036035b6a224d70e1105a96fe2c29270bf3b4fb3 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 10 Mar 2025 15:04:19 -0400 Subject: [PATCH 056/336] Adding modeling for OpenSSL random number generation. --- .../experimental/Quantum/OpenSSL/OpenSSL.qll | 1 + .../experimental/Quantum/OpenSSL/Random.qll | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/Random.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll index 6c30bec16cdd..9e48f8cbb934 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll @@ -7,6 +7,7 @@ module OpenSSLModel { import experimental.Quantum.OpenSSL.EVPHashOperation import experimental.Quantum.OpenSSL.EVPCipherAlgorithmSource import experimental.Quantum.OpenSSL.EVPHashAlgorithmSource + import experimental.Quantum.OpenSSL.Random // // TODO: trace CTX from init variants to the context arg of EVP update calls diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Random.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/Random.qll new file mode 100644 index 000000000000..eceff8748743 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/Random.qll @@ -0,0 +1,21 @@ +import cpp +private import experimental.Quantum.Language +private import codeql.cryptography.Model +private import LibraryDetector +private import semmle.code.cpp.dataflow.new.DataFlow + +class OpenSSLRandomNumberGeneratorInstance extends Crypto::RandomNumberGenerationInstance instanceof Call +{ + OpenSSLRandomNumberGeneratorInstance() { + this.(Call).getTarget().getName() in ["RAND_bytes", "RAND_pseudo_bytes"] and + isPossibleOpenSSLFunction(this.(Call).getTarget()) + } + + override Crypto::DataFlowNode getOutputNode() { + result.asDefiningArgument() = this.(Call).getArgument(0) + } + + override predicate flowsTo(Crypto::FlowAwareElement other) { + ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) + } +} From c83cb533ce4dac9fcd5082bc82c562ccc8afc0d6 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 10 Mar 2025 15:56:01 -0400 Subject: [PATCH 057/336] Adding an instantiation of the additional flow step class to automatically apply to generic dataflow. Flow step passthrough comes from the algorithm to getter flow passthroughs. --- cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll | 2 ++ .../Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll index 9e48f8cbb934..16b9e6485c96 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll @@ -8,6 +8,8 @@ module OpenSSLModel { import experimental.Quantum.OpenSSL.EVPCipherAlgorithmSource import experimental.Quantum.OpenSSL.EVPHashAlgorithmSource import experimental.Quantum.OpenSSL.Random + // Imports the additional algorithm flow step for OpenSSL + import experimental.Quantum.OpenSSL.OpenSSLAlgorithmGetter // // TODO: trace CTX from init variants to the context arg of EVP update calls diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll index 689f022b56dc..02d0d8339183 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll @@ -4,6 +4,14 @@ import LibraryDetector import OpenSSLKnownAlgorithmConstants import experimental.Quantum.Language +class OpenSSLAlgorithmAdditionalFlowStep extends AdditionalFlowInputStep { + OpenSSLAlgorithmAdditionalFlowStep() { exists(AlgorithmPassthroughCall c | c.getInNode() = this) } + + override DataFlow::Node getOutput() { + exists(AlgorithmPassthroughCall c | c.getInNode() = this and c.getOutNode() = result) + } +} + module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { exists(OpenSSLAlgorithmGetterCall c | c.getResultNode() = source) From f72efa638adc9a7c9c5c69acf90bd59daee88baf Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 10 Mar 2025 16:12:53 -0400 Subject: [PATCH 058/336] Uncommenting out generic dataflow --- cpp/ql/lib/experimental/Quantum/Language.qll | 48 ++++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index f0775df1b2e6..5ec4da8d19d6 100644 --- a/cpp/ql/lib/experimental/Quantum/Language.qll +++ b/cpp/ql/lib/experimental/Quantum/Language.qll @@ -22,30 +22,30 @@ abstract class AdditionalFlowInputStep extends DataFlow::Node { } -// /** -// * Generic data source to node input configuration -// */ -// module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { -// predicate isSource(DataFlow::Node source) { -// source = any(Crypto::GenericDataSourceInstance i).getOutputNode() -// } - -// predicate isSink(DataFlow::Node sink) { -// sink = any(Crypto::FlowAwareElement other).getInputNode() -// } - -// predicate isBarrierOut(DataFlow::Node node) { -// node = any(Crypto::FlowAwareElement element).getInputNode() -// } - -// predicate isBarrierIn(DataFlow::Node node) { -// node = any(Crypto::FlowAwareElement element).getOutputNode() -// } - -// predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { -// node1.(AdditionalFlowInputStep).getOutput() = node2 -// } -// } +/** + * Generic data source to node input configuration + */ +module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source = any(Crypto::GenericDataSourceInstance i).getOutputNode() + } + + predicate isSink(DataFlow::Node sink) { + sink = any(Crypto::FlowAwareElement other).getInputNode() + } + + predicate isBarrierOut(DataFlow::Node node) { + node = any(Crypto::FlowAwareElement element).getInputNode() + } + + predicate isBarrierIn(DataFlow::Node node) { + node = any(Crypto::FlowAwareElement element).getOutputNode() + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + node1.(AdditionalFlowInputStep).getOutput() = node2 + } +} From ae574f7cf2b67a981e7052851d23a85a601a421a Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 11 Mar 2025 13:35:02 -0400 Subject: [PATCH 059/336] Resolving hash and cipher types for openssl not using literals but KnownOpenSSLAlgorithmConstant. --- .../Quantum/OpenSSL/EVPCipherAlgorithmSource.qll | 14 +++++++++----- .../Quantum/OpenSSL/EVPHashAlgorithmSource.qll | 11 +++++++---- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll index 2c1930698b12..8718fb5b44db 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll @@ -9,9 +9,9 @@ import OpenSSLAlgorithmGetter * If the literal does not represent any known cipher algorithm, * this predicate will not hold (i.e., it will not bind an unknown to an unknown cipher type) */ -predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) { - exists(string name, string algType | algType.toLowerCase().matches("%encryption") | - resolveAlgorithmFromLiteral(e, name, algType) and +predicate knownOpenSSLConstantToCipherFamilyType(KnownOpenSSLAlgorithmConstant e, Crypto::TCipherType type) { + exists(string name | e.getAlgType().toLowerCase().matches("%encryption") | + name = e.getNormalizedName() and ( name.matches("AES%") and type instanceof Crypto::AES or @@ -97,5 +97,9 @@ class KnownOpenSSLCipherConstantAlgorithmInstance extends Crypto::CipherAlgorith override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } - override Crypto::TCipherType getCipherFamily() { literalToCipherFamilyType(this, result) } -} + override Crypto::TCipherType getCipherFamily() { + knownOpenSSLConstantToCipherFamilyType(this, result) + or + not knownOpenSSLConstantToCipherFamilyType(this, _) and result = Crypto::OtherCipherType() + } +} \ No newline at end of file diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll index 5fc61c7b6c57..d89eee2590d1 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll @@ -2,9 +2,9 @@ import cpp import experimental.Quantum.Language import OpenSSLAlgorithmGetter -predicate literalToHashFamilyType(Literal e, Crypto::THashType type) { - exists(string name, string algType | algType.toLowerCase().matches("hash") | - resolveAlgorithmFromLiteral(e, name, algType) and +predicate knownOpenSSLConstantToHashFamilyType(KnownOpenSSLAlgorithmConstant e, Crypto::THashType type) { + exists(string name | e.getAlgType().toLowerCase().matches("hash") | + name = e.getNormalizedName() and ( name.matches("BLAKE2B") and type instanceof Crypto::BLAKE2B or @@ -70,7 +70,10 @@ class KnownOpenSSLHashConstantAlgorithmInstance extends Crypto::HashAlgorithmIns AlgGetterToAlgConsumerFlow::flow(getterCall.getResultNode(), DataFlow::exprNode(result)) } - override Crypto::THashType getHashFamily() { literalToHashFamilyType(this, result) } + override Crypto::THashType getHashFamily() { + knownOpenSSLConstantToHashFamilyType(this, result) or + not knownOpenSSLConstantToHashFamilyType(this, _) and result = Crypto::OtherHashType() + } override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } From f69b0578936314eed92339e1d43ba753b029cb45 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 11 Mar 2025 13:35:44 -0400 Subject: [PATCH 060/336] Updating OpenSSLKnownAlgorithmConstants.qll (a few bugs) and also enforcing that known key sizes are on the normalized name (need to re-visit for GOST). --- .../OpenSSLKnownAlgorithmConstants.qll | 64 +++++++++---------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll index 063a7084d3db..0d328e287f6a 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll @@ -302,85 +302,85 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "aria-128-cbc" and nid = 1066 and normalized = "CBC" and algType = "BLOCK_MODE" or - name = "aria-128-cbc" and nid = 1066 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-cbc" and nid = 1066 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-128-cfb" and nid = 1067 and normalized = "CFB" and algType = "BLOCK_MODE" or - name = "aria-128-cfb" and nid = 1067 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-cfb" and nid = 1067 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-128-ctr" and nid = 1069 and normalized = "CTR" and algType = "BLOCK_MODE" or - name = "aria-128-ctr" and nid = 1069 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-ctr" and nid = 1069 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-128-ecb" and nid = 1065 and normalized = "ECB" and algType = "BLOCK_MODE" or - name = "aria-128-ecb" and nid = 1065 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-ecb" and nid = 1065 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-128-ofb" and nid = 1068 and normalized = "OFB" and algType = "BLOCK_MODE" or - name = "aria-128-ofb" and nid = 1068 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-ofb" and nid = 1068 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" or - name = "aria-128-cfb1" and nid = 1080 and normalized = "CFB" and algType = "BLOCK_MODE" + name = "aria-128-cfb1" and nid = 1080 and normalized = "CFB1" and algType = "BLOCK_MODE" or - name = "aria-128-cfb1" and nid = 1080 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-cfb1" and nid = 1080 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" or - name = "aria-128-cfb8" and nid = 1083 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-cfb8" and nid = 1083 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-128-cfb8" and nid = 1083 and normalized = "CFB8" and algType = "BLOCK_MODE" or name = "aria-192-cbc" and nid = 1071 and normalized = "CBC" and algType = "BLOCK_MODE" or - name = "aria-192-cbc" and nid = 1071 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-cbc" and nid = 1071 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-192-cfb" and nid = 1072 and normalized = "CFB" and algType = "BLOCK_MODE" or - name = "aria-192-cfb" and nid = 1072 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-cfb" and nid = 1072 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-192-ctr" and nid = 1074 and normalized = "CTR" and algType = "BLOCK_MODE" or - name = "aria-192-ctr" and nid = 1074 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-ctr" and nid = 1074 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-192-ecb" and nid = 1070 and normalized = "ECB" and algType = "BLOCK_MODE" or - name = "aria-192-ecb" and nid = 1070 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-ecb" and nid = 1070 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-192-ofb" and nid = 1073 and normalized = "OFB" and algType = "BLOCK_MODE" or - name = "aria-192-ofb" and nid = 1073 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-ofb" and nid = 1073 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" or - name = "aria-192-cfb1" and nid = 1081 and normalized = "CFB" and algType = "BLOCK_MODE" + name = "aria-192-cfb1" and nid = 1081 and normalized = "CFB1" and algType = "BLOCK_MODE" or - name = "aria-192-cfb1" and nid = 1081 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-cfb1" and nid = 1081 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" or - name = "aria-192-cfb8" and nid = 1084 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-cfb8" and nid = 1084 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-192-cfb8" and nid = 1084 and normalized = "CFB8" and algType = "BLOCK_MODE" or name = "aria-256-cbc" and nid = 1076 and normalized = "CBC" and algType = "BLOCK_MODE" or - name = "aria-256-cbc" and nid = 1076 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-cbc" and nid = 1076 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-256-cfb" and nid = 1077 and normalized = "CFB" and algType = "BLOCK_MODE" or - name = "aria-256-cfb" and nid = 1077 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-cfb" and nid = 1077 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-256-ctr" and nid = 1079 and normalized = "CTR" and algType = "BLOCK_MODE" or - name = "aria-256-ctr" and nid = 1079 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-ctr" and nid = 1079 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-256-ecb" and nid = 1075 and normalized = "ECB" and algType = "BLOCK_MODE" or - name = "aria-256-ecb" and nid = 1075 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-ecb" and nid = 1075 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-256-ofb" and nid = 1078 and normalized = "OFB" and algType = "BLOCK_MODE" or - name = "aria-256-ofb" and nid = 1078 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-ofb" and nid = 1078 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" or - name = "aria-256-cfb1" and nid = 1082 and normalized = "CFB" and algType = "BLOCK_MODE" + name = "aria-256-cfb1" and nid = 1082 and normalized = "CFB1" and algType = "BLOCK_MODE" or - name = "aria-256-cfb1" and nid = 1082 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-cfb1" and nid = 1082 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" or - name = "aria-256-cfb8" and nid = 1085 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-cfb8" and nid = 1085 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-256-cfb8" and nid = 1085 and normalized = "CFB8" and algType = "BLOCK_MODE" or @@ -1386,27 +1386,27 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "aria-128-ccm" and nid = 1120 and normalized = "CCM" and algType = "BLOCK_MODE" or - name = "aria-128-ccm" and nid = 1120 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-ccm" and nid = 1120 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-192-ccm" and nid = 1121 and normalized = "CCM" and algType = "BLOCK_MODE" or - name = "aria-192-ccm" and nid = 1121 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-ccm" and nid = 1121 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-256-ccm" and nid = 1122 and normalized = "CCM" and algType = "BLOCK_MODE" or - name = "aria-256-ccm" and nid = 1122 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-ccm" and nid = 1122 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-128-gcm" and nid = 1123 and normalized = "GCM" and algType = "BLOCK_MODE" or - name = "aria-128-gcm" and nid = 1123 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-gcm" and nid = 1123 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-192-gcm" and nid = 1124 and normalized = "GCM" and algType = "BLOCK_MODE" or - name = "aria-192-gcm" and nid = 1124 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-gcm" and nid = 1124 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aria-256-gcm" and nid = 1125 and normalized = "GCM" and algType = "BLOCK_MODE" or - name = "aria-256-gcm" and nid = 1125 and normalized = "ARIA" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-gcm" and nid = 1125 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" or name = "sm4-cfb1" and nid = 1136 and normalized = "SM4" and algType = "SYMMETRIC_ENCRYPTION" or @@ -2678,14 +2678,10 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "rsaes-oaep" and nid = 919 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "rsaes-oaep" and nid = 919 and normalized = "AES" and algType = "SYMMETRIC_ENCRYPTION" - or name = "rsaes-oaep" and nid = 919 and normalized = "OAEP" and algType = "ASYMMETRIC_PADDING" or name = "rsaesoaep" and nid = 919 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "rsaesoaep" and nid = 919 and normalized = "AES" and algType = "SYMMETRIC_ENCRYPTION" - or name = "rsaesoaep" and nid = 919 and normalized = "OAEP" and algType = "ASYMMETRIC_PADDING" or name = "rsaoaepencryptionset" and From 085e8d40fd0c2d2ccfd801be695b66ed627bfd68 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 11 Mar 2025 14:06:36 -0400 Subject: [PATCH 061/336] Hash nodes have instances. --- shared/cryptography/codeql/cryptography/Model.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 0e8a39596756..4ad83b12210f 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -1078,6 +1078,8 @@ module CryptographyBase Input> { * A hashing algorithm that transforms variable-length input into a fixed-size hash value. */ abstract class HashAlgorithmNode extends AlgorithmNode, THashAlgorithm { + HashAlgorithmInstance instance; + HashAlgorithmNode() { this = THashAlgorithm(instance) } override string getInternalType() { result = "HashAlgorithm" } final predicate hashTypeToNameMapping(THashType type, string name) { From 44b1e921d6fd0609e65fc7874b21a09c3fdec2f3 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 11 Mar 2025 14:10:04 -0400 Subject: [PATCH 062/336] commenting out hash size for now, TODO --- .../lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll | 2 +- shared/cryptography/codeql/cryptography/Model.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll index d89eee2590d1..d269658c8aab 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll @@ -77,5 +77,5 @@ class KnownOpenSSLHashConstantAlgorithmInstance extends Crypto::HashAlgorithmIns override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } - override int getHashSize() { none() } //TODO + // override int getHashSize() { none() } //TODO } diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 4ad83b12210f..74a9b5d02a76 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -369,7 +369,7 @@ module CryptographyBase Input> { */ abstract THashType getHashFamily(); - abstract int getHashSize(); + // abstract int getHashSize(); } abstract class KeyDerivationOperationInstance extends KnownElement { } From 7757279908a1e9049d20e67b4651d7018d7ed285 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 11 Mar 2025 14:46:36 -0400 Subject: [PATCH 063/336] Adding a KDF algorithm getter. --- .../OpenSSL/OpenSSLAlgorithmGetter.qll | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll index 02d0d8339183..364bb3ab0b82 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll @@ -255,6 +255,30 @@ class EVPDigestGetterCall extends OpenSSLAlgorithmGetterCall { override Expr getResultExpr() { result = resultExpr } } + +class EVPKDFFetch extends OpenSSLAlgorithmGetterCall { + DataFlow::Node valueArgNode; + DataFlow::Node resultNode; + Expr valueArgExpr; + Expr resultExpr; + + EVPKDFFetch() { + resultExpr = this and + resultNode.asExpr() = this and + isPossibleOpenSSLFunction(this.getTarget()) and + this.getTarget().getName() in ["EVP_KDF_fetch"] and + valueArgExpr = this.getArgument(1) and + valueArgNode.asExpr() = valueArgExpr + } + + override DataFlow::Node getValueArgNode() { result = valueArgNode } + + override DataFlow::Node getResultNode() { result = resultNode } + + override Expr getValueArgExpr() { result = valueArgExpr } + + override Expr getResultExpr() { result = resultExpr } +} // /** // * Predicates/classes for identifying algorithm sinks. // * An Algorithm Sink is a function that takes an algorithm as an argument. From d988afd4a4b3cd177dab2dd48f933c14c04061ee Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 11 Mar 2025 14:47:10 -0400 Subject: [PATCH 064/336] Adding an EVP_AASYM_CIPHER_fetch getter. --- .../OpenSSL/OpenSSLAlgorithmGetter.qll | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll index 364bb3ab0b82..3e061eeff88f 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll @@ -224,6 +224,30 @@ class EVPCipherGetterCall extends OpenSSLAlgorithmGetterCall { override Expr getResultExpr() { result = resultExpr } } +class EVPAsymCipherGetterCall extends OpenSSLAlgorithmGetterCall { + DataFlow::Node valueArgNode; + DataFlow::Node resultNode; + Expr valueArgExpr; + Expr resultExpr; + + EVPAsymCipherGetterCall() { + isPossibleOpenSSLFunction(this.getTarget()) and + resultExpr = this and + resultNode.asExpr() = this and + this.getTarget().getName() = "EVP_ASYM_CIPHER_fetch" and + valueArgExpr = this.getArgument(1) and + valueArgNode.asExpr() = valueArgExpr + } + + override DataFlow::Node getValueArgNode() { result = valueArgNode } + + override DataFlow::Node getResultNode() { result = resultNode } + + override Expr getValueArgExpr() { result = valueArgExpr } + + override Expr getResultExpr() { result = resultExpr } +} + class EVPDigestGetterCall extends OpenSSLAlgorithmGetterCall { DataFlow::Node valueArgNode; DataFlow::Node resultNode; From a9458ba762875bacfc985242883d90d894095eed Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 11 Mar 2025 14:48:38 -0400 Subject: [PATCH 065/336] Formatting, removing dead comments, --- .../Quantum/OpenSSL/EVPCipherOperation.qll | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll index 4913d2763e96..fd95bb718056 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll @@ -46,14 +46,12 @@ abstract class EVP_Final_Call extends EVP_Cipher_Operation { } class EVP_Cipher_Call extends EVP_Cipher_Operation { - // TODO/QUESTION: what is the better way to do this? EVP_Cipher_Call() { this.(Call).getTarget().getName() = "EVP_Cipher" } override Expr getInputArg() { result = this.(Call).getArgument(2) } } class EVP_Encrypt_Decrypt_or_Cipher_Update_Call extends EVP_Update_Call { - // TODO/QUESTION: what is the better way to do this? EVP_Encrypt_Decrypt_or_Cipher_Update_Call() { this.(Call).getTarget().getName() in [ "EVP_EncryptUpdate", "EVP_DecryptUpdate", "EVP_CipherUpdate" @@ -64,10 +62,8 @@ class EVP_Encrypt_Decrypt_or_Cipher_Update_Call extends EVP_Update_Call { } class EVP_Encrypt_Decrypt_or_Cipher_Final_Call extends EVP_Final_Call { - // TODO/QUESTION: what is the better way to do this? EVP_Encrypt_Decrypt_or_Cipher_Final_Call() { - this.(Call).getTarget().getName() in - [ + this.(Call).getTarget().getName() in [ "EVP_EncryptFinal_ex", "EVP_DecryptFinal_ex", "EVP_CipherFinal_ex", "EVP_EncryptFinal", "EVP_DecryptFinal", "EVP_CipherFinal" ] @@ -77,11 +73,9 @@ class EVP_Encrypt_Decrypt_or_Cipher_Final_Call extends EVP_Final_Call { class EVPCipherOutput extends CipherOutputArtifact { EVPCipherOutput() { exists(EVP_Cipher_Operation op | op.getOutputArg() = this) } - override DataFlow::Node getOutputNode(){ - result.asExpr() = this - } + override DataFlow::Node getOutputNode() { result.asExpr() = this } } class EVPCipherInputArgument extends Expr { EVPCipherInputArgument() { exists(EVP_Cipher_Operation op | op.getInputArg() = this) } -} \ No newline at end of file +} From c98e6d7c56011e429c2f945930a41fa94b89192e Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 11 Mar 2025 14:49:07 -0400 Subject: [PATCH 066/336] Adding a stub EVP_CIpher_Operation for EVP_PKEY, this probably should be made into it's own class, hence it is a stub with comments. --- .../Quantum/OpenSSL/EVPCipherOperation.qll | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll index fd95bb718056..f426eb3f92dd 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll @@ -70,6 +70,17 @@ class EVP_Encrypt_Decrypt_or_Cipher_Final_Call extends EVP_Final_Call { } } +class EVP_PKEY_Operation extends EVP_Cipher_Operation { + EVP_PKEY_Operation() { + this.(Call).getTarget().getName() in ["EVP_PKEY_decrypt", "EVP_PKEY_encrypt"] + } + + override Expr getInputArg() { result = this.(Call).getArgument(3) } + // TODO: how PKEY is initialized is different that symmetric cipher + // Consider making an entirely new class for this and specializing + // the get init call +} + class EVPCipherOutput extends CipherOutputArtifact { EVPCipherOutput() { exists(EVP_Cipher_Operation op | op.getOutputArg() = this) } From 71eae39feb73e2d7e680b04d2c6536831864ae02 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 11 Mar 2025 15:19:42 -0400 Subject: [PATCH 067/336] Adding missing block modes. --- shared/cryptography/codeql/cryptography/Model.qll | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 74a9b5d02a76..f5f57d245ba1 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -761,12 +761,14 @@ module CryptographyBase Input> { newtype TBlockCipherModeOperationType = ECB() or // Not secure, widely used CBC() or // Vulnerable to padding oracle attacks + CFB() or GCM() or // Widely used AEAD mode (TLS 1.3, SSH, IPsec) CTR() or // Fast stream-like encryption (SSH, disk encryption) XTS() or // Standard for full-disk encryption (BitLocker, LUKS, FileVault) CCM() or // Used in lightweight cryptography (IoT, WPA2) SIV() or // Misuse-resistant encryption, used in secure storage OCB() or // Efficient AEAD mode + OFB() or OtherMode() class ModeOfOperationAlgorithmNode extends AlgorithmNode, TModeOfOperationAlgorithm { @@ -807,6 +809,10 @@ module CryptographyBase Input> { or type instanceof OCB and name = "OCB" or + type instanceof CFB and name = "CFB" + or + type instanceof OFB and name = "OFB" + or type instanceof OtherMode and name = this.getRawAlgorithmName() } From 8a7671dc2a5bdc4bdfa87a0b4a24e617e85ddb25 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 11 Mar 2025 15:20:05 -0400 Subject: [PATCH 068/336] Adding block mode models to openssl. --- .../OpenSSL/EVPCipherAlgorithmSource.qll | 94 +++++++++++++++++-- 1 file changed, 85 insertions(+), 9 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll index 8718fb5b44db..65231e32cd03 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll @@ -4,12 +4,12 @@ import EVPCipherConsumers import OpenSSLAlgorithmGetter /** - * Given a literal `e`, converts this to a cipher family type. - * The literal must be a known literal representing a cipher algorithm. - * If the literal does not represent any known cipher algorithm, - * this predicate will not hold (i.e., it will not bind an unknown to an unknown cipher type) + * Given a `KnownOpenSSLAlgorithmConstant`, converts this to a cipher family type. + * Does not bind if there is know mapping (no mapping to 'unknown' or 'other'). */ -predicate knownOpenSSLConstantToCipherFamilyType(KnownOpenSSLAlgorithmConstant e, Crypto::TCipherType type) { +predicate knownOpenSSLConstantToCipherFamilyType( + KnownOpenSSLAlgorithmConstant e, Crypto::TCipherType type +) { exists(string name | e.getAlgType().toLowerCase().matches("%encryption") | name = e.getNormalizedName() and ( @@ -90,16 +90,92 @@ class KnownOpenSSLCipherConstantAlgorithmInstance extends Crypto::CipherAlgorith } override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { - none() // TODO: provider defaults + // if there is a block mode associated with the same element, then that's the block mode + // note, if none are associated, we may need to parse if the cipher is a block cipher + // to determine if this is an unknown vs not relevant. + result = this } override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { none() } override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } - override Crypto::TCipherType getCipherFamily() { - knownOpenSSLConstantToCipherFamilyType(this, result) + override Crypto::TCipherType getCipherFamily() { + knownOpenSSLConstantToCipherFamilyType(this, result) or not knownOpenSSLConstantToCipherFamilyType(this, _) and result = Crypto::OtherCipherType() } -} \ No newline at end of file +} + +/** + * Given a `KnownOpenSSLAlgorithmConstant`, converts this to a cipher family type. + * Does not bind if there is know mapping (no mapping to 'unknown' or 'other'). + */ +predicate knownOpenSSLConstantToBlockModeFamilyType( + KnownOpenSSLAlgorithmConstant e, Crypto::TBlockCipherModeOperationType type +) { + exists(string name | e.getAlgType().toLowerCase().matches("block_mode") | + name = e.getNormalizedName() and + ( + name.matches("CBC") and type instanceof Crypto::CBC + or + name.matches("CFB%") and type instanceof Crypto::CFB + or + name.matches("CTR") and type instanceof Crypto::CTR + or + name.matches("GCM") and type instanceof Crypto::GCM + or + name.matches("OFB") and type instanceof Crypto::OFB + or + name.matches("XTS") and type instanceof Crypto::XTS + or + name.matches("CCM") and type instanceof Crypto::CCM + or + name.matches("GCM") and type instanceof Crypto::GCM + or + name.matches("CCM") and type instanceof Crypto::CCM + or + name.matches("ECB") and type instanceof Crypto::ECB + ) + ) +} + +class KnownOpenSSLBlockModeConstantAlgorithmInstance extends Crypto::ModeOfOperationAlgorithmInstance instanceof KnownOpenSSLAlgorithmConstant +{ + OpenSSLAlgorithmGetterCall getterCall; + + KnownOpenSSLBlockModeConstantAlgorithmInstance() { + // Not just any known value, but specifically a known cipher operation + this.(KnownOpenSSLAlgorithmConstant).getAlgType().toLowerCase().matches("block_mode") and + ( + // Two possibilities: + // 1) The source is a literal and flows to a getter, then we know we have an instance + // 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that + // Possibility 1: + this instanceof Literal and + exists(DataFlow::Node src, DataFlow::Node sink | + // Sink is an argument to a CipherGetterCall + sink = getterCall.(OpenSSLAlgorithmGetterCall).getValueArgNode() and + // Source is `this` + src.asExpr() = this and + // This traces to a getter + KnownOpenSSLAlgorithmToAlgorithmGetterFlow::flow(src, sink) + ) + or + // Possibility 2: + this instanceof DirectGetterCall and getterCall = this + ) + } + + override Crypto::TBlockCipherModeOperationType getModeType() { + knownOpenSSLConstantToBlockModeFamilyType(this, result) + or + not knownOpenSSLConstantToBlockModeFamilyType(this, _) and result = Crypto::OtherMode() + } + + // NOTE: I'm not going to attempt to parse out the mode specific part, so returning + // the same as the raw name for now. + override string getRawModeAlgorithmName() { result = this.(Literal).getValue().toString() } + + override string getRawAlgorithmName() { result = this.getRawModeAlgorithmName() } +} From 95607c5f31c9ee72e9b556bce21af8d92c5281de Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Tue, 18 Mar 2025 22:05:00 +0100 Subject: [PATCH 069/336] Refactor instances and consumers + add JCA hashes --- cpp/ql/lib/experimental/Quantum/Language.qll | 30 +- .../Quantum/OpenSSL/EVPCipherConsumers.qll | 2 +- .../Quantum/OpenSSL/EVPHashConsumers.qll | 35 +- java/ql/lib/experimental/Quantum/JCA.qll | 121 +++++- java/ql/lib/experimental/Quantum/Language.qll | 20 +- .../InsecureOrUnknownNonceAtOperation.ql | 9 +- .../Quantum/PossibleReusedNonce.ql | 6 +- .../ql/src/experimental/Quantum/TestCipher.ql | 3 +- java/ql/src/experimental/Quantum/TestHash.ql | 9 + .../codeql/cryptography/Model.qll | 391 +++++++++++++----- 10 files changed, 467 insertions(+), 159 deletions(-) create mode 100644 java/ql/src/experimental/Quantum/TestHash.ql diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index 5ec4da8d19d6..dbcb2004b83b 100644 --- a/cpp/ql/lib/experimental/Quantum/Language.qll +++ b/cpp/ql/lib/experimental/Quantum/Language.qll @@ -3,10 +3,11 @@ import semmle.code.cpp.ir.IR import semmle.code.cpp.security.FlowSources as FlowSources private import cpp as Lang - module CryptoInput implements InputSig { class DataFlowNode = DataFlow::Node; + class LocatableElement = Lang::Locatable; + class UnknownLocation = Lang::UnknownDefaultLocation; } @@ -21,7 +22,6 @@ abstract class AdditionalFlowInputStep extends DataFlow::Node { final DataFlow::Node getInput() { result = this } } - /** * Generic data source to node input configuration */ @@ -47,61 +47,44 @@ module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { } } - - // // // TODO: I think this will be inefficient, no? // // class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource instanceof Literal { -// // override DataFlow::Node getOutputNode() { -// // result.asExpr() = this +// // override DataFlow::Node getOutputNode() { +// // result.asExpr() = this // // } - // // override predicate flowsTo(Crypto::FlowAwareElement other) { // // // TODO: separate config to avoid blowing up data-flow analysis // // GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) // // } - // // override string getAdditionalDescription() { result = this.toString() } // // } - // /** // * Definitions of various generic data sources // */ // // final class DefaultFlowSource = SourceNode; - // // final class DefaultRemoteFlowSource = RemoteFlowSource; - // // class GenericLocalDataSource extends Crypto::GenericLocalDataSource { // // GenericLocalDataSource() { // // any(DefaultFlowSource src | not src instanceof DefaultRemoteFlowSource).asExpr() = this // // } - // // override DataFlow::Node getOutputNode() { result.asExpr() = this } - // // override predicate flowsTo(Crypto::FlowAwareElement other) { // // GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) // // } - // // override string getAdditionalDescription() { result = this.toString() } // // } - // // class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { // // GenericRemoteDataSource() { any(DefaultRemoteFlowSource src).asExpr() = this } - // // override DataFlow::Node getOutputNode() { result.asExpr() = this } - // // override predicate flowsTo(Crypto::FlowAwareElement other) { // // GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) // // } - // // override string getAdditionalDescription() { result = this.toString() } // // } - - // module GenericDataSourceUniversalFlow = DataFlow::Global; - module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { - source = any(Crypto::ArtifactElement artifact).getOutputNode() + source = any(Crypto::ArtifactInstance artifact).getOutputNode() } predicate isSink(DataFlow::Node sink) { @@ -120,12 +103,13 @@ module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { node1.(AdditionalFlowInputStep).getOutput() = node2 } } + module ArtifactUniversalFlow = DataFlow::Global; + abstract class CipherOutputArtifact extends Crypto::CipherOutputArtifactInstance { override predicate flowsTo(Crypto::FlowAwareElement other) { ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) } } - import OpenSSL.OpenSSL diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll index 4f8a5ccd354c..e2f5bc0e8380 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll @@ -6,7 +6,7 @@ class EVP_Cipher_Initializer_Algorithm_Consumer extends Crypto::AlgorithmConsume { override DataFlow::Node getInputNode() { result.asExpr() = this } - override Crypto::AlgorithmElement getAKnownAlgorithmSource() { + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { result.(KnownOpenSSLCipherConstantAlgorithmInstance).getConsumer() = this } } diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll index 2edca9d5763b..82bf331546f7 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll @@ -2,26 +2,29 @@ import EVPHashInitializer import EVPHashOperation import EVPHashAlgorithmSource -class EVP_Digest_Initializer_Algorithm_Consumer extends Crypto::AlgorithmConsumer instanceof EVPDigestInitializerAlgorithmArgument{ - override DataFlow::Node getInputNode() { result.asExpr() = this } +class EVP_Digest_Initializer_Algorithm_Consumer extends Crypto::AlgorithmValueConsumer instanceof EVPDigestInitializerAlgorithmArgument +{ + override DataFlow::Node getInputNode() { result.asExpr() = this } - override Crypto::AlgorithmElement getAKnownAlgorithmSource() { - result.(KnownOpenSSLHashConstantAlgorithmInstance).getConsumer() = this - } + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + result.(KnownOpenSSLHashConstantAlgorithmInstance).getConsumer() = this + } } -class EVP_Q_Digest_Algorithm_Consumer extends Crypto::AlgorithmConsumer instanceof EVP_Q_Digest_Algorithm_Argument{ - override DataFlow::Node getInputNode() { result.asExpr() = this } +class EVP_Q_Digest_Algorithm_Consumer extends Crypto::AlgorithmValueConsumer instanceof EVP_Q_Digest_Algorithm_Argument +{ + override DataFlow::Node getInputNode() { result.asExpr() = this } - override Crypto::AlgorithmElement getAKnownAlgorithmSource() { - result.(KnownOpenSSLHashConstantAlgorithmInstance).getConsumer() = this - } + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + result.(KnownOpenSSLHashConstantAlgorithmInstance).getConsumer() = this + } } -class EVP_Digest_Algorithm_Consumer extends Crypto::AlgorithmConsumer instanceof EVP_Digest_Algorithm_Argument{ - override DataFlow::Node getInputNode() { result.asExpr() = this } +class EVP_Digest_Algorithm_Consumer extends Crypto::AlgorithmValueConsumer instanceof EVP_Digest_Algorithm_Argument +{ + override DataFlow::Node getInputNode() { result.asExpr() = this } - override Crypto::AlgorithmElement getAKnownAlgorithmSource() { - result.(KnownOpenSSLHashConstantAlgorithmInstance).getConsumer() = this - } -} \ No newline at end of file + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + result.(KnownOpenSSLHashConstantAlgorithmInstance).getConsumer() = this + } +} diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index b2698cabee24..336f7fe5cc55 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -205,7 +205,7 @@ module JCAModel { * * For example, in `Cipher.getInstance(algorithm)`, this class represents `algorithm`. */ - class CipherGetInstanceAlgorithmArg extends Crypto::AlgorithmConsumer instanceof Expr { + class CipherGetInstanceAlgorithmArg extends Crypto::AlgorithmValueConsumer instanceof Expr { CipherGetInstanceCall call; CipherGetInstanceAlgorithmArg() { this = call.getAlgorithmArg() } @@ -218,7 +218,7 @@ module JCAModel { value = result.getValue() } - override Crypto::AlgorithmElement getAKnownAlgorithmSource() { + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { result.(CipherStringLiteralAlgorithmInstance).getConsumer() = this } } @@ -354,15 +354,17 @@ module JCAModel { override Crypto::CipherOperationSubtype getCipherOperationSubtype() { result = mode } - override Crypto::NonceArtifactConsumer getNonceConsumer() { - result = sink.getState().(InitializedCipherModeFlowState).getInitCall().getNonceArg() + override DataFlow::Node getNonceConsumer() { + result.asExpr() = sink.getState().(InitializedCipherModeFlowState).getInitCall().getNonceArg() } - override Crypto::CipherInputConsumer getInputConsumer() { - result = doFinalize.getMessageArg().asExpr() + override DataFlow::Node getInputConsumer() { result = doFinalize.getMessageArg() } + + override DataFlow::Node getKeyConsumer() { + result.asExpr() = sink.getState().(InitializedCipherModeFlowState).getInitCall().getKeyArg() } - override Crypto::AlgorithmConsumer getAlgorithmConsumer() { result = consumer } + override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { result = consumer } override Crypto::CipherOutputArtifactInstance getOutputArtifact() { result = doFinalize.getOutput() @@ -493,27 +495,114 @@ module JCAModel { } } - class CipherInitCallNonceArgConsumer extends Crypto::NonceArtifactConsumer instanceof Expr { - CipherInitCallNonceArgConsumer() { this = any(CipherInitCall call).getNonceArg() } + class CipherInitCallKeyConsumer extends Crypto::ArtifactConsumer { + CipherInitCallKeyConsumer() { this = any(CipherInitCall call).getKeyArg() } override DataFlow::Node getInputNode() { result.asExpr() = this } } - class CipherInitCallKeyConsumer extends Crypto::ArtifactConsumer { - CipherInitCallKeyConsumer() { this = any(CipherInitCall call).getKeyArg() } + class CipherOperationCallOutput extends CipherOutputArtifact { + CipherOperationCallOutput() { this = any(CipherOperationCall call).getOutput() } - override DataFlow::Node getInputNode() { result.asExpr() = this } + override DataFlow::Node getOutputNode() { result.asExpr() = this } + } + + bindingset[hash] + predicate hash_names(string hash) { + hash.toUpperCase() + .matches([ + "SHA-1", "SHA-256", "SHA-384", "SHA-512", "SHA3-224", "SHA3-256", "SHA3-384", + "SHA3-512", "BLAKE2b", "BLAKE2s" + ].toUpperCase()) + } + + // flow config from a known hash algorithm literal to MessageDigest.getInstance + module KnownHashAlgorithmLiteralToMessageDigestConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { hash_names(src.asExpr().(StringLiteral).getValue()) } + + predicate isSink(DataFlow::Node sink) { + exists(MessageDigestGetInstanceCall call | sink.asExpr() = call.getAlgorithmArg()) + } + } + + module KnownHashAlgorithmLiteralToMessageDigestFlow = + DataFlow::Global; + + class KnownHashAlgorithm extends Crypto::HashAlgorithmInstance instanceof StringLiteral { + MessageDigestAlgorithmValueConsumer consumer; + + KnownHashAlgorithm() { + hash_names(this.getValue()) and + KnownHashAlgorithmLiteralToMessageDigestFlow::flow(DataFlow::exprNode(this), + consumer.getInputNode()) + } + + MessageDigestAlgorithmValueConsumer getConsumer() { result = consumer } + + override string getRawAlgorithmName() { result = this.(StringLiteral).getValue() } + + override Crypto::THashType getHashFamily() { + result = Crypto::OtherHashType() // TODO + } } - class CipherMessageInputConsumer extends Crypto::CipherInputConsumer { - CipherMessageInputConsumer() { this = any(CipherOperationCall call).getMessageArg().asExpr() } + class MessageDigestAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { + MessageDigestGetInstanceCall call; + + MessageDigestAlgorithmValueConsumer() { this = call.getAlgorithmArg() } override DataFlow::Node getInputNode() { result.asExpr() = this } + + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + exists(KnownHashAlgorithm l | l.getConsumer() = this and result = l) + } } - class CipherOperationCallOutput extends CipherOutputArtifact { - CipherOperationCallOutput() { this = any(CipherOperationCall call).getOutput() } + class MessageDigestGetInstanceCall extends MethodCall { + MessageDigestGetInstanceCall() { + this.getCallee().hasQualifiedName("java.security", "MessageDigest", "getInstance") + } + + Expr getAlgorithmArg() { result = this.getArgument(0) } + + DigestHashOperation getDigestCall() { + DigestGetInstanceToDigestFlow::flow(DataFlow::exprNode(this), + DataFlow::exprNode(result.(DigestCall).getQualifier())) + } + } + + class DigestCall extends MethodCall { + DigestCall() { this.getCallee().hasQualifiedName("java.security", "MessageDigest", "digest") } + + Expr getDigestArtifactOutput() { result = this } + } + + // flow config from MessageDigest.getInstance to MessageDigest.digest + module DigestGetInstanceToDigestConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof MessageDigestGetInstanceCall } + + predicate isSink(DataFlow::Node sink) { + exists(DigestCall c | c.getQualifier() = sink.asExpr()) + } + } + + module DigestGetInstanceToDigestFlow = DataFlow::Global; + + class DigestArtifact extends DigestArtifactInstance { + DigestArtifact() { this = any(DigestCall call).getDigestArtifactOutput() } override DataFlow::Node getOutputNode() { result.asExpr() = this } } + + class DigestHashOperation extends Crypto::HashOperationInstance instanceof DigestCall { + override Crypto::DigestArtifactInstance getDigestArtifact() { + result = this.(DigestCall).getDigestArtifactOutput() + } + + override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { + exists(MessageDigestGetInstanceCall call | + call.getDigestCall() = this and result = call.getAlgorithmArg() + ) + } + } } diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 0e875295bd8a..5666a0c42bb5 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -25,6 +25,11 @@ module CryptoInput implements InputSig { class LocatableElement = Language::Element; class UnknownLocation = UnknownDefaultLocation; + + LocatableElement dfn_to_element(DataFlow::Node node) { + result = node.asExpr() or + result = node.asParameter() + } } /** @@ -100,6 +105,17 @@ class InsecureRandomnessInstance extends RandomnessInstance { InsecureRandomnessInstance() { exists(InsecureRandomnessSource node | this = node.asExpr()) } } +/** + * Output artifact flow logic + */ +abstract class DigestArtifactInstance extends Crypto::DigestArtifactInstance { + override predicate flowsTo(Crypto::FlowAwareElement other) { + ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) + } + + override predicate isConsumerArtifact() { none() } +} + /** * Artifact output to node input configuration */ @@ -115,6 +131,8 @@ abstract class CipherOutputArtifact extends Crypto::CipherOutputArtifactInstance override predicate flowsTo(Crypto::FlowAwareElement other) { ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) } + + override predicate isConsumerArtifact() { none() } } /** @@ -144,7 +162,7 @@ module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { - source = any(Crypto::ArtifactElement artifact).getOutputNode() + source = any(Crypto::ArtifactInstance artifact).getOutputNode() } predicate isSink(DataFlow::Node sink) { diff --git a/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql b/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql index cdeeebd5a7d7..7fea3515b7dd 100644 --- a/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql +++ b/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql @@ -6,17 +6,19 @@ import experimental.Quantum.Language -from Crypto::NonceNode n, Crypto::CipherOperationNode op, Crypto::FlowAwareElement src, string msg +from + Crypto::NonceArtifactNode n, Crypto::CipherOperationNode op, Crypto::FlowAwareElement src, + string msg where op.getANonce() = n and // Only encryption mode is relevant for insecure nonces, consder any 'unknown' subtype - // as possibly encryption. + // as possibly encryption. ( op.getCipherOperationSubtype() instanceof Crypto::EncryptionSubtype or op.getCipherOperationSubtype() instanceof Crypto::WrapSubtype or - op.getCipherOperationSubtype() instanceof Crypto::UnwrapSubtype + op.getCipherOperationSubtype() instanceof Crypto::UnwrapSubtype ) and ( // Known sources cases that are not secure @@ -30,7 +32,6 @@ where src = n.asElement() ) select n, msg, src, src.toString() - // variant using instances, does not yield the same results // from Crypto::NonceArtifactConsumer n, Crypto::CipherOperationInstance op, Crypto::FlowAwareElement src, string msg // where diff --git a/java/ql/src/experimental/Quantum/PossibleReusedNonce.ql b/java/ql/src/experimental/Quantum/PossibleReusedNonce.ql index fde1ef121786..f9fc7a873db1 100644 --- a/java/ql/src/experimental/Quantum/PossibleReusedNonce.ql +++ b/java/ql/src/experimental/Quantum/PossibleReusedNonce.ql @@ -1,14 +1,16 @@ /** * @name Possible Nonce Reuse: Produces false positives if reuse occurs in a source that is a re-entry point. * @id java/possible-nonce-reuse + * @kind problem */ import experimental.Quantum.Language import semmle.code.java.dataflow.DataFlow from - Crypto::CipherOperationNode op1, Crypto::CipherOperationNode op2, Crypto::NonceNode nonce1, - Crypto::NonceNode nonce2, Crypto::FlowAwareElement src1, Crypto::FlowAwareElement src2 + Crypto::CipherOperationNode op1, Crypto::CipherOperationNode op2, + Crypto::NonceArtifactNode nonce1, Crypto::NonceArtifactNode nonce2, Crypto::FlowAwareElement src1, + Crypto::FlowAwareElement src2 where // NOTE: not looking at value of the nonce, if we knew value, it would be insecure (hard coded) // Instead trying to find nonce sources that trace to multiple operations. diff --git a/java/ql/src/experimental/Quantum/TestCipher.ql b/java/ql/src/experimental/Quantum/TestCipher.ql index fa04770d8549..b98347a57eca 100644 --- a/java/ql/src/experimental/Quantum/TestCipher.ql +++ b/java/ql/src/experimental/Quantum/TestCipher.ql @@ -6,7 +6,8 @@ import experimental.Quantum.Language from Crypto::CipherOperationNode op, Crypto::CipherAlgorithmNode a, - Crypto::ModeOfOperationAlgorithmNode m, Crypto::PaddingAlgorithmNode p, Crypto::NonceNode nonce + Crypto::ModeOfOperationAlgorithmNode m, Crypto::PaddingAlgorithmNode p, + Crypto::NonceArtifactNode nonce where a = op.getAKnownCipherAlgorithm() and m = a.getModeOfOperation() and diff --git a/java/ql/src/experimental/Quantum/TestHash.ql b/java/ql/src/experimental/Quantum/TestHash.ql new file mode 100644 index 000000000000..96f99193cba4 --- /dev/null +++ b/java/ql/src/experimental/Quantum/TestHash.ql @@ -0,0 +1,9 @@ +/** + * @name TestHashOperations + */ + +import experimental.Quantum.Language + +from Crypto::HashOperationNode op, Crypto::HashAlgorithmNode alg +where alg = op.getAKnownHashAlgorithm() +select op, op.getDigest(), alg, alg.getRawAlgorithmName() diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index f5f57d245ba1..cebbac2ff6bd 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -4,6 +4,7 @@ import codeql.util.Location import codeql.util.Option +import codeql.util.Either signature module InputSig { class LocatableElement { @@ -19,6 +20,8 @@ signature module InputSig { } class UnknownLocation instanceof Location; + + LocatableElement dfn_to_element(DataFlowNode node); } module CryptographyBase Input> { @@ -50,12 +53,12 @@ module CryptographyBase Input> { NodeBase getPassthroughNodeChild(NodeBase node) { result = node.(CipherInputNode).getChild(_) or - result = node.(NonceNode).getChild(_) + result = node.(NonceArtifactNode).getChild(_) } predicate isPassthroughNode(NodeBase node) { node instanceof CipherInputNode or - node instanceof NonceNode + node instanceof NonceArtifactNode } predicate nodes_graph_impl(NodeBase node, string key, string value) { @@ -121,7 +124,7 @@ module CryptographyBase Input> { } /** - * An element that represents a _known_ cryptographic asset. + * An element that represents a _known_ cryptographic asset with a determinable value OR an artifact. * * CROSS PRODUCT WARNING: Do not model any *other* element that is a `FlowAwareElement` to the same * instance in the database, as every other `KnownElement` will share that output artifact's flow. @@ -133,17 +136,17 @@ module CryptographyBase Input> { /** * An element that represents a _known_ cryptographic operation. */ - abstract class OperationElement extends KnownElement { + abstract class OperationInstance extends KnownElement { /** - * Gets the consumer of algorithms associated with this operation. + * Gets the consumers of algorithm values associated with this operation. */ - abstract AlgorithmConsumer getAlgorithmConsumer(); + abstract AlgorithmValueConsumer getAnAlgorithmValueConsumer(); } /** * An element that represents a _known_ cryptographic algorithm. */ - abstract class AlgorithmElement extends KnownElement { + abstract class AlgorithmInstance extends KnownElement { /** * Gets the raw name as it appears in source, e.g., "AES/CBC/PKCS7Padding". * This name is not parsed or formatted. @@ -151,11 +154,6 @@ module CryptographyBase Input> { abstract string getRawAlgorithmName(); } - /** - * An element that represents a _known_ cryptographic artifact. - */ - abstract class ArtifactElement extends KnownElement, FlowAwareElement { } - /** * An element that represents an _unknown_ data-source with a non-statically determinable value. */ @@ -198,6 +196,7 @@ module CryptographyBase Input> { override DataFlowNode getOutputNode() { none() } + // for internal use only final GenericDataSourceInstance getAnUnknownSource() { result.flowsTo(this) and not result = this.getAKnownSource() } @@ -207,23 +206,31 @@ module CryptographyBase Input> { } final NodeBase getAKnownSourceNode() { result.asElement() = this.getAKnownSource() } - } - - /** - * An element that consumes _known_ and _unknown_ values. - * - * A value consumer can consume multiple values and multiple value sources at once. - */ - abstract class ValueConsumer extends ConsumerElement { - final override KnownElement getAKnownSource() { none() } - abstract string getAKnownValue(Location location); + final LocatableElement getASource() { + result = this.getAnUnknownSource() or + result = this.getAKnownSource() + } } - abstract class AlgorithmConsumer extends ConsumerElement { + abstract class AlgorithmValueConsumer extends ConsumerElement { + /** + * DO NOT USE. + * Model `getAKnownAlgorithmSource()` instead, which is equivalent but correctly typed. + */ final override KnownElement getAKnownSource() { result = this.getAKnownAlgorithmSource() } - abstract AlgorithmElement getAKnownAlgorithmSource(); + /** + * Gets a known algorithm value that is equivalent to or consumed by this element. + */ + abstract AlgorithmInstance getAKnownAlgorithmSource(); + } + + /** + * An element that represents a _known_ cryptographic artifact. + */ + abstract class ArtifactInstance extends KnownElement, FlowAwareElement { + abstract predicate isConsumerArtifact(); // whether this is an input artifact defined by its consumer } /** @@ -232,15 +239,6 @@ module CryptographyBase Input> { * The concept of "`ArtifactConsumer` = `ArtifactNode`" should be used for inputs, as a consumer can be directly tied * to the artifact it receives, thereby becoming the definitive contextual source for that artifact. * - * For example, consider a nonce artifact consumer: - * - * A `NonceArtifactConsumer` is always the `NonceArtifactInstance` itself, since data only becomes (i.e., is determined to be) - * a `NonceArtifactInstance` when it is consumed in a context that expects a nonce (e.g., an argument expecting nonce data). - * In this case, the artifact (nonce) is fully defined by the context in which it is consumed, and the consumer embodies - * that identity without the need for additional differentiation. Without the context a consumer provides, that data could - * otherwise be any other type of artifact or even simply random data. - * - * * Architectural Implications: * * By directly coupling a consumer with the node that receives an artifact, * the data flow is fully transparent with the consumer itself serving only as a transparent node. @@ -251,24 +249,114 @@ module CryptographyBase Input> { */ abstract class ArtifactConsumer extends ConsumerElement { /** + * DO NOT USE: * Use `getAKnownArtifactSource() instead. The behaviour of these two predicates is equivalent. */ final override KnownElement getAKnownSource() { result = this.getAKnownArtifactSource() } - final ArtifactElement getAKnownArtifactSource() { result.flowsTo(this) } + final ArtifactInstance getAKnownArtifactSource() { result.flowsTo(this) } } - abstract class ArtifactConsumerAndInstance extends ArtifactConsumer { - final override DataFlowNode getOutputNode() { none() } + /** + * An `ArtifactConsumer` that is also an `ArtifactInstance`. + * + * For example: + * A `NonceArtifactConsumer` is always the `NonceArtifactInstance` itself, since data only becomes (i.e., is determined to be) + * a `NonceArtifactInstance` when it is consumed in a context that expects a nonce (e.g., an argument expecting nonce data). + * In this case, the artifact (nonce) is fully defined by the context in which it is consumed, and the consumer embodies + * that identity without the need for additional differentiation. Without the context a consumer provides, that data could + * otherwise be any other type of artifact or even simply random data. + * + * TODO: what if a Nonce from hypothetical func `generateNonce()` flows to this instance which is also a Nonce? + * TODO: potential solution is creating another artifact type called NonceData or treating it as a generic source. + * + * TODO: An alternative is simply having a predicate DataFlowNode getNonceInputNode() on (for example) operations. + * Under the hood, in Model.qll, we would create the instance for the modeller, thus avoiding the need for the modeller + * to create a separate consumer class / instance themselves using this class. + */ + abstract private class ArtifactConsumerAndInstance extends ArtifactConsumer, ArtifactInstance { + override predicate isConsumerArtifact() { any() } + } + + final private class NonceArtifactConsumer extends ArtifactConsumerAndInstance { + DataFlowNode inputNode; + + NonceArtifactConsumer() { + exists(CipherOperationInstance op | inputNode = op.getNonceConsumer()) and + this = Input::dfn_to_element(inputNode) + } + + final override DataFlowNode getInputNode() { result = inputNode } + } + + final private class CipherInputArtifactConsumer extends ArtifactConsumerAndInstance { + DataFlowNode inputNode; - final override predicate flowsTo(FlowAwareElement other) { none() } + CipherInputArtifactConsumer() { + exists(CipherOperationInstance op | inputNode = op.getInputConsumer()) and + this = Input::dfn_to_element(inputNode) + } + + final override DataFlowNode getInputNode() { result = inputNode } + } + + // Output artifacts are determined solely by the element that produces them. + // Implementation guidance: these *do* need to be defined generically at the language-level + // in order for a flowsTo to be defined. At the per-modeling-instance level, extend that language-level class! + abstract class OutputArtifactInstance extends ArtifactInstance { + override predicate isConsumerArtifact() { none() } + } + + abstract class DigestArtifactInstance extends OutputArtifactInstance { + final override DataFlowNode getInputNode() { none() } + } + + abstract class RandomNumberGenerationInstance extends OutputArtifactInstance { + // TODO: input seed? + final override DataFlowNode getInputNode() { none() } } - abstract class CipherOutputArtifactInstance extends ArtifactElement { + abstract class CipherOutputArtifactInstance extends ArtifactInstance { final override DataFlowNode getInputNode() { none() } } - abstract class CipherOperationInstance extends OperationElement { + // Artifacts that may be outputs or inputs + newtype TKeyArtifactType = + TSymmetricKeyType() or + TAsymmetricKeyType() or + TUnknownKeyType() + + class KeyArtifactType extends TKeyArtifactType { + string toString() { + this = TSymmetricKeyType() and result = "Symmetric" + or + this = TAsymmetricKeyType() and result = "Asymmetric" + or + this = TUnknownKeyType() and result = "Unknown" + } + } + + abstract class KeyArtifactInstance extends ArtifactInstance { + abstract KeyArtifactType getKeyType(); + } + + final class KeyArtifactConsumer extends ArtifactConsumerAndInstance, KeyArtifactInstance { + DataFlowNode inputNode; + + KeyArtifactConsumer() { + exists(CipherOperationInstance op | inputNode = op.getKeyConsumer()) and + this = Input::dfn_to_element(inputNode) + } + + override KeyArtifactType getKeyType() { result instanceof TUnknownKeyType } + + final override DataFlowNode getInputNode() { result = inputNode } + } + + /** + * A cipher operation instance, such as encryption or decryption. + */ + abstract class CipherOperationInstance extends OperationInstance { /** * Gets the subtype of this cipher operation, distinguishing encryption, decryption, key wrapping, and key unwrapping. */ @@ -277,12 +365,17 @@ module CryptographyBase Input> { /** * Gets the consumer of nonces/IVs associated with this cipher operation. */ - abstract NonceArtifactConsumer getNonceConsumer(); + abstract DataFlowNode getNonceConsumer(); /** * Gets the consumer of plaintext or ciphertext input associated with this cipher operation. */ - abstract CipherInputConsumer getInputConsumer(); + abstract DataFlowNode getInputConsumer(); + + /** + * Gets the consumer of a key. + */ + abstract DataFlowNode getKeyConsumer(); /** * Gets the output artifact of this cipher operation. @@ -294,7 +387,7 @@ module CryptographyBase Input> { abstract CipherOutputArtifactInstance getOutputArtifact(); } - abstract class CipherAlgorithmInstance extends AlgorithmElement { + abstract class CipherAlgorithmInstance extends AlgorithmInstance { /** * Gets the type of this cipher, e.g., "AES" or "ChaCha20". */ @@ -303,7 +396,7 @@ module CryptographyBase Input> { /** * Gets the mode of operation of this cipher, e.g., "GCM" or "CBC". * - * IMPLEMENTATION NOTE: as a trade-off, this is not a consumer but always either an instance or unknown. + * IMPLEMENTATION NOTE: as a tradeoff, this is not a consumer but always either an instance or unknown. * A mode of operation is therefore assumed to always be part of the cipher algorithm itself. */ abstract ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm(); @@ -311,13 +404,13 @@ module CryptographyBase Input> { /** * Gets the padding scheme of this cipher, e.g., "PKCS7" or "NoPadding". * - * IMPLEMENTATION NOTE: as a trade-off, this is not a consumer but always either an instance or unknown. + * IMPLEMENTATION NOTE: as a tradeoff, this is not a consumer but always either an instance or unknown. * A padding algorithm is therefore assumed to always be defined as part of the cipher algorithm itself. */ abstract PaddingAlgorithmInstance getPaddingAlgorithm(); } - abstract class ModeOfOperationAlgorithmInstance extends AlgorithmElement { + abstract class ModeOfOperationAlgorithmInstance extends AlgorithmInstance { /** * Gets the type of this mode of operation, e.g., "ECB" or "CBC". * @@ -335,7 +428,7 @@ module CryptographyBase Input> { abstract string getRawModeAlgorithmName(); } - abstract class PaddingAlgorithmInstance extends AlgorithmElement { + abstract class PaddingAlgorithmInstance extends AlgorithmInstance { /** * Gets the isolated name as it appears in source, e.g., "PKCS7Padding" in "AES/CBC/PKCS7Padding". * @@ -353,56 +446,70 @@ module CryptographyBase Input> { abstract TPaddingType getPaddingType(); } - abstract class KeyEncapsulationOperationInstance extends LocatableElement { } + abstract class OAEPPaddingAlgorithmInstance extends PaddingAlgorithmInstance { + OAEPPaddingAlgorithmInstance() { this.getPaddingType() = OAEP() } + + /** + * Gets the hash algorithm used in this padding scheme. + */ + abstract HashAlgorithmInstance getHashAlgorithm(); + + /** + * Gets the mask generation function used in this padding scheme. + */ + abstract HashAlgorithmInstance getMaskGenerationFunction(); + } + + abstract class KeyEncapsulationOperationInstance extends OperationInstance { } - abstract class KeyEncapsulationAlgorithmInstance extends LocatableElement { } + abstract class KeyEncapsulationAlgorithmInstance extends AlgorithmInstance { } - abstract class EllipticCurveAlgorithmInstance extends LocatableElement { } + abstract class EllipticCurveAlgorithmInstance extends AlgorithmInstance { } - abstract class HashOperationInstance extends OperationElement { - // TODO: need input and outputs, but this should be universal to all Operations + abstract class HashOperationInstance extends OperationInstance { + abstract DigestArtifactInstance getDigestArtifact(); } - abstract class HashAlgorithmInstance extends AlgorithmElement { + abstract class HashAlgorithmInstance extends AlgorithmInstance { /** * Gets the type of this digest algorithm, e.g., "SHA1", "SHA2", "MD5" etc. */ abstract THashType getHashFamily(); - - // abstract int getHashSize(); } - abstract class KeyDerivationOperationInstance extends KnownElement { } + abstract class KeyDerivationOperationInstance extends OperationInstance { } - abstract class KeyDerivationAlgorithmInstance extends KnownElement { } + abstract class KeyDerivationAlgorithmInstance extends AlgorithmInstance { } - // Artifacts determined solely by the element that produces them - // Implementation guidance: these *do* need to be defined generically at the language-level - // in order for a flowsTo to be defined. At the per-modeling-instance level, extend that language-level class! - abstract class OutputArtifactElement extends ArtifactElement { - final override DataFlowNode getInputNode() { none() } - } + private signature class AlgorithmInstanceType instanceof AlgorithmInstance; - abstract class DigestArtifactInstance extends OutputArtifactElement { } + module AlgorithmInstanceOrValueConsumer { + class Union extends LocatableElement { + Union() { + this instanceof Alg + or + this instanceof AlgorithmValueConsumer and + not exists(this.(AlgorithmValueConsumer).getASource()) + } - abstract class RandomNumberGenerationInstance extends OutputArtifactElement { } // TODO: is this an OutputArtifactElement if it takes a seed? + Alg asAlg() { result = this } - // Artifacts determined solely by the consumer that consumes them are defined as consumers - // Implementation guidance: these do not need to be defined generically at the language-level - // Only the sink node needs to be defined per-modeling-instance (e.g., in JCA.qll) - abstract class NonceArtifactConsumer extends ArtifactConsumerAndInstance { } + AlgorithmValueConsumer asAVC() { result = this } + } + } - abstract class CipherInputConsumer extends ArtifactConsumerAndInstance { } + class CipherAlgorithmInstanceOrValueConsumer = + AlgorithmInstanceOrValueConsumer::Union; - // Other artifacts - abstract class KeyArtifactInstance extends ArtifactElement { } // TODO: implement and categorize + class HashAlgorithmInstanceOrValueConsumer = + AlgorithmInstanceOrValueConsumer::Union; newtype TNode = // Artifacts (data that is not an operation or algorithm, e.g., a key) TDigest(DigestArtifactInstance e) or TKey(KeyArtifactInstance e) or TNonce(NonceArtifactConsumer e) or - TCipherInput(CipherInputConsumer e) or + TCipherInput(CipherInputArtifactConsumer e) or TCipherOutput(CipherOutputArtifactInstance e) or TRandomNumberGeneration(RandomNumberGenerationInstance e) { e.flowsTo(_) } or // Operations (e.g., hashing, encryption) @@ -411,9 +518,9 @@ module CryptographyBase Input> { TCipherOperation(CipherOperationInstance e) or TKeyEncapsulationOperation(KeyEncapsulationOperationInstance e) or // Algorithms (e.g., SHA-256, AES) - TCipherAlgorithm(CipherAlgorithmInstance e) or + TCipherAlgorithm(CipherAlgorithmInstanceOrValueConsumer e) or TEllipticCurveAlgorithm(EllipticCurveAlgorithmInstance e) or - THashAlgorithm(HashAlgorithmInstance e) or + THashAlgorithm(HashAlgorithmInstanceOrValueConsumer e) or TKeyDerivationAlgorithm(KeyDerivationAlgorithmInstance e) or TKeyEncapsulationAlgorithm(KeyEncapsulationAlgorithmInstance e) or // Non-standalone Algorithms (e.g., Mode, Padding) @@ -567,10 +674,10 @@ module CryptographyBase Input> { /** * A nonce or initialization vector */ - final class NonceNode extends ArtifactNode, TNonce { + final class NonceArtifactNode extends ArtifactNode, TNonce { NonceArtifactConsumer instance; - NonceNode() { this = TNonce(instance) } + NonceArtifactNode() { this = TNonce(instance) } final override string getInternalType() { result = "Nonce" } @@ -594,7 +701,7 @@ module CryptographyBase Input> { * Input text to a cipher operation */ final class CipherInputNode extends ArtifactNode, TCipherInput { - CipherInputConsumer instance; + CipherInputArtifactConsumer instance; CipherInputNode() { this = TCipherInput(instance) } @@ -616,6 +723,41 @@ module CryptographyBase Input> { override LocatableElement asElement() { result = instance } } + /** + * A cryptographic key, such as a symmetric key or asymmetric key pair. + */ + final class KeyArtifactNode extends ArtifactNode, TKey { + KeyArtifactInstance instance; + + KeyArtifactNode() { this = TKey(instance) } + + final override string getInternalType() { result = "Key" } + + override LocatableElement asElement() { result = instance } + + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + // [ONLY_KNOWN] + key = "KeyType" and + value = instance.getKeyType().toString() and + location = this.getLocation() + } + } + + /** + * A digest produced by a hash operation. + */ + final class DigestArtifactNode extends ArtifactNode, TDigest { + DigestArtifactInstance instance; + + DigestArtifactNode() { this = TDigest(instance) } + + final override string getInternalType() { result = "Digest" } + + override LocatableElement asElement() { result = instance } + } + /** * A cryptographic operation, such as hashing or encryption. */ @@ -693,26 +835,30 @@ module CryptographyBase Input> { */ NodeBase getACipherAlgorithmOrUnknown() { result = this.getAKnownCipherAlgorithm() or - result = this.asElement().(OperationElement).getAlgorithmConsumer().getAnUnknownSourceNode() + result = + this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAnUnknownSourceNode() } /** * Gets a known algorithm associated with this operation */ CipherAlgorithmNode getAKnownCipherAlgorithm() { - result = this.asElement().(OperationElement).getAlgorithmConsumer().getAKnownSourceNode() + result = + this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAKnownSourceNode() } CipherOperationSubtype getCipherOperationSubtype() { result = instance.getCipherOperationSubtype() } - NonceNode getANonce() { - result.asElement() = this.asElement().(CipherOperationInstance).getNonceConsumer() + NonceArtifactNode getANonce() { + result.asElement() = + Input::dfn_to_element(this.asElement().(CipherOperationInstance).getNonceConsumer()) } CipherInputNode getAnInputArtifact() { - result.asElement() = this.asElement().(CipherOperationInstance).getInputConsumer() + result.asElement() = + Input::dfn_to_element(this.asElement().(CipherOperationInstance).getInputConsumer()) } CipherOutputNode getAnOutputArtifact() { @@ -858,6 +1004,32 @@ module CryptographyBase Input> { override string getRawAlgorithmName() { result = instance.getRawPaddingAlgorithmName() } } + class OAEPPaddingAlgorithmNode extends PaddingAlgorithmNode { + override OAEPPaddingAlgorithmInstance instance; + + OAEPPaddingAlgorithmNode() { this = TPaddingAlgorithm(instance) } + + HashAlgorithmNode getHashAlgorithm() { result.asElement() = instance.getHashAlgorithm() } + + HashAlgorithmNode getMaskGenerationFunction() { + result.asElement() = instance.getMaskGenerationFunction() + } + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + // [KNOWN_OR_UNKNOWN] + edgeName = "MD" and + if exists(this.getHashAlgorithm()) then result = this.getHashAlgorithm() else result = this + or + // [KNOWN_OR_UNKNOWN] + edgeName = "MGF" and + if exists(this.getMaskGenerationFunction()) + then result = this.getMaskGenerationFunction() + else result = this + } + } + /** * A helper type for distinguishing between block and stream ciphers. */ @@ -904,7 +1076,7 @@ module CryptographyBase Input> { OtherCipherType() final class CipherAlgorithmNode extends AlgorithmNode, TCipherAlgorithm { - CipherAlgorithmInstance instance; + CipherAlgorithmInstanceOrValueConsumer instance; CipherAlgorithmNode() { this = TCipherAlgorithm(instance) } @@ -920,7 +1092,7 @@ module CryptographyBase Input> { this.cipherFamilyToNameAndStructure(this.getCipherFamily(), result, _) } - final override string getRawAlgorithmName() { result = instance.getRawAlgorithmName() } + final override string getRawAlgorithmName() { result = instance.asAlg().getRawAlgorithmName() } /** * Gets the key size of this cipher, e.g., "128" or "256". @@ -930,20 +1102,20 @@ module CryptographyBase Input> { /** * Gets the type of this cipher, e.g., "AES" or "ChaCha20". */ - TCipherType getCipherFamily() { result = instance.getCipherFamily() } + TCipherType getCipherFamily() { result = instance.asAlg().getCipherFamily() } /** * Gets the mode of operation of this cipher, e.g., "GCM" or "CBC". */ ModeOfOperationAlgorithmNode getModeOfOperation() { - result.asElement() = instance.getModeOfOperationAlgorithm() + result.asElement() = instance.asAlg().getModeOfOperationAlgorithm() } /** * Gets the padding scheme of this cipher, e.g., "PKCS7" or "NoPadding". */ PaddingAlgorithmNode getPaddingAlgorithm() { - result.asElement() = instance.getPaddingAlgorithm() + result.asElement() = instance.asAlg().getPaddingAlgorithm() } bindingset[type] @@ -1038,7 +1210,7 @@ module CryptographyBase Input> { * hash value as the output using a specified hashing algorithm. */ class HashOperationNode extends OperationNode, THashOperation { - HashAlgorithmInstance instance; + HashOperationInstance instance; HashOperationNode() { this = THashOperation(instance) } @@ -1049,16 +1221,39 @@ module CryptographyBase Input> { /** * Gets the algorithm or unknown source nodes consumed as an algorithm associated with this operation. */ - NodeBase getACipherAlgorithmOrUnknown() { - result = this.getAKnownCipherAlgorithm() or - result = this.asElement().(OperationElement).getAlgorithmConsumer().getAnUnknownSourceNode() + NodeBase getAHashAlgorithmOrUnknown() { + result = this.getAKnownHashAlgorithm() or + result = + this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAnUnknownSourceNode() } /** * Gets a known algorithm associated with this operation */ - HashAlgorithmNode getAKnownCipherAlgorithm() { - result = this.asElement().(OperationElement).getAlgorithmConsumer().getAKnownSourceNode() + HashAlgorithmNode getAKnownHashAlgorithm() { + result = + this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAKnownSourceNode() + } + + /** + * Gets the output digest node + */ + DigestArtifactNode getDigest() { + result.asElement() = this.asElement().(HashOperationInstance).getDigestArtifact() + } + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + // [KNOWN_OR_UNKNOWN] + edgeName = "Algorithm" and + if exists(this.getAHashAlgorithmOrUnknown()) + then result = this.getAHashAlgorithmOrUnknown() + else result = this + or + // [KNOWN_OR_UNKNOWN] + edgeName = "Digest" and + if exists(this.getDigest()) then result = this.getDigest() else result = this } } @@ -1083,11 +1278,17 @@ module CryptographyBase Input> { /** * A hashing algorithm that transforms variable-length input into a fixed-size hash value. */ - abstract class HashAlgorithmNode extends AlgorithmNode, THashAlgorithm { - HashAlgorithmInstance instance; + final class HashAlgorithmNode extends AlgorithmNode, THashAlgorithm { + HashAlgorithmInstanceOrValueConsumer instance; + HashAlgorithmNode() { this = THashAlgorithm(instance) } + override string getInternalType() { result = "HashAlgorithm" } + override LocatableElement asElement() { result = instance } + + override string getRawAlgorithmName() { result = instance.asAlg().getRawAlgorithmName() } + final predicate hashTypeToNameMapping(THashType type, string name) { type instanceof BLAKE2B and name = "BLAKE2B" or From 63aaebbea6bd4a5249393265d980c27a5f1724c7 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Wed, 19 Mar 2025 18:30:06 -0400 Subject: [PATCH 070/336] . --- cpp/ql/lib/experimental/Quantum/Language.qll | 6 + .../OpenSSL/EVPCipherAlgorithmSource.qll | 181 ---- .../Quantum/OpenSSL/EVPCipherInitializer.qll | 153 --- .../Quantum/OpenSSL/EVPCipherOperation.qll | 92 -- .../experimental/Quantum/OpenSSL/OpenSSL.qll | 216 ++-- .../OpenSSL/OpenSSLAlgorithmGetter.qll | 976 ++++++++---------- .../codeql/cryptography/Model.qll | 5 + 7 files changed, 531 insertions(+), 1098 deletions(-) delete mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll delete mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherInitializer.qll delete mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index dbcb2004b83b..2dc17f5e267a 100644 --- a/cpp/ql/lib/experimental/Quantum/Language.qll +++ b/cpp/ql/lib/experimental/Quantum/Language.qll @@ -9,6 +9,12 @@ module CryptoInput implements InputSig { class LocatableElement = Lang::Locatable; class UnknownLocation = Lang::UnknownDefaultLocation; + + LocatableElement dfn_to_element(DataFlow::Node node) { + result = node.asExpr() or + result = node.asParameter() or + result = node.asVariable() + } } module Crypto = CryptographyBase; diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll deleted file mode 100644 index 65231e32cd03..000000000000 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll +++ /dev/null @@ -1,181 +0,0 @@ -import cpp -import experimental.Quantum.Language -import EVPCipherConsumers -import OpenSSLAlgorithmGetter - -/** - * Given a `KnownOpenSSLAlgorithmConstant`, converts this to a cipher family type. - * Does not bind if there is know mapping (no mapping to 'unknown' or 'other'). - */ -predicate knownOpenSSLConstantToCipherFamilyType( - KnownOpenSSLAlgorithmConstant e, Crypto::TCipherType type -) { - exists(string name | e.getAlgType().toLowerCase().matches("%encryption") | - name = e.getNormalizedName() and - ( - name.matches("AES%") and type instanceof Crypto::AES - or - name.matches("ARIA") and type instanceof Crypto::ARIA - or - name.matches("BLOWFISH") and type instanceof Crypto::BLOWFISH - or - name.matches("BF") and type instanceof Crypto::BLOWFISH - or - name.matches("CAMELLIA%") and type instanceof Crypto::CAMELLIA - or - name.matches("CHACHA20") and type instanceof Crypto::CHACHA20 - or - name.matches("CAST5") and type instanceof Crypto::CAST5 - or - name.matches("2DES") and type instanceof Crypto::DoubleDES - or - name.matches(["3DES", "TRIPLEDES"]) and type instanceof Crypto::TripleDES - or - name.matches("DES") and type instanceof Crypto::DES - or - name.matches("DESX") and type instanceof Crypto::DESX - or - name.matches("GOST%") and type instanceof Crypto::GOST - or - name.matches("IDEA") and type instanceof Crypto::IDEA - or - name.matches("KUZNYECHIK") and type instanceof Crypto::KUZNYECHIK - or - name.matches("MAGMA") and type instanceof Crypto::MAGMA - or - name.matches("RC2") and type instanceof Crypto::RC2 - or - name.matches("RC4") and type instanceof Crypto::RC4 - or - name.matches("RC5") and type instanceof Crypto::RC5 - or - name.matches("RSA") and type instanceof Crypto::RSA - or - name.matches("SEED") and type instanceof Crypto::SEED - or - name.matches("SM4") and type instanceof Crypto::SM4 - ) - ) -} - -class KnownOpenSSLCipherConstantAlgorithmInstance extends Crypto::CipherAlgorithmInstance instanceof KnownOpenSSLAlgorithmConstant -{ - OpenSSLAlgorithmGetterCall getterCall; - - KnownOpenSSLCipherConstantAlgorithmInstance() { - // Not just any known value, but specifically a known cipher operation - this.(KnownOpenSSLAlgorithmConstant).getAlgType().toLowerCase().matches("%encryption") and - ( - // Two possibilities: - // 1) The source is a literal and flows to a getter, then we know we have an instance - // 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that - // Possibility 1: - this instanceof Literal and - exists(DataFlow::Node src, DataFlow::Node sink | - // Sink is an argument to a CipherGetterCall - sink = getterCall.(OpenSSLAlgorithmGetterCall).getValueArgNode() and - // Source is `this` - src.asExpr() = this and - // This traces to a getter - KnownOpenSSLAlgorithmToAlgorithmGetterFlow::flow(src, sink) - ) - or - // Possibility 2: - this instanceof DirectGetterCall and getterCall = this - ) - } - - Crypto::AlgorithmConsumer getConsumer() { - AlgGetterToAlgConsumerFlow::flow(getterCall.getResultNode(), DataFlow::exprNode(result)) - } - - override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { - // if there is a block mode associated with the same element, then that's the block mode - // note, if none are associated, we may need to parse if the cipher is a block cipher - // to determine if this is an unknown vs not relevant. - result = this - } - - override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { none() } - - override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } - - override Crypto::TCipherType getCipherFamily() { - knownOpenSSLConstantToCipherFamilyType(this, result) - or - not knownOpenSSLConstantToCipherFamilyType(this, _) and result = Crypto::OtherCipherType() - } -} - -/** - * Given a `KnownOpenSSLAlgorithmConstant`, converts this to a cipher family type. - * Does not bind if there is know mapping (no mapping to 'unknown' or 'other'). - */ -predicate knownOpenSSLConstantToBlockModeFamilyType( - KnownOpenSSLAlgorithmConstant e, Crypto::TBlockCipherModeOperationType type -) { - exists(string name | e.getAlgType().toLowerCase().matches("block_mode") | - name = e.getNormalizedName() and - ( - name.matches("CBC") and type instanceof Crypto::CBC - or - name.matches("CFB%") and type instanceof Crypto::CFB - or - name.matches("CTR") and type instanceof Crypto::CTR - or - name.matches("GCM") and type instanceof Crypto::GCM - or - name.matches("OFB") and type instanceof Crypto::OFB - or - name.matches("XTS") and type instanceof Crypto::XTS - or - name.matches("CCM") and type instanceof Crypto::CCM - or - name.matches("GCM") and type instanceof Crypto::GCM - or - name.matches("CCM") and type instanceof Crypto::CCM - or - name.matches("ECB") and type instanceof Crypto::ECB - ) - ) -} - -class KnownOpenSSLBlockModeConstantAlgorithmInstance extends Crypto::ModeOfOperationAlgorithmInstance instanceof KnownOpenSSLAlgorithmConstant -{ - OpenSSLAlgorithmGetterCall getterCall; - - KnownOpenSSLBlockModeConstantAlgorithmInstance() { - // Not just any known value, but specifically a known cipher operation - this.(KnownOpenSSLAlgorithmConstant).getAlgType().toLowerCase().matches("block_mode") and - ( - // Two possibilities: - // 1) The source is a literal and flows to a getter, then we know we have an instance - // 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that - // Possibility 1: - this instanceof Literal and - exists(DataFlow::Node src, DataFlow::Node sink | - // Sink is an argument to a CipherGetterCall - sink = getterCall.(OpenSSLAlgorithmGetterCall).getValueArgNode() and - // Source is `this` - src.asExpr() = this and - // This traces to a getter - KnownOpenSSLAlgorithmToAlgorithmGetterFlow::flow(src, sink) - ) - or - // Possibility 2: - this instanceof DirectGetterCall and getterCall = this - ) - } - - override Crypto::TBlockCipherModeOperationType getModeType() { - knownOpenSSLConstantToBlockModeFamilyType(this, result) - or - not knownOpenSSLConstantToBlockModeFamilyType(this, _) and result = Crypto::OtherMode() - } - - // NOTE: I'm not going to attempt to parse out the mode specific part, so returning - // the same as the raw name for now. - override string getRawModeAlgorithmName() { result = this.(Literal).getValue().toString() } - - override string getRawAlgorithmName() { result = this.getRawModeAlgorithmName() } -} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherInitializer.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherInitializer.qll deleted file mode 100644 index 12cbe4da650a..000000000000 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherInitializer.qll +++ /dev/null @@ -1,153 +0,0 @@ -import experimental.Quantum.Language -import CtxFlow as CTXFlow - -module EncValToInitEncArgConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source.asExpr().getValue().toInt() in [0, 1] } - - predicate isSink(DataFlow::Node sink) { - exists(EVP_Cipher_Inititalizer initCall | sink.asExpr() = initCall.getOperataionSubtypeArg()) - } -} - -module EncValToInitEncArgFlow = DataFlow::Global; - -int getEncConfigValue(Expr e) { - exists(EVP_Cipher_Inititalizer initCall | e = initCall.getOperataionSubtypeArg()) and - exists(DataFlow::Node a, DataFlow::Node b | - EncValToInitEncArgFlow::flow(a, b) and b.asExpr() = e and result = a.asExpr().getValue().toInt() - ) -} - -bindingset[i] -Crypto::CipherOperationSubtype intToCipherOperationSubtype(int i) { - if i = 0 - then result instanceof Crypto::EncryptionSubtype - else - if i = 1 - then result instanceof Crypto::DecryptionSubtype - else result instanceof Crypto::UnknownCipherOperationSubtype -} - -// TODO: need to add key consumer -abstract class EVP_Cipher_Inititalizer extends Call { - Expr getContextArg() { result = this.(Call).getArgument(0) } - - Expr getAlgorithmArg() { result = this.(Call).getArgument(1) } - - abstract Expr getKeyArg(); - - abstract Expr getIVArg(); - -// abstract Crypto::CipherOperationSubtype getCipherOperationSubtype(); - - abstract Expr getOperataionSubtypeArg(); - -Crypto::CipherOperationSubtype getCipherOperationSubtype() { - if this.(Call).getTarget().getName().toLowerCase().matches("%encrypt%") - then result instanceof Crypto::EncryptionSubtype - else - if this.(Call).getTarget().getName().toLowerCase().matches("%decrypt%") - then result instanceof Crypto::DecryptionSubtype - else - if exists(getEncConfigValue(this.getOperataionSubtypeArg())) - then result = intToCipherOperationSubtype(getEncConfigValue(this.getOperataionSubtypeArg())) - else result instanceof Crypto::UnknownCipherOperationSubtype - } -} - -abstract class EVP_EX_Initializer extends EVP_Cipher_Inititalizer { - override Expr getKeyArg() { result = this.(Call).getArgument(3) } - - override Expr getIVArg() { result = this.(Call).getArgument(4) } -} - -abstract class EVP_EX2_Initializer extends EVP_Cipher_Inititalizer { - override Expr getKeyArg() { result = this.(Call).getArgument(2) } - - override Expr getIVArg() { result = this.(Call).getArgument(3) } -} - -class EVP_Cipher_EX_Init_Call extends EVP_EX_Initializer { - EVP_Cipher_EX_Init_Call() { - this.(Call).getTarget().getName() in [ - "EVP_EncryptInit_ex", "EVP_DecryptInit_ex", "EVP_CipherInit_ex" - ] - } - - override Expr getOperataionSubtypeArg() { - this.(Call).getTarget().getName().toLowerCase().matches("%cipherinit%") and - result = this.(Call).getArgument(5) - } -} - -// abstract class EVP_CipherInit extends EVP_Cipher_Inititalizer{ -// abstract Expr getOperataionSubtypeArg(); -// } -// class EVP_CipherInit_ex_Call extends EVP_EX_Initializer, EVP_CipherInit { -// EVP_CipherInit_ex_Call() { this.(Call).getTarget().getName() = "EVP_CipherInit_ex" } -// override Crypto::CipherOperationSubtype getCipherOperationSubtype() { -// result instanceof Crypto::EncryptionSubtype -// } -// override Expr getOperataionSubtypeArg(){ -// result = this.(Call).getArgument(5) -// } -// } -// class EVP_CipherInit_ex2_Call extends EVP_EX_Initializer, EVP_CipherInit { -// EVP_CipherInit_ex2_Call() { this.(Call).getTarget().getName() = "EVP_CipherInit_ex2" } -// override Crypto::CipherOperationSubtype getCipherOperationSubtype() { -// result instanceof Crypto::EncryptionSubtype -// } -// override Expr getOperataionSubtypeArg(){ -// result = this.(Call).getArgument(4) -// } -// } -class EVP_Cipher_EX2_or_Simple_Init_Call extends EVP_EX2_Initializer { - EVP_Cipher_EX2_or_Simple_Init_Call() { - this.(Call).getTarget().getName() in [ - "EVP_EncryptInit_ex2", "EVP_DecryptInit_ex2", "EVP_CipherInit_ex2", - "EVP_EncryptInit", "EVP_DecryptInit", "EVP_CipherInit" - ] - } - - - override Expr getOperataionSubtypeArg() { - this.(Call).getTarget().getName().toLowerCase().matches("%cipherinit%") and - result = this.(Call).getArgument(4) - } -} - -class EVP_CipherInit_SKEY_Call extends EVP_EX2_Initializer { - EVP_CipherInit_SKEY_Call() { - this.(Call).getTarget().getName() in [ - "EVP_CipherInit_SKEY" - ] - } - - override Expr getOperataionSubtypeArg() { - result = this.(Call).getArgument(5) - } -} - - -// class EVP_CipherInit extends EVP_Cipher_Inititalizer { -// EVP_CipherInit() { this.(Call).getTarget().getName() = "EVP_CipherInit" } -// override Expr getKeyArg() { result = this.(Call).getArgument(2) } -// override Expr getIVArg() { result = this.(Call).getArgument(3) } -// override Crypto::CipherOperationSubtype getCipherOperationSubtype() { -// result instanceof Crypto::EncryptionSubtype -// } -// } -class EVPCipherInitializerAlgorithmArgument extends Expr { - EVPCipherInitializerAlgorithmArgument() { - exists(EVP_Cipher_Inititalizer initCall | this = initCall.getAlgorithmArg()) - } -} -class EVPCipherInitializerKeyArgument extends Expr { - EVPCipherInitializerKeyArgument() { - exists(EVP_Cipher_Inititalizer initCall | this = initCall.getKeyArg()) - } -} -class EVPCipherInitializerIVArgument extends Expr { - EVPCipherInitializerIVArgument() { exists(EVP_Cipher_Inititalizer initCall | this = initCall.getIVArg()) } -} - diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll deleted file mode 100644 index f426eb3f92dd..000000000000 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherOperation.qll +++ /dev/null @@ -1,92 +0,0 @@ -import experimental.Quantum.Language -import CtxFlow as CTXFlow -import EVPCipherInitializer -import EVPCipherConsumers - -//https://docs.openssl.org/master/man3/EVP_EncryptInit/#synopsis -abstract class EVP_Cipher_Operation extends Crypto::CipherOperationInstance instanceof Call { - Expr getContextArg() { result = this.(Call).getArgument(0) } - - abstract Expr getInputArg(); - - Expr getOutputArg() { result = this.(Call).getArgument(1) } - - override Crypto::CipherOperationSubtype getCipherOperationSubtype() { - result instanceof Crypto::EncryptionSubtype and - this.(Call).getTarget().getName().toLowerCase().matches("%encrypt%") - or - result instanceof Crypto::DecryptionSubtype and - this.(Call).getTarget().getName().toLowerCase().matches("%decrypt%") - or - result = this.getInitCall().getCipherOperationSubtype() and - this.(Call).getTarget().getName().toLowerCase().matches("%cipher%") - } - - EVP_Cipher_Inititalizer getInitCall() { - CTXFlow::ctxFlowsTo(result.getContextArg(), this.getContextArg()) - } - - override Crypto::NonceArtifactConsumer getNonceConsumer() { - this.getInitCall().getIVArg() = result - } - - override Crypto::CipherInputConsumer getInputConsumer() { this.getInputArg() = result } - - override Crypto::CipherOutputArtifactInstance getOutputArtifact() { this.getOutputArg() = result } - - override Crypto::AlgorithmConsumer getAlgorithmConsumer() { - this.getInitCall().getAlgorithmArg() = result - } -} - -abstract class EVP_Update_Call extends EVP_Cipher_Operation { } - -abstract class EVP_Final_Call extends EVP_Cipher_Operation { - override Expr getInputArg() { none() } -} - -class EVP_Cipher_Call extends EVP_Cipher_Operation { - EVP_Cipher_Call() { this.(Call).getTarget().getName() = "EVP_Cipher" } - - override Expr getInputArg() { result = this.(Call).getArgument(2) } -} - -class EVP_Encrypt_Decrypt_or_Cipher_Update_Call extends EVP_Update_Call { - EVP_Encrypt_Decrypt_or_Cipher_Update_Call() { - this.(Call).getTarget().getName() in [ - "EVP_EncryptUpdate", "EVP_DecryptUpdate", "EVP_CipherUpdate" - ] - } - - override Expr getInputArg() { result = this.(Call).getArgument(3) } -} - -class EVP_Encrypt_Decrypt_or_Cipher_Final_Call extends EVP_Final_Call { - EVP_Encrypt_Decrypt_or_Cipher_Final_Call() { - this.(Call).getTarget().getName() in [ - "EVP_EncryptFinal_ex", "EVP_DecryptFinal_ex", "EVP_CipherFinal_ex", "EVP_EncryptFinal", - "EVP_DecryptFinal", "EVP_CipherFinal" - ] - } -} - -class EVP_PKEY_Operation extends EVP_Cipher_Operation { - EVP_PKEY_Operation() { - this.(Call).getTarget().getName() in ["EVP_PKEY_decrypt", "EVP_PKEY_encrypt"] - } - - override Expr getInputArg() { result = this.(Call).getArgument(3) } - // TODO: how PKEY is initialized is different that symmetric cipher - // Consider making an entirely new class for this and specializing - // the get init call -} - -class EVPCipherOutput extends CipherOutputArtifact { - EVPCipherOutput() { exists(EVP_Cipher_Operation op | op.getOutputArg() = this) } - - override DataFlow::Node getOutputNode() { result.asExpr() = this } -} - -class EVPCipherInputArgument extends Expr { - EVPCipherInputArgument() { exists(EVP_Cipher_Operation op | op.getInputArg() = this) } -} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll index 16b9e6485c96..1f9fb9a54bae 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll @@ -3,127 +3,93 @@ import semmle.code.cpp.dataflow.new.DataFlow module OpenSSLModel { import experimental.Quantum.Language - import experimental.Quantum.OpenSSL.EVPCipherOperation - import experimental.Quantum.OpenSSL.EVPHashOperation - import experimental.Quantum.OpenSSL.EVPCipherAlgorithmSource - import experimental.Quantum.OpenSSL.EVPHashAlgorithmSource - import experimental.Quantum.OpenSSL.Random - // Imports the additional algorithm flow step for OpenSSL - import experimental.Quantum.OpenSSL.OpenSSLAlgorithmGetter - - -// // TODO: trace CTX from init variants to the context arg of EVP update calls -// //https://docs.openssl.org/master/man3/EVP_EncryptInit/#synopsis -// abstract class EVP_Cipher_Init_Call extends Call { -// Expr getContextArg() { result = this.getArgument(0) } -// abstract Expr getKeyArg(); - -// abstract Expr getIVArg(); - -// abstract Crypto::CipherOperationSubtype getCipherOperationSubtype(); -// } - -// abstract class EVP_Cipher_EX_Init_Call extends EVP_Cipher_Init_Call { -// override Expr getKeyArg() { result = this.getArgument(3) } - -// override Expr getIVArg() { result = this.getArgument(4) } -// } - -// abstract class EVP_Cipher_EX2_Init_Call extends EVP_Cipher_Init_Call { -// override Expr getKeyArg() { result = this.getArgument(2) } - -// override Expr getIVArg() { result = this.getArgument(3) } -// } - -// abstract class EVP_Cipher_Operation_Call extends Crypto::CipherOperationInstance instanceof Call { -// Expr getContextArg() { result = this.(Call).getArgument(0) } -// abstract Expr getInputArg(); -// Expr getOutputArg() { result = this.(Call).getArgument(1) } -// abstract Expr getInitCall(); -// } - -// abstract class EVP_Update_Call extends EVP_Cipher_Operation_Call { -// override Expr getInputArg() { result = this.(Call).getArgument(3) } - -// } - -// abstract class EVP_Final_Call extends EVP_Cipher_Operation_Call{ -// override Expr getInputArg() { none() } - -// } - -// class EVP_Cipher_Call extends EVP_Cipher_Operation_Call{ -// // TODO/QUESTION: what is the better way to do this? -// EVP_Cipher_Call() { this.(Call).getTarget().getName() = "EVP_Cipher" } - -// override Expr getInputArg() { result = this.(Call).getArgument(2) } - -// override Expr getOutputArg() { result = this.(Call).getArgument(1) } - -// override Crypto::CipherOperationSubtype getCipherOperationSubtype(){ -// result instanceof Crypto::EncryptionSubtype -// } - -// override Expr getInitCall(){ -// //TODO: -// none() -// } - -// override Crypto::NonceArtifactConsumer getNonceConsumer(){ -// none() -// } - -// override Crypto::CipherInputConsumer getInputConsumer(){ -// none() -// } - -// override Crypto::CipherOutputArtifactInstance getOutputArtifact(){ -// none() -// } - -// override Crypto::AlgorithmConsumer getAlgorithmConsumer(){ -// none() -// } -// } - - + import experimental.Quantum.OpenSSL.AlgorithmInstances.Instances + import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.AlgorithmValueConsumers + import experimental.Quantum.OpenSSL.Operations.Operations + // import experimental.Quantum.OpenSSL.EVPCipherOperation + // import experimental.Quantum.OpenSSL.EVPHashOperation + // import experimental.Quantum.OpenSSL.EVPCipherAlgorithmSource + // import experimental.Quantum.OpenSSL.EVPHashAlgorithmSource + // import experimental.Quantum.OpenSSL.Random + // // Imports the additional algorithm flow step for OpenSSL + // import experimental.Quantum.OpenSSL.OpenSSLAlgorithmGetter + // // TODO: trace CTX from init variants to the context arg of EVP update calls + // //https://docs.openssl.org/master/man3/EVP_EncryptInit/#synopsis + // abstract class EVP_Cipher_Init_Call extends Call { + // Expr getContextArg() { result = this.getArgument(0) } + // abstract Expr getKeyArg(); + // abstract Expr getIVArg(); + // abstract Crypto::CipherOperationSubtype getCipherOperationSubtype(); + // } + // abstract class EVP_Cipher_EX_Init_Call extends EVP_Cipher_Init_Call { + // override Expr getKeyArg() { result = this.getArgument(3) } + // override Expr getIVArg() { result = this.getArgument(4) } + // } + // abstract class EVP_Cipher_EX2_Init_Call extends EVP_Cipher_Init_Call { + // override Expr getKeyArg() { result = this.getArgument(2) } + // override Expr getIVArg() { result = this.getArgument(3) } + // } + // abstract class EVP_Cipher_Operation_Call extends Crypto::CipherOperationInstance instanceof Call { + // Expr getContextArg() { result = this.(Call).getArgument(0) } + // abstract Expr getInputArg(); + // Expr getOutputArg() { result = this.(Call).getArgument(1) } + // abstract Expr getInitCall(); + // } + // abstract class EVP_Update_Call extends EVP_Cipher_Operation_Call { + // override Expr getInputArg() { result = this.(Call).getArgument(3) } + // } + // abstract class EVP_Final_Call extends EVP_Cipher_Operation_Call{ + // override Expr getInputArg() { none() } + // } + // class EVP_Cipher_Call extends EVP_Cipher_Operation_Call{ + // // TODO/QUESTION: what is the better way to do this? + // EVP_Cipher_Call() { this.(Call).getTarget().getName() = "EVP_Cipher" } + // override Expr getInputArg() { result = this.(Call).getArgument(2) } + // override Expr getOutputArg() { result = this.(Call).getArgument(1) } + // override Crypto::CipherOperationSubtype getCipherOperationSubtype(){ + // result instanceof Crypto::EncryptionSubtype + // } + // override Expr getInitCall(){ + // //TODO: + // none() + // } + // override Crypto::NonceArtifactConsumer getNonceConsumer(){ + // none() + // } + // override Crypto::CipherInputConsumer getInputConsumer(){ + // none() + // } + // override Crypto::CipherOutputArtifactInstance getOutputArtifact(){ + // none() + // } + // override Crypto::AlgorithmConsumer getAlgorithmConsumer(){ + // none() + // } + // } //TODO: what about EVP_CIpher - - // class EVP_EncryptUpdateCall extends Crypto::CipherOperationInstance instanceof Call { // // NICK QUESTION: is there a better way to tie this to openssl? // EVP_EncryptUpdateCall() { this.getTarget().getName() = "EVP_EncryptUpdate" } - // Expr getContextArg() { result = super.getArgument(0) } - // Expr getInputArg() { result = super.getArgument(3) } - // Expr getOutputArg() { result = super.getArgument(1) } - // override Crypto::CipherOperationSubtype getCipherOperationSubtype(){ // result instanceof Crypto::EncryptionSubtype // } - // override Crypto::NonceArtifactConsumer getNonceConsumer(){ // none() // } - // override Crypto::CipherInputConsumer getInputConsumer(){ // none() // } - // override Crypto::CipherOutputArtifactInstance getOutputArtifact(){ // none() // } - // override Crypto::AlgorithmConsumer getAlgorithmConsumer(){ // none() // } - // } - //EVP_EncryptUpdate - // /** // * Hash function references in OpenSSL. // */ @@ -146,34 +112,26 @@ module OpenSSLModel { // or // name = "whirlpool" and algo instanceof Crypto::WHIRLPOOL // } - // predicate hash_ref_type_mapping(FunctionCallOrMacroAccess ref, string name, Crypto::THashType algo) { // name = ref.getTargetName().regexpCapture("(?:SN_|LN_|EVP_)([a-z0-9]+)", 1) and // hash_ref_type_mapping_known(name, algo) // } - // class FunctionCallOrMacroAccess extends Element { // FunctionCallOrMacroAccess() { this instanceof FunctionCall or this instanceof MacroAccess } - // string getTargetName() { // result = this.(FunctionCall).getTarget().getName() // or // result = this.(MacroAccess).getMacroName() // } // } - // class HashAlgorithmCallOrMacro extends Crypto::HashAlgorithmInstance instanceof FunctionCallOrMacroAccess // { // HashAlgorithmCallOrMacro() { hash_ref_type_mapping(this, _, _) } - // string getTargetName() { result = this.(FunctionCallOrMacroAccess).getTargetName() } // } - // class HashAlgorithm extends Crypto::HashAlgorithm { // HashAlgorithmCallOrMacro instance; - // HashAlgorithm() { this = Crypto::THashAlgorithm(instance) } - // override string getSHA2OrSHA3DigestSize(Location location) { // ( // this.getHashType() instanceof Crypto::SHA2 or @@ -185,16 +143,11 @@ module OpenSSLModel { // location = instance.getLocation() // ) // } - // override string getRawAlgorithmName() { result = instance.getTargetName() } - // override Crypto::THashType getHashType() { hash_ref_type_mapping(instance, _, result) } - // Element getInstance() { result = instance } - // override Location getLocation() { result = instance.getLocation() } // } - // /** // * Data-flow configuration for key derivation algorithm flow to EVP_KDF_derive. // */ @@ -202,7 +155,6 @@ module OpenSSLModel { // predicate isSource(DataFlow::Node source) { // source.asExpr() = any(KeyDerivationAlgorithm a).getInstance() // } - // predicate isSink(DataFlow::Node sink) { // exists(EVP_KDF_derive kdo | // sink.asExpr() = kdo.getCall().getAlgorithmArg() @@ -210,155 +162,113 @@ module OpenSSLModel { // sink.asExpr() = kdo.getCall().getContextArg() // via `EVP_KDF_CTX_set_params` // ) // } - // predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { // none() // TODO // } // } - // module AlgorithmToEVPKeyDeriveFlow = DataFlow::Global; - // predicate algorithm_to_EVP_KDF_derive(KeyDerivationAlgorithm algo, EVP_KDF_derive derive) { // none() // } - // /** // * Key derivation operation (e.g., `EVP_KDF_derive`) // */ // class EVP_KDF_derive_FunctionCall extends Crypto::KeyDerivationOperationInstance instanceof FunctionCall // { // EVP_KDF_derive_FunctionCall() { this.getTarget().getName() = "EVP_KDF_derive" } - // Expr getAlgorithmArg() { result = super.getArgument(3) } - // Expr getContextArg() { result = super.getArgument(0) } // } - // class EVP_KDF_derive extends Crypto::KeyDerivationOperation { // EVP_KDF_derive_FunctionCall instance; - // EVP_KDF_derive() { this = Crypto::TKeyDerivationOperation(instance) } - // override Crypto::Algorithm getAlgorithm() { algorithm_to_EVP_KDF_derive(result, this) } - // EVP_KDF_derive_FunctionCall getCall() { result = instance } // } - // /** // * Key derivation algorithm nodes // */ // abstract class KeyDerivationAlgorithm extends Crypto::KeyDerivationAlgorithm { // abstract Expr getInstance(); // } - // /** // * `EVP_KDF_fetch` returns a key derivation algorithm. // */ // class EVP_KDF_fetch_Call extends FunctionCall { // EVP_KDF_fetch_Call() { this.getTarget().getName() = "EVP_KDF_fetch" } - // Expr getAlgorithmArg() { result = this.getArgument(1) } // } - // class EVP_KDF_fetch_AlgorithmArg extends Crypto::KeyDerivationAlgorithmInstance instanceof Expr { // EVP_KDF_fetch_AlgorithmArg() { exists(EVP_KDF_fetch_Call call | this = call.getAlgorithmArg()) } // } - // predicate kdf_names(string algo) { algo = ["HKDF", "PKCS12KDF", "PBKDF2"] } - // class KDFAlgorithmStringLiteral extends StringLiteral { // KDFAlgorithmStringLiteral() { kdf_names(this.getValue().toUpperCase()) } // } - // private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { // predicate isSource(DataFlow::Node src) { src.asExpr() instanceof KDFAlgorithmStringLiteral } - // predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof EVP_KDF_fetch_AlgorithmArg } // } - // module AlgorithmStringToFetchFlow = DataFlow::Global; - // predicate algorithmStringToKDFFetchArgFlow( // string name, KDFAlgorithmStringLiteral origin, EVP_KDF_fetch_AlgorithmArg arg // ) { // origin.getValue().toUpperCase() = name and // AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), DataFlow::exprNode(arg)) // } - // /** // * HKDF key derivation algorithm. // */ // class HKDF extends KeyDerivationAlgorithm, Crypto::HKDF { // KDFAlgorithmStringLiteral origin; // EVP_KDF_fetch_AlgorithmArg instance; - // HKDF() { // this = Crypto::TKeyDerivationAlgorithm(instance) and // algorithmStringToKDFFetchArgFlow("HKDF", origin, instance) // } - // override string getRawAlgorithmName() { result = origin.getValue() } - // override Crypto::HashAlgorithm getHashAlgorithm() { none() } - // override Crypto::LocatableElement getOrigin(string name) { // result = origin and name = origin.toString() // } - // override Expr getInstance() { result = origin } // } - // /** // * PBKDF2 key derivation algorithm. // */ // class PBKDF2 extends KeyDerivationAlgorithm, Crypto::PBKDF2 { // KDFAlgorithmStringLiteral origin; // EVP_KDF_fetch_AlgorithmArg instance; - // PBKDF2() { // this = Crypto::TKeyDerivationAlgorithm(instance) and // algorithmStringToKDFFetchArgFlow("PBKDF2", origin, instance) // } - // override string getRawAlgorithmName() { result = origin.getValue() } - // override string getIterationCount(Location location) { none() } // TODO - // override string getKeyLength(Location location) { none() } // TODO - // override Crypto::HashAlgorithm getHashAlgorithm() { none() } // TODO - // override Crypto::LocatableElement getOrigin(string name) { // result = origin and name = origin.toString() // } - // override Expr getInstance() { result = instance } // } - // /** // * PKCS12KDF key derivation algorithm. // */ // class PKCS12KDF extends KeyDerivationAlgorithm, Crypto::PKCS12KDF { // KDFAlgorithmStringLiteral origin; // EVP_KDF_fetch_AlgorithmArg instance; - // PKCS12KDF() { // this = Crypto::TKeyDerivationAlgorithm(instance) and // algorithmStringToKDFFetchArgFlow("PKCS12KDF", origin, instance) // } - // override string getRawAlgorithmName() { result = origin.getValue() } - // override string getIterationCount(Location location) { none() } // TODO - // override string getIDByte(Location location) { none() } // TODO - // override Crypto::HashAlgorithm getHashAlgorithm() { none() } // TODO - // override Crypto::LocatableElement getOrigin(string name) { // result = origin and name = origin.toString() // } - // override Expr getInstance() { result = instance } // } } diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll index 3e061eeff88f..b436f3b412a8 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll @@ -1,557 +1,495 @@ -import cpp -import semmle.code.cpp.dataflow.new.DataFlow -import LibraryDetector -import OpenSSLKnownAlgorithmConstants -import experimental.Quantum.Language -class OpenSSLAlgorithmAdditionalFlowStep extends AdditionalFlowInputStep { - OpenSSLAlgorithmAdditionalFlowStep() { exists(AlgorithmPassthroughCall c | c.getInNode() = this) } - - override DataFlow::Node getOutput() { - exists(AlgorithmPassthroughCall c | c.getInNode() = this and c.getOutNode() = result) - } -} - -module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { - exists(OpenSSLAlgorithmGetterCall c | c.getResultNode() = source) - } - - predicate isSink(DataFlow::Node sink) { - exists(Crypto::AlgorithmConsumer c | c.getInputNode() = sink) - } -} - -module AlgGetterToAlgConsumerFlow = DataFlow::Global; - -abstract class AlgorithmPassthroughCall extends Call { - abstract DataFlow::Node getInNode(); - - abstract DataFlow::Node getOutNode(); -} - -class CopyAndDupAlgorithmPassthroughCall extends AlgorithmPassthroughCall { - DataFlow::Node inNode; - DataFlow::Node outNode; - - CopyAndDupAlgorithmPassthroughCall() { - // Flow out through any return or other argument of the same type - // Assume flow in and out is asIndirectExpr or asDefinitingArgument since a pointer is assumed - // to be involved - // NOTE: not attempting to detect openssl specific copy/dup functions, but anything suspected to be copy/dup - this.getTarget().getName().toLowerCase().matches(["%_dup%", "%_copy%"]) and - exists(Expr inArg, Type t | - inArg = this.getAnArgument() and t = inArg.getUnspecifiedType().stripType() - | - inNode.asIndirectExpr() = inArg and - ( - // Case 1: flow through another argument as an out arg of the same type - exists(Expr outArg | - outArg = this.getAnArgument() and - outArg != inArg and - outArg.getUnspecifiedType().stripType() = t - | - outNode.asDefiningArgument() = outArg - ) - or - // Case 2: flow through the return value if the result is the same as the intput type - exists(Expr outArg | outArg = this and outArg.getUnspecifiedType().stripType() = t | - outNode.asIndirectExpr() = outArg - ) - ) - ) - } - - override DataFlow::Node getInNode() { result = inNode } - - override DataFlow::Node getOutNode() { result = outNode } -} - -class NIDToPointerPassthroughCall extends AlgorithmPassthroughCall { - DataFlow::Node inNode; - DataFlow::Node outNode; - - NIDToPointerPassthroughCall() { - this.getTarget().getName() in ["OBJ_nid2obj", "OBJ_nid2ln", "OBJ_nid2sn"] and - inNode.asExpr() = this.getArgument(0) and - outNode.asExpr() = this - //outNode.asIndirectExpr() = this - } - - override DataFlow::Node getInNode() { result = inNode } - - override DataFlow::Node getOutNode() { result = outNode } -} - -class PointerToPointerPassthroughCall extends AlgorithmPassthroughCall { - DataFlow::Node inNode; - DataFlow::Node outNode; - - PointerToPointerPassthroughCall() { - this.getTarget().getName() = "OBJ_txt2obj" and - inNode.asIndirectExpr() = this.getArgument(0) and - outNode.asIndirectExpr() = this - or - //outNode.asExpr() = this - this.getTarget().getName() in ["OBJ_obj2txt", "i2t_ASN1_OBJECT"] and - inNode.asIndirectExpr() = this.getArgument(2) and - outNode.asDefiningArgument() = this.getArgument(0) - } - - override DataFlow::Node getInNode() { result = inNode } - - override DataFlow::Node getOutNode() { result = outNode } -} - -class PointerToNIDPassthroughCall extends AlgorithmPassthroughCall { - DataFlow::Node inNode; - DataFlow::Node outNode; - - PointerToNIDPassthroughCall() { - this.getTarget().getName() in ["OBJ_obj2nid", "OBJ_ln2nid", "OBJ_sn2nid", "OBJ_txt2nid"] and - ( - inNode.asIndirectExpr() = this.getArgument(0) - or - inNode.asExpr() = this.getArgument(0) - ) and - outNode.asExpr() = this - } - - override DataFlow::Node getInNode() { result = inNode } - - override DataFlow::Node getOutNode() { result = outNode } -} - -predicate knownPassThroughStep(DataFlow::Node node1, DataFlow::Node node2) { - exists(AlgorithmPassthroughCall c | c.getInNode() = node1 and c.getOutNode() = node2) -} - -abstract class OpenSSLAlgorithmGetterCall extends Call { - abstract DataFlow::Node getValueArgNode(); - - abstract DataFlow::Node getResultNode(); - - abstract Expr getValueArgExpr(); - - abstract Expr getResultExpr(); -} - -module KnownOpenSSLAlgorithmToAlgorithmGetterConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { - source.asExpr() instanceof KnownOpenSSLAlgorithmConstant - } - - predicate isSink(DataFlow::Node sink) { - exists(OpenSSLAlgorithmGetterCall c | c.getValueArgNode() = sink) - } - - predicate isBarrier(DataFlow::Node node) { - // False positive reducer, don't flow out through argv - exists(VariableAccess va, Variable v | - v.getAnAccess() = va and va = node.asExpr() - or - va = node.asIndirectExpr() - | - v.getName().matches("%argv") - ) - } - - predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - knownPassThroughStep(node1, node2) - } -} - -module KnownOpenSSLAlgorithmToAlgorithmGetterFlow = - DataFlow::Global; - -/** - * Cases like EVP_MD5(), - * there is no input, rather it directly gets an algorithm - * and returns it. - */ -class DirectGetterCall extends OpenSSLAlgorithmGetterCall { - DataFlow::Node resultNode; - Expr resultExpr; - - DirectGetterCall() { - this instanceof KnownOpenSSLAlgorithmConstant and - this instanceof Call and - resultExpr = this and - resultNode.asExpr() = resultExpr - } - - override DataFlow::Node getValueArgNode() { none() } - - override DataFlow::Node getResultNode() { result = resultNode } - - override Expr getValueArgExpr() { none() } - - override Expr getResultExpr() { result = resultExpr } -} - -// https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html -class EVPCipherGetterCall extends OpenSSLAlgorithmGetterCall { - DataFlow::Node valueArgNode; - DataFlow::Node resultNode; - Expr valueArgExpr; - Expr resultExpr; - - EVPCipherGetterCall() { - resultExpr = this and - resultNode.asExpr() = this and - isPossibleOpenSSLFunction(this.getTarget()) and - ( - this.getTarget().getName() in ["EVP_get_cipherbyname", "EVP_get_cipherbyobj"] and - valueArgExpr = this.getArgument(0) and - valueArgNode.asExpr() = valueArgExpr - or - this.getTarget().getName() = "EVP_CIPHER_fetch" and - valueArgExpr = this.getArgument(1) and - valueArgNode.asExpr() = valueArgExpr - or - this.getTarget().getName() = "EVP_get_cipherbynid" and - valueArgExpr = this.getArgument(0) and - valueArgNode.asExpr() = valueArgExpr - ) - } - - override DataFlow::Node getValueArgNode() { result = valueArgNode } - - override DataFlow::Node getResultNode() { result = resultNode } - - override Expr getValueArgExpr() { result = valueArgExpr } - - override Expr getResultExpr() { result = resultExpr } -} - -class EVPAsymCipherGetterCall extends OpenSSLAlgorithmGetterCall { - DataFlow::Node valueArgNode; - DataFlow::Node resultNode; - Expr valueArgExpr; - Expr resultExpr; - - EVPAsymCipherGetterCall() { - isPossibleOpenSSLFunction(this.getTarget()) and - resultExpr = this and - resultNode.asExpr() = this and - this.getTarget().getName() = "EVP_ASYM_CIPHER_fetch" and - valueArgExpr = this.getArgument(1) and - valueArgNode.asExpr() = valueArgExpr - } - - override DataFlow::Node getValueArgNode() { result = valueArgNode } - - override DataFlow::Node getResultNode() { result = resultNode } - - override Expr getValueArgExpr() { result = valueArgExpr } - - override Expr getResultExpr() { result = resultExpr } -} - -class EVPDigestGetterCall extends OpenSSLAlgorithmGetterCall { - DataFlow::Node valueArgNode; - DataFlow::Node resultNode; - Expr valueArgExpr; - Expr resultExpr; - - EVPDigestGetterCall() { - resultExpr = this and - resultNode.asExpr() = this and - isPossibleOpenSSLFunction(this.getTarget()) and - ( - this.getTarget().getName() in [ - "EVP_get_digestbyname", "EVP_get_digestbyobj", "EVP_get_digestbynid" - ] and - valueArgExpr = this.getArgument(0) and - valueArgNode.asExpr() = valueArgExpr - or - this.getTarget().getName() = "EVP_MD_fetch" and - valueArgExpr = this.getArgument(1) and - valueArgNode.asExpr() = valueArgExpr - ) - } - - override DataFlow::Node getValueArgNode() { result = valueArgNode } - - override DataFlow::Node getResultNode() { result = resultNode } - - override Expr getValueArgExpr() { result = valueArgExpr } - - override Expr getResultExpr() { result = resultExpr } -} - -class EVPKDFFetch extends OpenSSLAlgorithmGetterCall { - DataFlow::Node valueArgNode; - DataFlow::Node resultNode; - Expr valueArgExpr; - Expr resultExpr; - - EVPKDFFetch() { - resultExpr = this and - resultNode.asExpr() = this and - isPossibleOpenSSLFunction(this.getTarget()) and - this.getTarget().getName() in ["EVP_KDF_fetch"] and - valueArgExpr = this.getArgument(1) and - valueArgNode.asExpr() = valueArgExpr - } - - override DataFlow::Node getValueArgNode() { result = valueArgNode } - - override DataFlow::Node getResultNode() { result = resultNode } - - override Expr getValueArgExpr() { result = valueArgExpr } - - override Expr getResultExpr() { result = resultExpr } -} -// /** -// * Predicates/classes for identifying algorithm sinks. -// * An Algorithm Sink is a function that takes an algorithm as an argument. -// * In particular, any function that takes in an algorithm that until the call -// * the algorithm is not definitely known to be an algorithm (e.g., an integer used as an identifier to fetch an algorithm) -// */ -// //TODO: enforce a hierarchy of AlgorithmSinkArgument, e.g., so I can get all Asymmetric SinkArguments that includes all the strictly RSA etc. // import cpp -// // import experimental.cryptography.utils.OpenSSL.LibraryFunction -// // import experimental.cryptography.CryptoAlgorithmNames -// predicate isAlgorithmSink(AlgorithmSinkArgument arg, string algType) { arg.algType() = algType } -// abstract class AlgorithmSinkArgument extends Expr { -// AlgorithmSinkArgument() { -// exists(Call c | c.getAnArgument() = this and openSSLLibraryFunc(c.getTarget())) +// import semmle.code.cpp.dataflow.new.DataFlow +// import LibraryDetector +// import OpenSSLKnownAlgorithmConstants +// import experimental.Quantum.Language +// class OpenSSLAlgorithmAdditionalFlowStep extends AdditionalFlowInputStep { +// OpenSSLAlgorithmAdditionalFlowStep() { exists(AlgorithmPassthroughCall c | c.getInNode() = this) } +// override DataFlow::Node getOutput() { +// exists(AlgorithmPassthroughCall c | c.getInNode() = this and c.getOutNode() = result) // } -// /** -// * Gets the function call in which the argument exists -// */ -// Call getSinkCall() { result.getAnArgument() = this } -// abstract string algType(); -// } -// // https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html -// predicate cipherAlgorithmSink(string funcName, int argInd) { -// funcName in ["EVP_get_cipherbyname", "EVP_get_cipherbynid", "EVP_get_cipherbyobj"] and argInd = 0 -// or -// funcName = "EVP_CIPHER_fetch" and argInd = 1 // } -// class CipherAlgorithmSink extends AlgorithmSinkArgument { -// CipherAlgorithmSink() { -// exists(Call c, string funcName, int argInd | -// funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// | -// cipherAlgorithmSink(funcName, argInd) -// ) +// module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig { +// predicate isSource(DataFlow::Node source) { +// exists(OpenSSLAlgorithmGetterCall c | c.getResultNode() = source) // } -// override string algType() { result = getSymmetricEncryptionType() } -// } -// // https://www.openssl.org/docs/manmaster/man3/EVP_MAC_fetch -// predicate macAlgorithmSink(string funcName, int argInd) { -// (funcName = "EVP_MAC_fetch" and argInd = 1) -// } -// class MACAlgorithmSink extends AlgorithmSinkArgument { -// MACAlgorithmSink() { -// exists(Call c, string funcName, int argInd | -// funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// | -// macAlgorithmSink(funcName, argInd) -// ) +// predicate isSink(DataFlow::Node sink) { +// exists(Crypto::AlgorithmConsumer c | c.getInputNode() = sink) // } -// override string algType() { result = "TBD" } // } -// // https://www.openssl.org/docs/manmaster/man3/EVP_MD_fetch -// predicate messageDigestAlgorithmSink(string funcName, int argInd) { -// funcName in ["EVP_get_digestbyname", "EVP_get_digestbynid", "EVP_get_digestbyobj"] and argInd = 0 -// or -// funcName = "EVP_MD_fetch" and argInd = 1 +// module AlgGetterToAlgConsumerFlow = DataFlow::Global; +// abstract class AlgorithmPassthroughCall extends Call { +// abstract DataFlow::Node getInNode(); +// abstract DataFlow::Node getOutNode(); // } -// class MessageDigestAlgorithmSink extends AlgorithmSinkArgument { -// MessageDigestAlgorithmSink() { -// exists(Call c, string funcName, int argInd | -// funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// class CopyAndDupAlgorithmPassthroughCall extends AlgorithmPassthroughCall { +// DataFlow::Node inNode; +// DataFlow::Node outNode; +// CopyAndDupAlgorithmPassthroughCall() { +// // Flow out through any return or other argument of the same type +// // Assume flow in and out is asIndirectExpr or asDefinitingArgument since a pointer is assumed +// // to be involved +// // NOTE: not attempting to detect openssl specific copy/dup functions, but anything suspected to be copy/dup +// this.getTarget().getName().toLowerCase().matches(["%_dup%", "%_copy%"]) and +// exists(Expr inArg, Type t | +// inArg = this.getAnArgument() and t = inArg.getUnspecifiedType().stripType() // | -// messageDigestAlgorithmSink(funcName, argInd) +// inNode.asIndirectExpr() = inArg and +// ( +// // Case 1: flow through another argument as an out arg of the same type +// exists(Expr outArg | +// outArg = this.getAnArgument() and +// outArg != inArg and +// outArg.getUnspecifiedType().stripType() = t +// | +// outNode.asDefiningArgument() = outArg +// ) +// or +// // Case 2: flow through the return value if the result is the same as the intput type +// exists(Expr outArg | outArg = this and outArg.getUnspecifiedType().stripType() = t | +// outNode.asIndirectExpr() = outArg +// ) +// ) // ) // } -// override string algType() { result = getHashType() } +// override DataFlow::Node getInNode() { result = inNode } +// override DataFlow::Node getOutNode() { result = outNode } // } -// // https://www.openssl.org/docs/manmaster/man3/EVP_KEYEXCH_fetch -// // https://www.openssl.org/docs/manmaster/man3/EVP_KEM_fetch -// predicate keyExchangeAlgorithmSink(string funcName, int argInd) { -// funcName = "EVP_KEYEXCH_fetch" and argInd = 1 -// or -// funcName = "EVP_KEM_fetch" and argInd = 1 -// } -// class KeyExchangeAlgorithmSink extends AlgorithmSinkArgument { -// KeyExchangeAlgorithmSink() { -// exists(Call c, string funcName, int argInd | -// funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// | -// keyExchangeAlgorithmSink(funcName, argInd) -// ) +// class NIDToPointerPassthroughCall extends AlgorithmPassthroughCall { +// DataFlow::Node inNode; +// DataFlow::Node outNode; +// NIDToPointerPassthroughCall() { +// this.getTarget().getName() in ["OBJ_nid2obj", "OBJ_nid2ln", "OBJ_nid2sn"] and +// inNode.asExpr() = this.getArgument(0) and +// outNode.asExpr() = this +// //outNode.asIndirectExpr() = this // } -// override string algType() { result = getKeyExchangeType() } +// override DataFlow::Node getInNode() { result = inNode } +// override DataFlow::Node getOutNode() { result = outNode } // } -// // https://www.openssl.org/docs/manmaster/man3/EVP_KEYMGMT_fetch -// predicate keyManagementAlgorithmSink(string funcName, int argInd) { -// funcName = "EVP_KEYMGMT_fetch" and argInd = 1 -// } -// class KeyManagementAlgorithmSink extends AlgorithmSinkArgument { -// KeyManagementAlgorithmSink() { -// exists(Call c, string funcName, int argInd | -// funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// | -// keyManagementAlgorithmSink(funcName, argInd) -// ) +// class PointerToPointerPassthroughCall extends AlgorithmPassthroughCall { +// DataFlow::Node inNode; +// DataFlow::Node outNode; +// PointerToPointerPassthroughCall() { +// this.getTarget().getName() = "OBJ_txt2obj" and +// inNode.asIndirectExpr() = this.getArgument(0) and +// outNode.asIndirectExpr() = this +// or +// //outNode.asExpr() = this +// this.getTarget().getName() in ["OBJ_obj2txt", "i2t_ASN1_OBJECT"] and +// inNode.asIndirectExpr() = this.getArgument(2) and +// outNode.asDefiningArgument() = this.getArgument(0) // } -// override string algType() { result = "TBD" } +// override DataFlow::Node getInNode() { result = inNode } +// override DataFlow::Node getOutNode() { result = outNode } // } -// // https://www.openssl.org/docs/manmaster/man3/EVP_KDF -// predicate keyDerivationAlgorithmSink(string funcName, int argInd) { -// funcName = "EVP_KDF_fetch" and argInd = 1 -// } -// class KeyDerivationAlgorithmSink extends AlgorithmSinkArgument { -// KeyDerivationAlgorithmSink() { -// exists(Call c, string funcName, int argInd | -// funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// | -// keyDerivationAlgorithmSink(funcName, argInd) -// ) +// class PointerToNIDPassthroughCall extends AlgorithmPassthroughCall { +// DataFlow::Node inNode; +// DataFlow::Node outNode; +// PointerToNIDPassthroughCall() { +// this.getTarget().getName() in ["OBJ_obj2nid", "OBJ_ln2nid", "OBJ_sn2nid", "OBJ_txt2nid"] and +// ( +// inNode.asIndirectExpr() = this.getArgument(0) +// or +// inNode.asExpr() = this.getArgument(0) +// ) and +// outNode.asExpr() = this // } -// override string algType() { result = getKeyDerivationType() } +// override DataFlow::Node getInNode() { result = inNode } +// override DataFlow::Node getOutNode() { result = outNode } // } -// // https://www.openssl.org/docs/manmaster/man3/EVP_ASYM_CIPHER_fetch -// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_new_id -// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_new_CMAC_key.html -// predicate asymmetricCipherAlgorithmSink(string funcName, int argInd) { -// funcName = "EVP_ASYM_CIPHER_fetch" and argInd = 1 -// or -// funcName = "EVP_PKEY_new_CMAC_key" and argInd = 3 -// // NOTE: other cases are handled by AsymmetricAlgorithmSink +// predicate knownPassThroughStep(DataFlow::Node node1, DataFlow::Node node2) { +// exists(AlgorithmPassthroughCall c | c.getInNode() = node1 and c.getOutNode() = node2) // } -// class AsymmetricCipherAlgorithmSink extends AlgorithmSinkArgument { -// AsymmetricCipherAlgorithmSink() { -// exists(Call c, string funcName, int argInd | -// funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// | -// asymmetricCipherAlgorithmSink(funcName, argInd) -// ) -// } -// override string algType() { result = "ASYMMETRIC_ENCRYPTION" } +// abstract class OpenSSLAlgorithmGetterCall extends Call { +// abstract DataFlow::Node getValueArgNode(); +// abstract DataFlow::Node getResultNode(); +// abstract Expr getValueArgExpr(); +// abstract Expr getResultExpr(); // } -// class AsymmetricCipherAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument { -// AsymmetricCipherAlgorithmSink_EVP_PKEY_Q_keygen() { -// exists(Call c, string funcName | -// funcName = c.getTarget().getName() and -// this = c.getArgument(3) -// | -// funcName = "EVP_PKEY_Q_keygen" and -// c.getArgument(3).getType().getUnderlyingType() instanceof IntegralType -// ) +// module KnownOpenSSLAlgorithmToAlgorithmGetterConfig implements DataFlow::ConfigSig { +// predicate isSource(DataFlow::Node source) { +// source.asExpr() instanceof KnownOpenSSLAlgorithmConstant // } -// override string algType() { result = "ASYMMETRIC_ENCRYPTION" } -// } -// // https://www.openssl.org/docs/manmaster/man3/EVP_RAND_fetch -// predicate randomAlgorithmSink(string funcName, int argInd) { -// funcName = "EVP_RAND_fetch" and argInd = 1 -// } -// class RandomAlgorithmSink extends AlgorithmSinkArgument { -// RandomAlgorithmSink() { -// exists(Call c, string funcName, int argInd | -// funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// | -// randomAlgorithmSink(funcName, argInd) -// ) +// predicate isSink(DataFlow::Node sink) { +// exists(OpenSSLAlgorithmGetterCall c | c.getValueArgNode() = sink) // } -// override string algType() { result = "TBD" } -// } -// // https://www.openssl.org/docs/manmaster/man3/EVP_SIGNATURE_fetch -// predicate signatureAlgorithmSink(string funcName, int argInd) { -// funcName = "EVP_SIGNATURE_fetch" and argInd = 1 -// } -// class SignatureAlgorithmSink extends AlgorithmSinkArgument { -// SignatureAlgorithmSink() { -// exists(Call c, string funcName, int argInd | -// funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// predicate isBarrier(DataFlow::Node node) { +// // False positive reducer, don't flow out through argv +// exists(VariableAccess va, Variable v | +// v.getAnAccess() = va and va = node.asExpr() +// or +// va = node.asIndirectExpr() // | -// signatureAlgorithmSink(funcName, argInd) +// v.getName().matches("%argv") // ) // } -// override string algType() { result = getSignatureType() } -// } -// // https://www.openssl.org/docs/manmaster/man3/EC_KEY_new_by_curve_name.html -// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_ec_paramgen_curve_nid.html -// predicate ellipticCurveAlgorithmSink(string funcName, int argInd) { -// funcName in ["EC_KEY_new_by_curve_name", "EVP_EC_gen"] and argInd = 0 -// or -// funcName = "EC_KEY_new_by_curve_name_ex" and argInd = 2 -// or -// funcName in ["EVP_PKEY_CTX_set_ec_paramgen_curve_nid"] and argInd = 1 -// } -// class EllipticCurveAlgorithmSink extends AlgorithmSinkArgument { -// EllipticCurveAlgorithmSink() { -// exists(Call c, string funcName, int argInd | -// funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// | -// ellipticCurveAlgorithmSink(funcName, argInd) -// ) +// predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { +// knownPassThroughStep(node1, node2) // } -// override string algType() { result = getEllipticCurveType() } // } +// module KnownOpenSSLAlgorithmToAlgorithmGetterFlow = +// DataFlow::Global; // /** -// * Special cased to address the fact that arg index 3 (zero offset based) is the curve name. -// * ASSUMPTION: if the arg ind 3 is a char* assume it is an elliptic curve +// * Cases like EVP_MD5(), +// * there is no input, rather it directly gets an algorithm +// * and returns it. // */ -// class EllipticCurveAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument { -// EllipticCurveAlgorithmSink_EVP_PKEY_Q_keygen() { -// exists(Call c, string funcName | -// funcName = c.getTarget().getName() and -// this = c.getArgument(3) -// | -// funcName = "EVP_PKEY_Q_keygen" and -// c.getArgument(3).getType().getUnderlyingType() instanceof PointerType and -// c.getArgument(3).getType().getUnderlyingType().stripType() instanceof CharType +// class DirectGetterCall extends OpenSSLAlgorithmGetterCall { +// DataFlow::Node resultNode; +// Expr resultExpr; +// DirectGetterCall() { +// this instanceof KnownOpenSSLAlgorithmConstant and +// this instanceof Call and +// resultExpr = this and +// resultNode.asExpr() = resultExpr +// } +// override DataFlow::Node getValueArgNode() { none() } +// override DataFlow::Node getResultNode() { result = resultNode } +// override Expr getValueArgExpr() { none() } +// override Expr getResultExpr() { result = resultExpr } +// } +// // https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html +// class EVPCipherGetterCall extends OpenSSLAlgorithmGetterCall { +// DataFlow::Node valueArgNode; +// DataFlow::Node resultNode; +// Expr valueArgExpr; +// Expr resultExpr; +// EVPCipherGetterCall() { +// resultExpr = this and +// resultNode.asExpr() = this and +// isPossibleOpenSSLFunction(this.getTarget()) and +// ( +// this.getTarget().getName() in ["EVP_get_cipherbyname", "EVP_get_cipherbyobj"] and +// valueArgExpr = this.getArgument(0) and +// valueArgNode.asExpr() = valueArgExpr +// or +// this.getTarget().getName() = "EVP_CIPHER_fetch" and +// valueArgExpr = this.getArgument(1) and +// valueArgNode.asExpr() = valueArgExpr +// or +// this.getTarget().getName() = "EVP_get_cipherbynid" and +// valueArgExpr = this.getArgument(0) and +// valueArgNode.asExpr() = valueArgExpr // ) // } -// override string algType() { result = getEllipticCurveType() } +// override DataFlow::Node getValueArgNode() { result = valueArgNode } +// override DataFlow::Node getResultNode() { result = resultNode } +// override Expr getValueArgExpr() { result = valueArgExpr } +// override Expr getResultExpr() { result = resultExpr } // } -// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_new_id.html -// // https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_new_raw_private_key.html -// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_new.html -// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_ctrl.html -// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_Q_keygen.html -// // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_ctrl.html -// predicate asymmetricAlgorithmSink(string funcName, int argInd) { -// funcName = "EVP_PKEY_CTX_new_id" and argInd = 0 -// or -// funcName = "EVP_PKEY_CTX_new_from_name" and argInd = 1 -// or -// funcName in [ -// "EVP_PKEY_new_raw_private_key", "EVP_PKEY_new_raw_public_key", "EVP_PKEY_new_mac_key" -// ] and -// argInd = 0 -// or -// funcName in ["EVP_PKEY_new_raw_private_key_ex", "EVP_PKEY_new_raw_public_key_ex"] and argInd = 1 -// or -// // special casing this as arg index 3 must be specified depending on if RSA or ECC, and otherwise not specified for other algs -// // funcName = "EVP_PKEY_Q_keygen" and argInd = 2 -// funcName in ["EVP_PKEY_CTX_ctrl", "EVP_PKEY_CTX_set_group_name"] and argInd = 1 -// // TODO consider void cases EVP_PKEY_new +// class EVPAsymCipherGetterCall extends OpenSSLAlgorithmGetterCall { +// DataFlow::Node valueArgNode; +// DataFlow::Node resultNode; +// Expr valueArgExpr; +// Expr resultExpr; +// EVPAsymCipherGetterCall() { +// isPossibleOpenSSLFunction(this.getTarget()) and +// resultExpr = this and +// resultNode.asExpr() = this and +// this.getTarget().getName() = "EVP_ASYM_CIPHER_fetch" and +// valueArgExpr = this.getArgument(1) and +// valueArgNode.asExpr() = valueArgExpr +// } +// override DataFlow::Node getValueArgNode() { result = valueArgNode } +// override DataFlow::Node getResultNode() { result = resultNode } +// override Expr getValueArgExpr() { result = valueArgExpr } +// override Expr getResultExpr() { result = resultExpr } // } -// class AsymmetricAlgorithmSink extends AlgorithmSinkArgument { -// AsymmetricAlgorithmSink() { -// exists(Call c, string funcName, int argInd | -// funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// | -// asymmetricAlgorithmSink(funcName, argInd) +// class EVPDigestGetterCall extends OpenSSLAlgorithmGetterCall { +// DataFlow::Node valueArgNode; +// DataFlow::Node resultNode; +// Expr valueArgExpr; +// Expr resultExpr; +// EVPDigestGetterCall() { +// resultExpr = this and +// resultNode.asExpr() = this and +// isPossibleOpenSSLFunction(this.getTarget()) and +// ( +// this.getTarget().getName() in [ +// "EVP_get_digestbyname", "EVP_get_digestbyobj", "EVP_get_digestbynid" +// ] and +// valueArgExpr = this.getArgument(0) and +// valueArgNode.asExpr() = valueArgExpr +// or +// this.getTarget().getName() = "EVP_MD_fetch" and +// valueArgExpr = this.getArgument(1) and +// valueArgNode.asExpr() = valueArgExpr // ) // } -// override string algType() { result = getAsymmetricType() } +// override DataFlow::Node getValueArgNode() { result = valueArgNode } +// override DataFlow::Node getResultNode() { result = resultNode } +// override Expr getValueArgExpr() { result = valueArgExpr } +// override Expr getResultExpr() { result = resultExpr } // } -// class AsymmetricAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument { -// AsymmetricAlgorithmSink_EVP_PKEY_Q_keygen() { -// exists(Call c, string funcName | -// funcName = c.getTarget().getName() and -// this = c.getArgument(2) -// | -// funcName = "EVP_PKEY_Q_keygen" and -// not exists(c.getArgument(3)) -// ) +// class EVPKDFFetch extends OpenSSLAlgorithmGetterCall { +// DataFlow::Node valueArgNode; +// DataFlow::Node resultNode; +// Expr valueArgExpr; +// Expr resultExpr; +// EVPKDFFetch() { +// resultExpr = this and +// resultNode.asExpr() = this and +// isPossibleOpenSSLFunction(this.getTarget()) and +// this.getTarget().getName() in ["EVP_KDF_fetch"] and +// valueArgExpr = this.getArgument(1) and +// valueArgNode.asExpr() = valueArgExpr // } -// override string algType() { result = getAsymmetricType() } +// override DataFlow::Node getValueArgNode() { result = valueArgNode } +// override DataFlow::Node getResultNode() { result = resultNode } +// override Expr getValueArgExpr() { result = valueArgExpr } +// override Expr getResultExpr() { result = resultExpr } // } +// // /** +// // * Predicates/classes for identifying algorithm sinks. +// // * An Algorithm Sink is a function that takes an algorithm as an argument. +// // * In particular, any function that takes in an algorithm that until the call +// // * the algorithm is not definitely known to be an algorithm (e.g., an integer used as an identifier to fetch an algorithm) +// // */ +// // //TODO: enforce a hierarchy of AlgorithmSinkArgument, e.g., so I can get all Asymmetric SinkArguments that includes all the strictly RSA etc. +// // import cpp +// // // import experimental.cryptography.utils.OpenSSL.LibraryFunction +// // // import experimental.cryptography.CryptoAlgorithmNames +// // predicate isAlgorithmSink(AlgorithmSinkArgument arg, string algType) { arg.algType() = algType } +// // abstract class AlgorithmSinkArgument extends Expr { +// // AlgorithmSinkArgument() { +// // exists(Call c | c.getAnArgument() = this and openSSLLibraryFunc(c.getTarget())) +// // } +// // /** +// // * Gets the function call in which the argument exists +// // */ +// // Call getSinkCall() { result.getAnArgument() = this } +// // abstract string algType(); +// // } +// // // https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html +// // predicate cipherAlgorithmSink(string funcName, int argInd) { +// // funcName in ["EVP_get_cipherbyname", "EVP_get_cipherbynid", "EVP_get_cipherbyobj"] and argInd = 0 +// // or +// // funcName = "EVP_CIPHER_fetch" and argInd = 1 +// // } +// // class CipherAlgorithmSink extends AlgorithmSinkArgument { +// // CipherAlgorithmSink() { +// // exists(Call c, string funcName, int argInd | +// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// // | +// // cipherAlgorithmSink(funcName, argInd) +// // ) +// // } +// // override string algType() { result = getSymmetricEncryptionType() } +// // } +// // // https://www.openssl.org/docs/manmaster/man3/EVP_MAC_fetch +// // predicate macAlgorithmSink(string funcName, int argInd) { +// // (funcName = "EVP_MAC_fetch" and argInd = 1) +// // } +// // class MACAlgorithmSink extends AlgorithmSinkArgument { +// // MACAlgorithmSink() { +// // exists(Call c, string funcName, int argInd | +// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// // | +// // macAlgorithmSink(funcName, argInd) +// // ) +// // } +// // override string algType() { result = "TBD" } +// // } +// // // https://www.openssl.org/docs/manmaster/man3/EVP_MD_fetch +// // predicate messageDigestAlgorithmSink(string funcName, int argInd) { +// // funcName in ["EVP_get_digestbyname", "EVP_get_digestbynid", "EVP_get_digestbyobj"] and argInd = 0 +// // or +// // funcName = "EVP_MD_fetch" and argInd = 1 +// // } +// // class MessageDigestAlgorithmSink extends AlgorithmSinkArgument { +// // MessageDigestAlgorithmSink() { +// // exists(Call c, string funcName, int argInd | +// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// // | +// // messageDigestAlgorithmSink(funcName, argInd) +// // ) +// // } +// // override string algType() { result = getHashType() } +// // } +// // // https://www.openssl.org/docs/manmaster/man3/EVP_KEYEXCH_fetch +// // // https://www.openssl.org/docs/manmaster/man3/EVP_KEM_fetch +// // predicate keyExchangeAlgorithmSink(string funcName, int argInd) { +// // funcName = "EVP_KEYEXCH_fetch" and argInd = 1 +// // or +// // funcName = "EVP_KEM_fetch" and argInd = 1 +// // } +// // class KeyExchangeAlgorithmSink extends AlgorithmSinkArgument { +// // KeyExchangeAlgorithmSink() { +// // exists(Call c, string funcName, int argInd | +// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// // | +// // keyExchangeAlgorithmSink(funcName, argInd) +// // ) +// // } +// // override string algType() { result = getKeyExchangeType() } +// // } +// // // https://www.openssl.org/docs/manmaster/man3/EVP_KEYMGMT_fetch +// // predicate keyManagementAlgorithmSink(string funcName, int argInd) { +// // funcName = "EVP_KEYMGMT_fetch" and argInd = 1 +// // } +// // class KeyManagementAlgorithmSink extends AlgorithmSinkArgument { +// // KeyManagementAlgorithmSink() { +// // exists(Call c, string funcName, int argInd | +// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// // | +// // keyManagementAlgorithmSink(funcName, argInd) +// // ) +// // } +// // override string algType() { result = "TBD" } +// // } +// // // https://www.openssl.org/docs/manmaster/man3/EVP_KDF +// // predicate keyDerivationAlgorithmSink(string funcName, int argInd) { +// // funcName = "EVP_KDF_fetch" and argInd = 1 +// // } +// // class KeyDerivationAlgorithmSink extends AlgorithmSinkArgument { +// // KeyDerivationAlgorithmSink() { +// // exists(Call c, string funcName, int argInd | +// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// // | +// // keyDerivationAlgorithmSink(funcName, argInd) +// // ) +// // } +// // override string algType() { result = getKeyDerivationType() } +// // } +// // // https://www.openssl.org/docs/manmaster/man3/EVP_ASYM_CIPHER_fetch +// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_new_id +// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_new_CMAC_key.html +// // predicate asymmetricCipherAlgorithmSink(string funcName, int argInd) { +// // funcName = "EVP_ASYM_CIPHER_fetch" and argInd = 1 +// // or +// // funcName = "EVP_PKEY_new_CMAC_key" and argInd = 3 +// // // NOTE: other cases are handled by AsymmetricAlgorithmSink +// // } +// // class AsymmetricCipherAlgorithmSink extends AlgorithmSinkArgument { +// // AsymmetricCipherAlgorithmSink() { +// // exists(Call c, string funcName, int argInd | +// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// // | +// // asymmetricCipherAlgorithmSink(funcName, argInd) +// // ) +// // } +// // override string algType() { result = "ASYMMETRIC_ENCRYPTION" } +// // } +// // class AsymmetricCipherAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument { +// // AsymmetricCipherAlgorithmSink_EVP_PKEY_Q_keygen() { +// // exists(Call c, string funcName | +// // funcName = c.getTarget().getName() and +// // this = c.getArgument(3) +// // | +// // funcName = "EVP_PKEY_Q_keygen" and +// // c.getArgument(3).getType().getUnderlyingType() instanceof IntegralType +// // ) +// // } +// // override string algType() { result = "ASYMMETRIC_ENCRYPTION" } +// // } +// // // https://www.openssl.org/docs/manmaster/man3/EVP_RAND_fetch +// // predicate randomAlgorithmSink(string funcName, int argInd) { +// // funcName = "EVP_RAND_fetch" and argInd = 1 +// // } +// // class RandomAlgorithmSink extends AlgorithmSinkArgument { +// // RandomAlgorithmSink() { +// // exists(Call c, string funcName, int argInd | +// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// // | +// // randomAlgorithmSink(funcName, argInd) +// // ) +// // } +// // override string algType() { result = "TBD" } +// // } +// // // https://www.openssl.org/docs/manmaster/man3/EVP_SIGNATURE_fetch +// // predicate signatureAlgorithmSink(string funcName, int argInd) { +// // funcName = "EVP_SIGNATURE_fetch" and argInd = 1 +// // } +// // class SignatureAlgorithmSink extends AlgorithmSinkArgument { +// // SignatureAlgorithmSink() { +// // exists(Call c, string funcName, int argInd | +// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// // | +// // signatureAlgorithmSink(funcName, argInd) +// // ) +// // } +// // override string algType() { result = getSignatureType() } +// // } +// // // https://www.openssl.org/docs/manmaster/man3/EC_KEY_new_by_curve_name.html +// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_ec_paramgen_curve_nid.html +// // predicate ellipticCurveAlgorithmSink(string funcName, int argInd) { +// // funcName in ["EC_KEY_new_by_curve_name", "EVP_EC_gen"] and argInd = 0 +// // or +// // funcName = "EC_KEY_new_by_curve_name_ex" and argInd = 2 +// // or +// // funcName in ["EVP_PKEY_CTX_set_ec_paramgen_curve_nid"] and argInd = 1 +// // } +// // class EllipticCurveAlgorithmSink extends AlgorithmSinkArgument { +// // EllipticCurveAlgorithmSink() { +// // exists(Call c, string funcName, int argInd | +// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// // | +// // ellipticCurveAlgorithmSink(funcName, argInd) +// // ) +// // } +// // override string algType() { result = getEllipticCurveType() } +// // } +// // /** +// // * Special cased to address the fact that arg index 3 (zero offset based) is the curve name. +// // * ASSUMPTION: if the arg ind 3 is a char* assume it is an elliptic curve +// // */ +// // class EllipticCurveAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument { +// // EllipticCurveAlgorithmSink_EVP_PKEY_Q_keygen() { +// // exists(Call c, string funcName | +// // funcName = c.getTarget().getName() and +// // this = c.getArgument(3) +// // | +// // funcName = "EVP_PKEY_Q_keygen" and +// // c.getArgument(3).getType().getUnderlyingType() instanceof PointerType and +// // c.getArgument(3).getType().getUnderlyingType().stripType() instanceof CharType +// // ) +// // } +// // override string algType() { result = getEllipticCurveType() } +// // } +// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_new_id.html +// // // https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_new_raw_private_key.html +// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_new.html +// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_ctrl.html +// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_Q_keygen.html +// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_ctrl.html +// // predicate asymmetricAlgorithmSink(string funcName, int argInd) { +// // funcName = "EVP_PKEY_CTX_new_id" and argInd = 0 +// // or +// // funcName = "EVP_PKEY_CTX_new_from_name" and argInd = 1 +// // or +// // funcName in [ +// // "EVP_PKEY_new_raw_private_key", "EVP_PKEY_new_raw_public_key", "EVP_PKEY_new_mac_key" +// // ] and +// // argInd = 0 +// // or +// // funcName in ["EVP_PKEY_new_raw_private_key_ex", "EVP_PKEY_new_raw_public_key_ex"] and argInd = 1 +// // or +// // // special casing this as arg index 3 must be specified depending on if RSA or ECC, and otherwise not specified for other algs +// // // funcName = "EVP_PKEY_Q_keygen" and argInd = 2 +// // funcName in ["EVP_PKEY_CTX_ctrl", "EVP_PKEY_CTX_set_group_name"] and argInd = 1 +// // // TODO consider void cases EVP_PKEY_new +// // } +// // class AsymmetricAlgorithmSink extends AlgorithmSinkArgument { +// // AsymmetricAlgorithmSink() { +// // exists(Call c, string funcName, int argInd | +// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) +// // | +// // asymmetricAlgorithmSink(funcName, argInd) +// // ) +// // } +// // override string algType() { result = getAsymmetricType() } +// // } +// // class AsymmetricAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument { +// // AsymmetricAlgorithmSink_EVP_PKEY_Q_keygen() { +// // exists(Call c, string funcName | +// // funcName = c.getTarget().getName() and +// // this = c.getArgument(2) +// // | +// // funcName = "EVP_PKEY_Q_keygen" and +// // not exists(c.getArgument(3)) +// // ) +// // } +// // override string algType() { result = getAsymmetricType() } +// // } diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index cebbac2ff6bd..2f5e2ca77faa 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -318,6 +318,8 @@ module CryptographyBase Input> { abstract class CipherOutputArtifactInstance extends ArtifactInstance { final override DataFlowNode getInputNode() { none() } + + override predicate isConsumerArtifact() { none() } } // Artifacts that may be outputs or inputs @@ -967,6 +969,7 @@ module CryptographyBase Input> { newtype TPaddingType = PKCS1_v1_5() or // RSA encryption/signing padding + PSS() or PKCS7() or // Standard block cipher padding (PKCS5 for 8-byte blocks) ANSI_X9_23() or // Zero-padding except last byte = padding length NoPadding() or // Explicit no-padding @@ -988,6 +991,8 @@ module CryptographyBase Input> { final private predicate paddingToNameMapping(TPaddingType type, string name) { type instanceof PKCS1_v1_5 and name = "PKCS1_v1_5" or + type instanceof PSS and name = "PSS" + or type instanceof PKCS7 and name = "PKCS7" or type instanceof ANSI_X9_23 and name = "ANSI_X9_23" From d18dac0c8e79a738cc53eb0991bc88890cc983ed Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 20 Mar 2025 21:26:18 +0100 Subject: [PATCH 071/336] Add JCA key (generation) modelling --- java/ql/lib/experimental/Quantum/JCA.qll | 98 +++++++++++++- java/ql/lib/experimental/Quantum/Language.qll | 30 +++-- .../ql/src/experimental/Quantum/TestCipher.ql | 7 +- .../src/experimental/Quantum/TestCipherKey.ql | 17 +++ .../codeql/cryptography/Model.qll | 127 +++++++++++++++--- 5 files changed, 240 insertions(+), 39 deletions(-) create mode 100644 java/ql/src/experimental/Quantum/TestCipherKey.ql diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 336f7fe5cc55..e0e30f6d5106 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -84,7 +84,7 @@ module JCAModel { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof CipherStringLiteral } predicate isSink(DataFlow::Node sink) { - exists(CipherGetInstanceCall call | sink.asExpr() = call.getAlgorithmArg()) + exists(Crypto::AlgorithmValueConsumer consumer | sink = consumer.getInputNode()) } } @@ -102,13 +102,13 @@ module JCAModel { class CipherStringLiteralAlgorithmInstance extends Crypto::CipherAlgorithmInstance, Crypto::ModeOfOperationAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof CipherStringLiteral { - CipherGetInstanceAlgorithmArg consumer; + Crypto::AlgorithmValueConsumer consumer; CipherStringLiteralAlgorithmInstance() { - AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), DataFlow::exprNode(consumer)) + AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) } - CipherGetInstanceAlgorithmArg getConsumer() { result = consumer } + Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { result = this and exists(this.getRawModeAlgorithmName()) // TODO: provider defaults @@ -411,6 +411,19 @@ module JCAModel { } } + // e.g., getPublic or getPrivate + class KeyPairGetKeyCall extends MethodCall { + KeyPairGetKeyCall() { + this.getCallee().hasQualifiedName("java.security", "KeyPair", "getPublic") + or + this.getCallee().hasQualifiedName("java.security", "KeyPair", "getPrivate") + } + + DataFlow::Node getInputNode() { result.asExpr() = this.getQualifier() } + + DataFlow::Node getOutputNode() { result.asExpr() = this } + } + predicate additionalFlowSteps(DataFlow::Node node1, DataFlow::Node node2) { exists(IvParameterSpecGetIvCall m | node1.asExpr() = m.getQualifier() and @@ -421,12 +434,17 @@ module JCAModel { node1 = n.getInputNode() and node2 = n.getOutputNode() ) + or + exists(KeyPairGetKeyCall call | + node1 = call.getInputNode() and + node2 = call.getOutputNode() + ) } - class NonceAdditionalFlowInputStep extends AdditionalFlowInputStep { + class ArtifactAdditionalFlowStep extends AdditionalFlowInputStep { DataFlow::Node output; - NonceAdditionalFlowInputStep() { additionalFlowSteps(this, output) } + ArtifactAdditionalFlowStep() { additionalFlowSteps(this, output) } override DataFlow::Node getOutput() { result = output } } @@ -605,4 +623,72 @@ module JCAModel { ) } } + + class KeyGeneratorCallAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { + KeyGeneratorGetInstanceCall call; + + KeyGeneratorCallAlgorithmValueConsumer() { this = call.getAlgorithmArg() } + + override DataFlow::Node getInputNode() { result.asExpr() = this } + + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + result.(CipherStringLiteralAlgorithmInstance).getConsumer() = this + } + } + + // flow from instance created by getInstance to generateKey + module KeyGeneratorGetInstanceToGenerateConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + exists(KeyGeneratorGetInstanceCall call | src.asExpr() = call) + } + + predicate isSink(DataFlow::Node sink) { + exists(KeyGeneratorGenerateCall call | sink.asExpr() = call.(MethodCall).getQualifier()) + } + } + + module KeyGeneratorGetInstanceToGenerateFlow = + DataFlow::Global; + + class KeyGeneratorGetInstanceCall extends MethodCall { + KeyGeneratorGetInstanceCall() { + this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "getInstance") + or + this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "getInstance") + } + + Expr getAlgorithmArg() { result = super.getArgument(0) } + + predicate flowsTo(KeyGeneratorGenerateCall sink) { + KeyGeneratorGetInstanceToGenerateFlow::flow(DataFlow::exprNode(this), + DataFlow::exprNode(sink.(MethodCall).getQualifier())) + } + } + + class KeyGeneratorGenerateCall extends Crypto::KeyGenerationOperationInstance instanceof MethodCall + { + Crypto::KeyArtifactType type; + + KeyGeneratorGenerateCall() { + this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "generateKey") and + type instanceof Crypto::TSymmetricKeyType + or + this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "generateKeyPair") and + type instanceof Crypto::TAsymmetricKeyType + } + + override DataFlow::Node getOutputKeyArtifact() { result.asExpr() = this } + + override Crypto::KeyArtifactType getOutputKeyType() { result = type } + + override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { + exists(KeyGeneratorGetInstanceCall getInstance | + getInstance.flowsTo(this) and result = getInstance.getAlgorithmArg() + ) + } + + Crypto::AlgorithmInstance getAKnownAlgorithm() { + result = this.getAnAlgorithmValueConsumer().getAKnownAlgorithmSource() + } + } } diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 5666a0c42bb5..e8bb052b6203 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -30,6 +30,12 @@ module CryptoInput implements InputSig { result = node.asExpr() or result = node.asParameter() } + + predicate artifactOutputFlowsToGenericInput( + DataFlow::Node artifactOutput, DataFlow::Node otherInput + ) { + ArtifactUniversalFlow::flow(artifactOutput, otherInput) + } } /** @@ -70,16 +76,20 @@ class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { override string getAdditionalDescription() { result = this.toString() } } -class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource instanceof Literal { - override DataFlow::Node getOutputNode() { result.asExpr() = this } - - override predicate flowsTo(Crypto::FlowAwareElement other) { - // TODO: separate config to avoid blowing up data-flow analysis - GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) - } - - override string getAdditionalDescription() { result = this.toString() } -} +/* + * class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource instanceof Literal { + * ConstantDataSource() { not this instanceof Crypto::KnownElement } + * + * override DataFlow::Node getOutputNode() { result.asExpr() = this } + * + * override predicate flowsTo(Crypto::FlowAwareElement other) { + * // TODO: separate config to avoid blowing up data-flow analysis + * GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) + * } + * + * override string getAdditionalDescription() { result = this.toString() } + * } + */ /** * Random number generation, where each instance is modelled as the expression diff --git a/java/ql/src/experimental/Quantum/TestCipher.ql b/java/ql/src/experimental/Quantum/TestCipher.ql index b98347a57eca..8743ef3aa19b 100644 --- a/java/ql/src/experimental/Quantum/TestCipher.ql +++ b/java/ql/src/experimental/Quantum/TestCipher.ql @@ -7,11 +7,12 @@ import experimental.Quantum.Language from Crypto::CipherOperationNode op, Crypto::CipherAlgorithmNode a, Crypto::ModeOfOperationAlgorithmNode m, Crypto::PaddingAlgorithmNode p, - Crypto::NonceArtifactNode nonce + Crypto::NonceArtifactNode nonce, Crypto::KeyArtifactNode k where a = op.getAKnownCipherAlgorithm() and m = a.getModeOfOperation() and p = a.getPaddingAlgorithm() and - nonce = op.getANonce() + nonce = op.getANonce() and + k = op.getAKey() select op, op.getCipherOperationSubtype(), a, a.getRawAlgorithmName(), m, m.getRawAlgorithmName(), - p, p.getRawAlgorithmName(), nonce + p, p.getRawAlgorithmName(), nonce, k, k.getSourceElement() diff --git a/java/ql/src/experimental/Quantum/TestCipherKey.ql b/java/ql/src/experimental/Quantum/TestCipherKey.ql new file mode 100644 index 000000000000..1ae0cdfd89f0 --- /dev/null +++ b/java/ql/src/experimental/Quantum/TestCipherKey.ql @@ -0,0 +1,17 @@ +/** + * @name "PQC Test" + */ + +import experimental.Quantum.Language + +from Crypto::CipherOperationNode op, Crypto::CipherAlgorithmNode a, Crypto::KeyArtifactNode k +where + a = op.getAKnownCipherAlgorithm() and + k = op.getAKey() +select op, op.getCipherOperationSubtype(), a, a.getRawAlgorithmName(), k, k.getSourceNode() +/* + * from Crypto::CipherOperationNode op + * where op.getLocation().getFile().getBaseName() = "AsymmetricEncryptionMacHybridCryptosystem.java" + * select op, op.getAKey().getSourceNode() + */ + diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 2f5e2ca77faa..2a006cd7f82d 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -22,6 +22,10 @@ signature module InputSig { class UnknownLocation instanceof Location; LocatableElement dfn_to_element(DataFlowNode node); + + predicate artifactOutputFlowsToGenericInput( + DataFlowNode artifactOutput, DataFlowNode otherFlowAwareInput + ); } module CryptographyBase Input> { @@ -51,26 +55,22 @@ module CryptographyBase Input> { ) } - NodeBase getPassthroughNodeChild(NodeBase node) { - result = node.(CipherInputNode).getChild(_) or - result = node.(NonceArtifactNode).getChild(_) - } + NodeBase getPassthroughNodeChild(NodeBase node) { result = node.getChild(_) } predicate isPassthroughNode(NodeBase node) { - node instanceof CipherInputNode or - node instanceof NonceArtifactNode + node.asElement() instanceof ArtifactConsumerAndInstance } predicate nodes_graph_impl(NodeBase node, string key, string value) { not node.isExcludedFromGraph() and - not isPassthroughNode(node) and + not isPassthroughNode(node) and // TODO: punt to fix known unknowns for passthrough nodes ( key = "semmle.label" and value = node.toString() or // CodeQL's DGML output does not include a location key = "Location" and - value = node.getLocation().toString() + value = "demo" // node.getLocation().toString() or // Known unknown edges should be reported as properties rather than edges node = node.getChild(key) and @@ -305,22 +305,17 @@ module CryptographyBase Input> { // in order for a flowsTo to be defined. At the per-modeling-instance level, extend that language-level class! abstract class OutputArtifactInstance extends ArtifactInstance { override predicate isConsumerArtifact() { none() } - } - abstract class DigestArtifactInstance extends OutputArtifactInstance { - final override DataFlowNode getInputNode() { none() } + override DataFlowNode getInputNode() { none() } } + abstract class DigestArtifactInstance extends OutputArtifactInstance { } + abstract class RandomNumberGenerationInstance extends OutputArtifactInstance { // TODO: input seed? - final override DataFlowNode getInputNode() { none() } } - abstract class CipherOutputArtifactInstance extends ArtifactInstance { - final override DataFlowNode getInputNode() { none() } - - override predicate isConsumerArtifact() { none() } - } + abstract class CipherOutputArtifactInstance extends OutputArtifactInstance { } // Artifacts that may be outputs or inputs newtype TKeyArtifactType = @@ -338,13 +333,30 @@ module CryptographyBase Input> { } } - abstract class KeyArtifactInstance extends ArtifactInstance { + abstract private class KeyArtifactInstance extends ArtifactInstance { abstract KeyArtifactType getKeyType(); } - final class KeyArtifactConsumer extends ArtifactConsumerAndInstance, KeyArtifactInstance { + final class KeyArtifactOutputInstance extends KeyArtifactInstance, OutputArtifactInstance { + KeyCreationOperationInstance creator; + + KeyArtifactOutputInstance() { Input::dfn_to_element(creator.getOutputKeyArtifact()) = this } + + final KeyCreationOperationInstance getCreator() { result = creator } + + override KeyArtifactType getKeyType() { result = creator.getOutputKeyType() } + + override DataFlowNode getOutputNode() { result = creator.getOutputKeyArtifact() } + + override predicate flowsTo(FlowAwareElement other) { + Input::artifactOutputFlowsToGenericInput(this.getOutputNode(), other.getInputNode()) + } + } + + final class KeyArtifactConsumer extends KeyArtifactInstance, ArtifactConsumerAndInstance { DataFlowNode inputNode; + // TODO: key type hint? e.g. hint: private || public KeyArtifactConsumer() { exists(CipherOperationInstance op | inputNode = op.getKeyConsumer()) and this = Input::dfn_to_element(inputNode) @@ -483,6 +495,33 @@ module CryptographyBase Input> { abstract class KeyDerivationAlgorithmInstance extends AlgorithmInstance { } + abstract private class KeyCreationOperationInstance extends OperationInstance { + abstract string getKeyCreationTypeDescription(); + + /** + * Gets the key artifact produced by this operation. + */ + abstract DataFlowNode getOutputKeyArtifact(); + + /** + * Gets the key artifact type produced. + */ + abstract KeyArtifactType getOutputKeyType(); + + /** + * Gets the key size of the key produced by this operation. + */ + string getKeySize() { none() } // TODO: punt, might need a generic value consumer? + } + + abstract class KeyGenerationOperationInstance extends KeyCreationOperationInstance { + final override string getKeyCreationTypeDescription() { result = "KeyGeneration" } + } + + abstract class KeyLoadOperationInstance extends KeyCreationOperationInstance { + final override string getKeyCreationTypeDescription() { result = "KeyLoad" } + } + private signature class AlgorithmInstanceType instanceof AlgorithmInstance; module AlgorithmInstanceOrValueConsumer { @@ -519,6 +558,8 @@ module CryptographyBase Input> { TKeyDerivationOperation(KeyDerivationOperationInstance e) or TCipherOperation(CipherOperationInstance e) or TKeyEncapsulationOperation(KeyEncapsulationOperationInstance e) or + // Key Creation Operations + TKeyCreationOperation(KeyCreationOperationInstance e) or // Algorithms (e.g., SHA-256, AES) TCipherAlgorithm(CipherAlgorithmInstanceOrValueConsumer e) or TEllipticCurveAlgorithm(EllipticCurveAlgorithmInstance e) or @@ -662,7 +703,7 @@ module CryptographyBase Input> { * * If a child class defines this predicate as `none()`, no relationship will be reported. */ - string getSourceNodeRelationship() { result = "Source" } + string getSourceNodeRelationship() { result = "Source" } // TODO: revisit why this exists override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) @@ -737,6 +778,33 @@ module CryptographyBase Input> { override LocatableElement asElement() { result = instance } + /** + * Gets the algorithm or unknown source nodes consumed as an algorithm associated with this operation. + */ + NodeBase getAnAlgorithmOrUnknown() { + result = this.getAKnownAlgorithm() or + result = + this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAnUnknownSourceNode() + } + + /** + * Gets a known algorithm associated with this operation + */ + CipherAlgorithmNode getAKnownAlgorithm() { + result = + this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAKnownSourceNode() + } + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + // [KNOWN_OR_UNKNOWN] + edgeName = "Algorithm" and + if exists(this.getAnAlgorithmOrUnknown()) + then result = this.getAnAlgorithmOrUnknown() + else result = this + } + override predicate properties(string key, string value, Location location) { super.properties(key, value, location) or @@ -787,6 +855,16 @@ module CryptographyBase Input> { } } + final class KeyCreationOperationNode extends OperationNode, TKeyCreationOperation { + KeyCreationOperationInstance instance; + + KeyCreationOperationNode() { this = TKeyCreationOperation(instance) } + + override LocatableElement asElement() { result = instance } + + override string getInternalType() { result = instance.getKeyCreationTypeDescription() } + } + newtype TCipherOperationSubtype = TEncryptionMode() or TDecryptionMode() or @@ -867,6 +945,11 @@ module CryptographyBase Input> { result.asElement() = this.asElement().(CipherOperationInstance).getOutputArtifact() } + KeyArtifactNode getAKey() { + result.asElement() = + Input::dfn_to_element(this.asElement().(CipherOperationInstance).getKeyConsumer()) + } + override NodeBase getChild(string key) { result = super.getChild(key) or @@ -891,6 +974,10 @@ module CryptographyBase Input> { if exists(this.getAnOutputArtifact()) then result = this.getAnOutputArtifact() else result = this + or + // [KNOWN_OR_UNKNOWN] + key = "Key" and + if exists(this.getAKey()) then result = this.getAKey() else result = this } override predicate properties(string key, string value, Location location) { From b6956413626fd8e7493fe696797d3cb7d4c90084 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Thu, 20 Mar 2025 16:27:20 -0400 Subject: [PATCH 072/336] Add signature to cipher operation --- shared/cryptography/codeql/cryptography/Model.qll | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 2f5e2ca77faa..577993e7f63b 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -792,6 +792,7 @@ module CryptographyBase Input> { TDecryptionMode() or TWrapMode() or TUnwrapMode() or + TSignatureMode() or TUnknownCipherOperationMode() abstract class CipherOperationSubtype extends TCipherOperationSubtype { @@ -814,6 +815,10 @@ module CryptographyBase Input> { override string toString() { result = "Unwrap" } } + class SignatureSubtype extends CipherOperationSubtype, TSignatureMode { + override string toString() { result = "Sign" } + } + class UnknownCipherOperationSubtype extends CipherOperationSubtype, TUnknownCipherOperationMode { override string toString() { result = "Unknown" } } From fb7c0033981e04118ad06414a7b2028334a9af05 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Sat, 22 Mar 2025 08:01:03 +0100 Subject: [PATCH 073/336] Add initial MAC support for JCA, refactor hashes --- java/ql/lib/experimental/Quantum/JCA.qll | 374 +++++++++++++++--- java/ql/lib/experimental/Quantum/Language.qll | 71 ++-- .../codeql/cryptography/Model.qll | 353 +++++++++++++---- 3 files changed, 626 insertions(+), 172 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index e0e30f6d5106..eac400183b88 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -36,6 +36,50 @@ module JCAModel { ].toUpperCase()) } + bindingset[hash] + predicate hash_names(string hash) { + hash.toUpperCase() + .matches(["SHA-%", "SHA3-%", "BLAKE2b%", "BLAKE2s%", "MD5", "RIPEMD160", "Whirlpool"] + .toUpperCase()) + } + + bindingset[name] + Crypto::THashType hash_name_to_hash_type(string name, int digestLength) { + name = "SHA-1" and result instanceof Crypto::SHA1 and digestLength = 160 + or + name = ["SHA-256", "SHA-384", "SHA-512"] and + result instanceof Crypto::SHA2 and + digestLength = name.splitAt("-", 1).toInt() + or + name = ["SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512"] and + result instanceof Crypto::SHA3 and + digestLength = name.splitAt("-", 1).toInt() + or + ( + name.matches("BLAKE2b%") and + result instanceof Crypto::BLAKE2B + or + name = "BLAKE2s" and result instanceof Crypto::BLAKE2S + ) and + ( + if exists(name.indexOf("-")) + then name.splitAt("-", 1).toInt() = digestLength + else digestLength = 512 + ) + or + name = "MD5" and + result instanceof Crypto::MD5 and + digestLength = 128 + or + name = "RIPEMD160" and + result instanceof Crypto::RIPEMD160 and + digestLength = 160 + or + name = "Whirlpool" and + result instanceof Crypto::WHIRLPOOL and + digestLength = 512 // TODO: verify + } + /** * A `StringLiteral` in the `"ALG/MODE/PADDING"` or `"ALG"` format */ @@ -99,8 +143,63 @@ module JCAModel { * * TODO: Model the case of relying on a provider default, but alert on it as a bad practice. */ - class CipherStringLiteralAlgorithmInstance extends Crypto::CipherAlgorithmInstance, - Crypto::ModeOfOperationAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof CipherStringLiteral + class CipherStringLiteralPaddingAlgorithmInstance extends CipherStringLiteralAlgorithmInstance, + Crypto::PaddingAlgorithmInstance instanceof CipherStringLiteral + { + CipherStringLiteralPaddingAlgorithmInstance() { exists(super.getPadding()) } // TODO: provider defaults + + override string getRawPaddingAlgorithmName() { result = super.getPadding() } + + bindingset[name] + private predicate paddingToNameMappingKnown(Crypto::TPaddingType type, string name) { + type instanceof Crypto::NoPadding and name = "NOPADDING" + or + type instanceof Crypto::PKCS7 and name = ["PKCS5Padding", "PKCS7Padding"] // TODO: misnomer in the JCA? + or + type instanceof Crypto::OAEP and name.matches("OAEP%") // TODO: handle OAEPWith% + } + + override Crypto::TPaddingType getPaddingType() { + if this.paddingToNameMappingKnown(_, super.getPadding()) + then this.paddingToNameMappingKnown(result, super.getPadding()) + else result instanceof Crypto::OtherPadding + } + } + + class CipherStringLiteralModeAlgorithmInstance extends CipherStringLiteralPaddingAlgorithmInstance, + Crypto::ModeOfOperationAlgorithmInstance instanceof CipherStringLiteral + { + CipherStringLiteralModeAlgorithmInstance() { exists(super.getMode()) } // TODO: provider defaults + + override string getRawModeAlgorithmName() { result = super.getMode() } + + bindingset[name] + private predicate modeToNameMappingKnown(Crypto::TBlockCipherModeOperationType type, string name) { + type instanceof Crypto::ECB and name = "ECB" + or + type instanceof Crypto::CBC and name = "CBC" + or + type instanceof Crypto::GCM and name = "GCM" + or + type instanceof Crypto::CTR and name = "CTR" + or + type instanceof Crypto::XTS and name = "XTS" + or + type instanceof Crypto::CCM and name = "CCM" + or + type instanceof Crypto::SIV and name = "SIV" + or + type instanceof Crypto::OCB and name = "OCB" + } + + override Crypto::TBlockCipherModeOperationType getModeType() { + if this.modeToNameMappingKnown(_, super.getMode()) + then this.modeToNameMappingKnown(result, super.getMode()) + else result instanceof Crypto::OtherMode + } + } + + class CipherStringLiteralAlgorithmInstance extends Crypto::CipherAlgorithmInstance instanceof CipherStringLiteral { Crypto::AlgorithmValueConsumer consumer; @@ -111,14 +210,14 @@ module JCAModel { Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { - result = this and exists(this.getRawModeAlgorithmName()) // TODO: provider defaults + result = this // TODO: provider defaults } override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { - result = this and exists(this.getRawPaddingAlgorithmName()) // TODO: provider defaults + result = this // TODO: provider defaults } - override string getRawAlgorithmName() { result = super.getValue() } + override string getRawCipherAlgorithmName() { result = super.getValue() } override Crypto::TCipherType getCipherFamily() { if this.cipherNameMappingKnown(_, super.getAlgorithmName()) @@ -155,49 +254,43 @@ module JCAModel { name = "RSA" and type instanceof Crypto::RSA } + } - private predicate modeToNameMappingKnown(Crypto::TBlockCipherModeOperationType type, string name) { - type instanceof Crypto::ECB and name = "ECB" - or - type instanceof Crypto::CBC and name = "CBC" - or - type instanceof Crypto::GCM and name = "GCM" - or - type instanceof Crypto::CTR and name = "CTR" - or - type instanceof Crypto::XTS and name = "XTS" - or - type instanceof Crypto::CCM and name = "CCM" - or - type instanceof Crypto::SIV and name = "SIV" - or - type instanceof Crypto::OCB and name = "OCB" - } + bindingset[input] + predicate oaep_padding_string_components(string input, string hash, string mfg) { + exists(string regex | + regex = "OAEPWith(.*)And(.*)Padding" and + hash = input.regexpCapture(regex, 1) and + mfg = input.regexpCapture(regex, 2) + ) + } - override Crypto::TBlockCipherModeOperationType getModeType() { - if this.modeToNameMappingKnown(_, super.getMode()) - then this.modeToNameMappingKnown(result, super.getMode()) - else result instanceof Crypto::OtherMode + predicate oaep_padding_string_components_eval(string hash, string mfg) { + oaep_padding_string_components(any(CipherStringLiteral s).getPadding(), hash, mfg) + } + + class OAEPPaddingHashAlgorithmInstance extends OAEPPaddingAlgorithmInstance, + Crypto::HashAlgorithmInstance instanceof CipherStringLiteral + { + string hashName; + + OAEPPaddingHashAlgorithmInstance() { + oaep_padding_string_components(super.getPadding(), hashName, _) } - override string getRawModeAlgorithmName() { result = super.getMode() } + override string getRawHashAlgorithmName() { result = super.getPadding() } - override string getRawPaddingAlgorithmName() { result = super.getPadding() } + override Crypto::THashType getHashFamily() { result = hash_name_to_hash_type(hashName, _) } - bindingset[name] - private predicate paddingToNameMappingKnown(Crypto::TPaddingType type, string name) { - type instanceof Crypto::NoPadding and name = "NOPADDING" - or - type instanceof Crypto::PKCS7 and name = ["PKCS5Padding", "PKCS7Padding"] // TODO: misnomer in the JCA? - or - type instanceof Crypto::OAEP and name.matches("OAEP%") // TODO: handle OAEPWith% - } + override int getDigestLength() { exists(hash_name_to_hash_type(hashName, result)) } + } - override Crypto::TPaddingType getPaddingType() { - if this.paddingToNameMappingKnown(_, super.getPadding()) - then this.paddingToNameMappingKnown(result, super.getPadding()) - else result instanceof Crypto::OtherPadding - } + class OAEPPaddingAlgorithmInstance extends Crypto::OAEPPaddingAlgorithmInstance, + CipherStringLiteralPaddingAlgorithmInstance + { + override Crypto::HashAlgorithmInstance getOAEPEncodingHashAlgorithm() { result = this } + + override Crypto::HashAlgorithmInstance getMGF1HashAlgorithm() { none() } // TODO } /** @@ -412,11 +505,13 @@ module JCAModel { } // e.g., getPublic or getPrivate - class KeyPairGetKeyCall extends MethodCall { - KeyPairGetKeyCall() { + class KeyAdditionalFlowSteps extends MethodCall { + KeyAdditionalFlowSteps() { this.getCallee().hasQualifiedName("java.security", "KeyPair", "getPublic") or this.getCallee().hasQualifiedName("java.security", "KeyPair", "getPrivate") + or + this.getCallee().hasQualifiedName("java.security", "Key", "getEncoded") } DataFlow::Node getInputNode() { result.asExpr() = this.getQualifier() } @@ -435,7 +530,7 @@ module JCAModel { node2 = n.getOutputNode() ) or - exists(KeyPairGetKeyCall call | + exists(KeyAdditionalFlowSteps call | node1 = call.getInputNode() and node2 = call.getOutputNode() ) @@ -519,21 +614,12 @@ module JCAModel { override DataFlow::Node getInputNode() { result.asExpr() = this } } - class CipherOperationCallOutput extends CipherOutputArtifact { + class CipherOperationCallOutput extends Crypto::CipherOutputArtifactInstance { CipherOperationCallOutput() { this = any(CipherOperationCall call).getOutput() } override DataFlow::Node getOutputNode() { result.asExpr() = this } } - bindingset[hash] - predicate hash_names(string hash) { - hash.toUpperCase() - .matches([ - "SHA-1", "SHA-256", "SHA-384", "SHA-512", "SHA3-224", "SHA3-256", "SHA3-384", - "SHA3-512", "BLAKE2b", "BLAKE2s" - ].toUpperCase()) - } - // flow config from a known hash algorithm literal to MessageDigest.getInstance module KnownHashAlgorithmLiteralToMessageDigestConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { hash_names(src.asExpr().(StringLiteral).getValue()) } @@ -557,10 +643,14 @@ module JCAModel { MessageDigestAlgorithmValueConsumer getConsumer() { result = consumer } - override string getRawAlgorithmName() { result = this.(StringLiteral).getValue() } + override string getRawHashAlgorithmName() { result = this.(StringLiteral).getValue() } override Crypto::THashType getHashFamily() { - result = Crypto::OtherHashType() // TODO + result = hash_name_to_hash_type(this.getRawHashAlgorithmName(), _) + } + + override int getDigestLength() { + exists(hash_name_to_hash_type(this.getRawHashAlgorithmName(), result)) } } @@ -606,7 +696,7 @@ module JCAModel { module DigestGetInstanceToDigestFlow = DataFlow::Global; - class DigestArtifact extends DigestArtifactInstance { + class DigestArtifact extends Crypto::DigestArtifactInstance { DigestArtifact() { this = any(DigestCall call).getDigestArtifactOutput() } override DataFlow::Node getOutputNode() { result.asExpr() = this } @@ -659,7 +749,7 @@ module JCAModel { Expr getAlgorithmArg() { result = super.getArgument(0) } - predicate flowsTo(KeyGeneratorGenerateCall sink) { + predicate flowsToKeyGenerateCallQualifier(KeyGeneratorGenerateCall sink) { KeyGeneratorGetInstanceToGenerateFlow::flow(DataFlow::exprNode(this), DataFlow::exprNode(sink.(MethodCall).getQualifier())) } @@ -683,7 +773,7 @@ module JCAModel { override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { exists(KeyGeneratorGetInstanceCall getInstance | - getInstance.flowsTo(this) and result = getInstance.getAlgorithmArg() + getInstance.flowsToKeyGenerateCallQualifier(this) and result = getInstance.getAlgorithmArg() ) } @@ -691,4 +781,170 @@ module JCAModel { result = this.getAnAlgorithmValueConsumer().getAKnownAlgorithmSource() } } + + /* + * TODO: + * + * MAC Algorithms possible (JCA Default + BouncyCastle Extensions) + * + * Name Type Description + * --------------------------------------------------------------------------- + * "HmacMD5" HMAC HMAC with MD5 (not recommended) + * "HmacSHA1" HMAC HMAC with SHA-1 (not recommended) + * "HmacSHA224" HMAC HMAC with SHA-224 + * "HmacSHA256" HMAC HMAC with SHA-256 + * "HmacSHA384" HMAC HMAC with SHA-384 + * "HmacSHA512" HMAC HMAC with SHA-512 + * + * (BouncyCastle and Other Provider Extensions) + * "AESCMAC" CMAC Cipher-based MAC using AES + * "DESCMAC" CMAC CMAC with DES (legacy) + * "GMAC" GCM-based MAC Authenticates AAD only (GCM-style) + * "Poly1305" AEAD-style MAC Used with ChaCha20 + * "SipHash" Hash-based MAC Fast MAC for short inputs + * "BLAKE2BMAC" HMAC-style BLAKE2b MAC (cryptographic hash) + * "HmacRIPEMD160" HMAC HMAC with RIPEMD160 hash + */ + + bindingset[name] + predicate mac_names(string name) { + name.toUpperCase() + .matches([ + "HMAC%", "AESCMAC", "DESCMAC", "GMAC", "Poly1305", "SipHash", "BLAKE2BMAC", + "HMACRIPEMD160" + ].toUpperCase()) + } + + bindingset[name] + predicate mac_name_to_mac_type_known(Crypto::TMACType type, string name) { + type instanceof Crypto::THMAC and + name.toUpperCase().matches("HMAC%") + } + + module MACKnownAlgorithmToConsumerConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { mac_names(src.asExpr().(StringLiteral).getValue()) } + + predicate isSink(DataFlow::Node sink) { + exists(MACGetInstanceCall call | sink.asExpr() = call.getAlgorithmArg()) + } + } + + module MACKnownAlgorithmToConsumerFlow = DataFlow::Global; + + module MACGetInstanceToMACOperationFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof MACGetInstanceCall } + + predicate isSink(DataFlow::Node sink) { + exists(MACOperationCall call | sink.asExpr() = call.(MethodCall).getQualifier()) or + exists(MACInitCall call | sink.asExpr() = call.(MethodCall).getQualifier()) + } + } + + module MACGetInstanceToMACOperationFlow = + DataFlow::Global; + + module MACInitCallToMACOperationFlowConfig implements DataFlow::ConfigSig { + // TODO: use flow state with one config + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof MACInitCall } + + predicate isSink(DataFlow::Node sink) { + exists(MACOperationCall call | sink.asExpr() = call.(MethodCall).getQualifier()) + } + } + + module MACInitCallToMACOperationFlow = DataFlow::Global; + + class KnownMACAlgorithm extends Crypto::MACAlgorithmInstance instanceof StringLiteral { + MACGetInstanceAlgorithmValueConsumer consumer; + + KnownMACAlgorithm() { + mac_names(this.getValue()) and + MACKnownAlgorithmToConsumerFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) + } + + MACGetInstanceAlgorithmValueConsumer getConsumer() { result = consumer } + + override string getRawMACAlgorithmName() { result = super.getValue() } + + override Crypto::TMACType getMACType() { + if mac_name_to_mac_type_known(_, super.getValue()) + then mac_name_to_mac_type_known(result, super.getValue()) + else result instanceof Crypto::TOtherMACType + } + } + + class MACGetInstanceCall extends MethodCall { + MACGetInstanceCall() { this.getCallee().hasQualifiedName("javax.crypto", "Mac", "getInstance") } + + Expr getAlgorithmArg() { result = this.getArgument(0) } + + MACOperationCall getOperation() { + MACGetInstanceToMACOperationFlow::flow(DataFlow::exprNode(this), + DataFlow::exprNode(result.(MethodCall).getQualifier())) + } + + MACInitCall getInitCall() { + MACInitCallToMACOperationFlow::flow(DataFlow::exprNode(this), + DataFlow::exprNode(result.getQualifier())) + } + } + + class MACInitCall extends MethodCall { + MACInitCall() { this.getCallee().hasQualifiedName("javax.crypto", "Mac", "init") } + + Expr getKeyArg() { + result = this.getArgument(0) and this.getMethod().getParameterType(0).hasName("Key") + } + + MACOperationCall getOperation() { + MACInitCallToMACOperationFlow::flow(DataFlow::exprNode(this), + DataFlow::exprNode(result.(MethodCall).getQualifier())) + } + } + + class MACGetInstanceAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { + MACGetInstanceCall call; + + MACGetInstanceAlgorithmValueConsumer() { this = call.getAlgorithmArg() } + + override DataFlow::Node getInputNode() { result.asExpr() = this } + + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + exists(KnownMACAlgorithm l | l.getConsumer() = this and result = l) + } + } + + class MACOperationCall extends Crypto::MACOperationInstance instanceof MethodCall { + Expr output; + + MACOperationCall() { + super.getMethod().getDeclaringType().hasQualifiedName("javax.crypto", "Mac") and + ( + super.getMethod().hasStringSignature(["doFinal()", "doFinal(byte[])"]) and this = output + or + super.getMethod().hasStringSignature("doFinal(byte[], int)") and + this.getArgument(0) = output + ) + } + + override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { + exists(MACGetInstanceCall instantiation | + instantiation.getOperation() = this and result = instantiation.getAlgorithmArg() + ) + } + + override DataFlow::Node getKeyConsumer() { + exists(MACGetInstanceCall instantiation, MACInitCall initCall | + instantiation.getOperation() = this and + initCall.getOperation() = this and + instantiation.getInitCall() = initCall and + result.asExpr() = initCall.getKeyArg() + ) + } + + override DataFlow::Node getMessageConsumer() { + result.asExpr() = super.getArgument(0) and + super.getMethod().getParameterType(0).hasName("byte[]") + } + } } diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index e8bb052b6203..74edfec1d390 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -26,6 +26,10 @@ module CryptoInput implements InputSig { class UnknownLocation = UnknownDefaultLocation; + string locationToFileBaseNameAndLineNumberString(Location location) { + result = location.getFile().getBaseName() + ":" + location.getStartLine() + } + LocatableElement dfn_to_element(DataFlow::Node node) { result = node.asExpr() or result = node.asParameter() @@ -50,6 +54,20 @@ final class DefaultFlowSource = SourceNode; final class DefaultRemoteFlowSource = RemoteFlowSource; +class GenericUnreferencedParameterSource extends Crypto::GenericUnreferencedParameterSource { + GenericUnreferencedParameterSource() { + exists(Parameter p | this = p and not exists(p.getAnArgument())) + } + + override predicate flowsTo(Crypto::FlowAwareElement other) { + GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) + } + + override DataFlow::Node getOutputNode() { result.asParameter() = this } + + override string getAdditionalDescription() { result = this.toString() } +} + class GenericLocalDataSource extends Crypto::GenericLocalDataSource { GenericLocalDataSource() { any(DefaultFlowSource src | not src instanceof DefaultRemoteFlowSource).asExpr() = this @@ -76,20 +94,16 @@ class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { override string getAdditionalDescription() { result = this.toString() } } -/* - * class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource instanceof Literal { - * ConstantDataSource() { not this instanceof Crypto::KnownElement } - * - * override DataFlow::Node getOutputNode() { result.asExpr() = this } - * - * override predicate flowsTo(Crypto::FlowAwareElement other) { - * // TODO: separate config to avoid blowing up data-flow analysis - * GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) - * } - * - * override string getAdditionalDescription() { result = this.toString() } - * } - */ +class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource instanceof Literal { + override DataFlow::Node getOutputNode() { result.asExpr() = this } + + override predicate flowsTo(Crypto::FlowAwareElement other) { + // TODO: separate config to avoid blowing up data-flow analysis + GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) + } + + override string getAdditionalDescription() { result = this.toString() } +} /** * Random number generation, where each instance is modelled as the expression @@ -97,10 +111,6 @@ class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { */ abstract class RandomnessInstance extends Crypto::RandomNumberGenerationInstance { override DataFlow::Node getOutputNode() { result.asExpr() = this } - - override predicate flowsTo(Crypto::FlowAwareElement other) { - ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) - } } class SecureRandomnessInstance extends RandomnessInstance { @@ -115,17 +125,6 @@ class InsecureRandomnessInstance extends RandomnessInstance { InsecureRandomnessInstance() { exists(InsecureRandomnessSource node | this = node.asExpr()) } } -/** - * Output artifact flow logic - */ -abstract class DigestArtifactInstance extends Crypto::DigestArtifactInstance { - override predicate flowsTo(Crypto::FlowAwareElement other) { - ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) - } - - override predicate isConsumerArtifact() { none() } -} - /** * Artifact output to node input configuration */ @@ -137,14 +136,6 @@ abstract class AdditionalFlowInputStep extends DataFlow::Node { module ArtifactUniversalFlow = DataFlow::Global; -abstract class CipherOutputArtifact extends Crypto::CipherOutputArtifactInstance { - override predicate flowsTo(Crypto::FlowAwareElement other) { - ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) - } - - override predicate isConsumerArtifact() { none() } -} - /** * Generic data source to node input configuration */ @@ -167,6 +158,12 @@ module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { node1.(AdditionalFlowInputStep).getOutput() = node2 + or + exists(MethodCall m | + m.getMethod().hasQualifiedName("java.lang", "String", "getBytes") and + node1.asExpr() = m.getQualifier() and + node2.asExpr() = m + ) } } diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 2a006cd7f82d..0ed24452c0bd 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -21,6 +21,8 @@ signature module InputSig { class UnknownLocation instanceof Location; + string locationToFileBaseNameAndLineNumberString(Location location); + LocatableElement dfn_to_element(DataFlowNode node); predicate artifactOutputFlowsToGenericInput( @@ -70,7 +72,7 @@ module CryptographyBase Input> { or // CodeQL's DGML output does not include a location key = "Location" and - value = "demo" // node.getLocation().toString() + value = Input::locationToFileBaseNameAndLineNumberString(node.getLocation()) // node.getLocation().toString() or // Known unknown edges should be reported as properties rather than edges node = node.getChild(key) and @@ -146,13 +148,7 @@ module CryptographyBase Input> { /** * An element that represents a _known_ cryptographic algorithm. */ - abstract class AlgorithmInstance extends KnownElement { - /** - * Gets the raw name as it appears in source, e.g., "AES/CBC/PKCS7Padding". - * This name is not parsed or formatted. - */ - abstract string getRawAlgorithmName(); - } + abstract class AlgorithmInstance extends KnownElement { } /** * An element that represents an _unknown_ data-source with a non-statically determinable value. @@ -173,6 +169,10 @@ module CryptographyBase Input> { final override string getInternalType() { result = "ExternalCall" } // TODO: call target name or toString of source? } + abstract class GenericUnreferencedParameterSource extends GenericDataSourceInstance { + final override string getInternalType() { result = "Parameter" } // TODO: toString of source? + } + abstract class GenericRemoteDataSource extends GenericDataSourceInstance { final override string getInternalType() { result = "RemoteData" } // TODO: toString of source? } @@ -300,6 +300,17 @@ module CryptographyBase Input> { final override DataFlowNode getInputNode() { result = inputNode } } + final private class MACInputArtifactConsumer extends ArtifactConsumerAndInstance { + DataFlowNode inputNode; + + MACInputArtifactConsumer() { + exists(MACOperationInstance op | inputNode = op.getMessageConsumer()) and + this = Input::dfn_to_element(inputNode) + } + + final override DataFlowNode getInputNode() { result = inputNode } + } + // Output artifacts are determined solely by the element that produces them. // Implementation guidance: these *do* need to be defined generically at the language-level // in order for a flowsTo to be defined. At the per-modeling-instance level, extend that language-level class! @@ -307,6 +318,10 @@ module CryptographyBase Input> { override predicate isConsumerArtifact() { none() } override DataFlowNode getInputNode() { none() } + + final override predicate flowsTo(FlowAwareElement other) { + Input::artifactOutputFlowsToGenericInput(this.getOutputNode(), other.getInputNode()) + } } abstract class DigestArtifactInstance extends OutputArtifactInstance { } @@ -347,10 +362,6 @@ module CryptographyBase Input> { override KeyArtifactType getKeyType() { result = creator.getOutputKeyType() } override DataFlowNode getOutputNode() { result = creator.getOutputKeyArtifact() } - - override predicate flowsTo(FlowAwareElement other) { - Input::artifactOutputFlowsToGenericInput(this.getOutputNode(), other.getInputNode()) - } } final class KeyArtifactConsumer extends KeyArtifactInstance, ArtifactConsumerAndInstance { @@ -402,6 +413,12 @@ module CryptographyBase Input> { } abstract class CipherAlgorithmInstance extends AlgorithmInstance { + /** + * Gets the raw name as it appears in source, e.g., "AES/CBC/PKCS7Padding". + * This name is not parsed or formatted. + */ + abstract string getRawCipherAlgorithmName(); + /** * Gets the type of this cipher, e.g., "AES" or "ChaCha20". */ @@ -466,12 +483,51 @@ module CryptographyBase Input> { /** * Gets the hash algorithm used in this padding scheme. */ - abstract HashAlgorithmInstance getHashAlgorithm(); + abstract HashAlgorithmInstance getOAEPEncodingHashAlgorithm(); + + /** + * Gets the hash algorithm used by MGF1 (assumption: MGF1 is the only MGF used by OAEP) + */ + abstract HashAlgorithmInstance getMGF1HashAlgorithm(); + } + + newtype TMACType = + THMAC() or + TOtherMACType() + + abstract class MACAlgorithmInstance extends AlgorithmInstance { + /** + * Gets the type of this MAC algorithm, e.g., "HMAC" or "CMAC". + */ + abstract TMACType getMACType(); + + /** + * Gets the isolated name as it appears in source, e.g., "HMAC-SHA256" in "HMAC-SHA256/UnrelatedInformation". + * + * This name should not be parsed or formatted beyond isolating the raw MAC name if necessary. + */ + abstract string getRawMACAlgorithmName(); + } + + abstract class MACOperationInstance extends OperationInstance { + /** + * Gets the message input used in this operation. + */ + abstract DataFlowNode getMessageConsumer(); /** - * Gets the mask generation function used in this padding scheme. + * Gets the key used in this operation. */ - abstract HashAlgorithmInstance getMaskGenerationFunction(); + abstract DataFlowNode getKeyConsumer(); + } + + abstract class HMACAlgorithmInstance extends MACAlgorithmInstance { + HMACAlgorithmInstance() { this.getMACType() instanceof THMAC } + + /** + * Gets the hash algorithm used by this HMAC algorithm. + */ + abstract AlgorithmValueConsumer getHashAlgorithmValueConsumer(); } abstract class KeyEncapsulationOperationInstance extends OperationInstance { } @@ -489,6 +545,16 @@ module CryptographyBase Input> { * Gets the type of this digest algorithm, e.g., "SHA1", "SHA2", "MD5" etc. */ abstract THashType getHashFamily(); + + /** + * Gets the isolated name as it appears in source, e.g., "SHA-256" in "SHA-256/PKCS7Padding". + */ + abstract string getRawHashAlgorithmName(); + + /** + * Gets the length of the hash digest in bits. + */ + abstract int getDigestLength(); } abstract class KeyDerivationOperationInstance extends OperationInstance { } @@ -512,6 +578,10 @@ module CryptographyBase Input> { * Gets the key size of the key produced by this operation. */ string getKeySize() { none() } // TODO: punt, might need a generic value consumer? + + final KeyArtifactOutputInstance getKeyArtifactOutputInstance() { + result.getOutputNode() = this.getOutputKeyArtifact() + } } abstract class KeyGenerationOperationInstance extends KeyCreationOperationInstance { @@ -524,13 +594,18 @@ module CryptographyBase Input> { private signature class AlgorithmInstanceType instanceof AlgorithmInstance; - module AlgorithmInstanceOrValueConsumer { + private signature predicate isCandidateAVCSig(AlgorithmValueConsumer avc); + + module AlgorithmInstanceOrValueConsumer< + AlgorithmInstanceType Alg, isCandidateAVCSig/1 isCandidateAVC> + { class Union extends LocatableElement { Union() { this instanceof Alg or - this instanceof AlgorithmValueConsumer and - not exists(this.(AlgorithmValueConsumer).getASource()) + isCandidateAVC(this) and + not exists(this.(AlgorithmValueConsumer).getAKnownAlgorithmSource()) and + exists(this.(AlgorithmValueConsumer).getAnUnknownSource()) } Alg asAlg() { result = this } @@ -539,25 +614,43 @@ module CryptographyBase Input> { } } - class CipherAlgorithmInstanceOrValueConsumer = - AlgorithmInstanceOrValueConsumer::Union; + private predicate isHashAVC(AlgorithmValueConsumer avc) { + exists(HashOperationInstance op | op.getAnAlgorithmValueConsumer() = avc) or + exists(HMACAlgorithmInstance alg | avc = alg.getAConsumer()) + } + + private predicate isCipherAVC(AlgorithmValueConsumer avc) { + exists(CipherOperationInstance op | op.getAnAlgorithmValueConsumer() = avc) + } + + private predicate isMACAVC(AlgorithmValueConsumer avc) { + exists(MACOperationInstance op | op.getAnAlgorithmValueConsumer() = avc) + } + + final private class CipherAlgorithmInstanceOrValueConsumer = + AlgorithmInstanceOrValueConsumer::Union; + + final private class HashAlgorithmInstanceOrValueConsumer = + AlgorithmInstanceOrValueConsumer::Union; - class HashAlgorithmInstanceOrValueConsumer = - AlgorithmInstanceOrValueConsumer::Union; + private class MACAlgorithmInstanceOrValueConsumer = + AlgorithmInstanceOrValueConsumer::Union; - newtype TNode = + private newtype TNode = // Artifacts (data that is not an operation or algorithm, e.g., a key) TDigest(DigestArtifactInstance e) or TKey(KeyArtifactInstance e) or TNonce(NonceArtifactConsumer e) or TCipherInput(CipherInputArtifactConsumer e) or TCipherOutput(CipherOutputArtifactInstance e) or + TMACMessageInput(MACInputArtifactConsumer e) or TRandomNumberGeneration(RandomNumberGenerationInstance e) { e.flowsTo(_) } or // Operations (e.g., hashing, encryption) THashOperation(HashOperationInstance e) or TKeyDerivationOperation(KeyDerivationOperationInstance e) or TCipherOperation(CipherOperationInstance e) or TKeyEncapsulationOperation(KeyEncapsulationOperationInstance e) or + TMACOperation(MACOperationInstance e) or // Key Creation Operations TKeyCreationOperation(KeyCreationOperationInstance e) or // Algorithms (e.g., SHA-256, AES) @@ -566,6 +659,7 @@ module CryptographyBase Input> { THashAlgorithm(HashAlgorithmInstanceOrValueConsumer e) or TKeyDerivationAlgorithm(KeyDerivationAlgorithmInstance e) or TKeyEncapsulationAlgorithm(KeyEncapsulationAlgorithmInstance e) or + TMACAlgorithm(MACAlgorithmInstanceOrValueConsumer e) or // Non-standalone Algorithms (e.g., Mode, Padding) // TODO: need to rename this, as "mode" is getting reused in different contexts, be precise TModeOfOperationAlgorithm(ModeOfOperationAlgorithmInstance e) or @@ -738,6 +832,8 @@ module CryptographyBase Input> { final override string getInternalType() { result = "CipherOutput" } override LocatableElement asElement() { result = instance } + + override string getSourceNodeRelationship() { none() } } /** @@ -764,6 +860,8 @@ module CryptographyBase Input> { final override string getInternalType() { result = "RandomNumberGeneration" } override LocatableElement asElement() { result = instance } + + override string getSourceNodeRelationship() { none() } // TODO: seed? } /** @@ -813,6 +911,127 @@ module CryptographyBase Input> { value = instance.getKeyType().toString() and location = this.getLocation() } + + override string getSourceNodeRelationship() { + instance.isConsumerArtifact() and + result = "Source" + } + } + + final class MACMessageInputNode extends ArtifactNode, TMACMessageInput { + MACInputArtifactConsumer instance; + + MACMessageInputNode() { this = TMACMessageInput(instance) } + + final override string getInternalType() { result = "MACMessageInput" } + + override LocatableElement asElement() { result = instance } + } + + /** + * A MAC operation that produces a MAC value. + */ + final class MACOperationNode extends OperationNode, TMACOperation { + MACOperationInstance instance; + + MACOperationNode() { this = TMACOperation(instance) } + + final override string getInternalType() { result = "MACOperation" } + + override LocatableElement asElement() { result = instance } + + MACMessageInputNode getAMessage() { + result.asElement() = Input::dfn_to_element(instance.getMessageConsumer()) + } + + KeyArtifactNode getAKey() { + result.asElement() = Input::dfn_to_element(instance.getKeyConsumer()) + } + + /** + * Gets the algorithm or unknown source nodes consumed as an algorithm associated with this operation. + */ + NodeBase getAMACAlgorithmOrUnknown() { + result = this.getAKnownMACAlgorithm() or + result = + this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAnUnknownSourceNode() + } + + /** + * Gets a known algorithm associated with this operation + */ + MACAlgorithmNode getAKnownMACAlgorithm() { + result = + this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAKnownSourceNode() + } + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + // [KNOWN_OR_UNKNOWN] + edgeName = "Algorithm" and + if exists(this.getAMACAlgorithmOrUnknown()) + then result = this.getAMACAlgorithmOrUnknown() + else result = this + or + // [KNOWN_OR_UNKNOWN] + edgeName = "Message" and + if exists(this.getAMessage()) then result = this.getAMessage() else result = this + or + // [KNOWN_OR_UNKNOWN] + edgeName = "Key" and + if exists(this.getAKey()) then result = this.getAKey() else result = this + } + } + + /** + * A MAC algorithm, such as HMAC or CMAC. + */ + class MACAlgorithmNode extends AlgorithmNode, TMACAlgorithm { + MACAlgorithmInstanceOrValueConsumer instance; + + MACAlgorithmNode() { this = TMACAlgorithm(instance) } + + final override string getInternalType() { result = "MACAlgorithm" } + + override LocatableElement asElement() { result = instance } + + final override string getRawAlgorithmName() { + result = instance.asAlg().getRawMACAlgorithmName() + } + + TMACType getMACType() { result = instance.asAlg().getMACType() } + + bindingset[type] + final private predicate macToNameMapping(TMACType type, string name) { + type instanceof THMAC and + name = "HMAC" + or + type instanceof TOtherMACType and + name = this.getRawAlgorithmName() + } + + override string getAlgorithmName() { this.macToNameMapping(this.getMACType(), result) } + } + + final class HMACAlgorithmNode extends MACAlgorithmNode { + HMACAlgorithmInstance hmacInstance; + + HMACAlgorithmNode() { hmacInstance = instance.asAlg() } + + NodeBase getHashAlgorithmOrUnknown() { + result.asElement() = hmacInstance.getHashAlgorithmValueConsumer().getASource() + } + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + // [KNOWN_OR_UNKNOWN] + edgeName = "H" and + if exists(this.getHashAlgorithmOrUnknown()) + then result = this.getHashAlgorithmOrUnknown() + else result = this + } } /** @@ -863,6 +1082,21 @@ module CryptographyBase Input> { override LocatableElement asElement() { result = instance } override string getInternalType() { result = instance.getKeyCreationTypeDescription() } + + /** + * Gets the key artifact produced by this operation. + */ + KeyArtifactNode getOutputKeyArtifact() { + instance.getKeyArtifactOutputInstance() = result.asElement() + } + + override NodeBase getChild(string key) { + result = super.getChild(key) + or + // [ALWAYS_KNOWN] + key = "Output" and + result = this.getOutputKeyArtifact() + } } newtype TCipherOperationSubtype = @@ -1101,10 +1335,12 @@ module CryptographyBase Input> { OAEPPaddingAlgorithmNode() { this = TPaddingAlgorithm(instance) } - HashAlgorithmNode getHashAlgorithm() { result.asElement() = instance.getHashAlgorithm() } + HashAlgorithmNode getOAEPEncodingHashAlgorithm() { + result.asElement() = instance.getOAEPEncodingHashAlgorithm() + } - HashAlgorithmNode getMaskGenerationFunction() { - result.asElement() = instance.getMaskGenerationFunction() + HashAlgorithmNode getMGF1HashAlgorithm() { + result.asElement() = instance.getMGF1HashAlgorithm() } override NodeBase getChild(string edgeName) { @@ -1112,12 +1348,14 @@ module CryptographyBase Input> { or // [KNOWN_OR_UNKNOWN] edgeName = "MD" and - if exists(this.getHashAlgorithm()) then result = this.getHashAlgorithm() else result = this + if exists(this.getOAEPEncodingHashAlgorithm()) + then result = this.getOAEPEncodingHashAlgorithm() + else result = this or // [KNOWN_OR_UNKNOWN] - edgeName = "MGF" and - if exists(this.getMaskGenerationFunction()) - then result = this.getMaskGenerationFunction() + edgeName = "MGF1Hash" and + if exists(this.getMGF1HashAlgorithm()) + then result = this.getMGF1HashAlgorithm() else result = this } } @@ -1184,7 +1422,9 @@ module CryptographyBase Input> { this.cipherFamilyToNameAndStructure(this.getCipherFamily(), result, _) } - final override string getRawAlgorithmName() { result = instance.asAlg().getRawAlgorithmName() } + final override string getRawAlgorithmName() { + result = instance.asAlg().getRawCipherAlgorithmName() + } /** * Gets the key size of this cipher, e.g., "128" or "256". @@ -1379,7 +1619,7 @@ module CryptographyBase Input> { override LocatableElement asElement() { result = instance } - override string getRawAlgorithmName() { result = instance.asAlg().getRawAlgorithmName() } + override string getRawAlgorithmName() { result = instance.asAlg().getRawHashAlgorithmName() } final predicate hashTypeToNameMapping(THashType type, string name) { type instanceof BLAKE2B and name = "BLAKE2B" @@ -1416,58 +1656,19 @@ module CryptographyBase Input> { * * When modeling a new hashing algorithm, use this predicate to specify the type of the algorithm. */ - abstract THashType getHashType(); - - override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashType(), result) } - - /** - * Gets the digest size of SHA2 or SHA3 algorithms. - * - * This predicate does not need to hold for other algorithms, - * as the digest size is already known based on the algorithm itself. - * - * For `OtherHashType` algorithms where a digest size should be reported, `THashType` - * should be extended to explicitly model that algorithm. If the algorithm has variable - * or multiple digest size variants, a similar predicate to this one must be defined - * for that algorithm to report the digest size. - */ - abstract string getSHA2OrSHA3DigestSize(Location location); - - bindingset[type] - private string getTypeDigestSizeFixed(THashType type) { - type instanceof MD2 and result = "128" - or - type instanceof MD4 and result = "128" - or - type instanceof MD5 and result = "128" - or - type instanceof SHA1 and result = "160" - or - type instanceof RIPEMD160 and result = "160" - or - type instanceof WHIRLPOOL and result = "512" - } + THashType getHashFamily() { result = instance.asAlg().getHashFamily() } - bindingset[type] - private string getTypeDigestSize(THashType type, Location location) { - result = this.getTypeDigestSizeFixed(type) and location = this.getLocation() - or - type instanceof SHA2 and result = this.getSHA2OrSHA3DigestSize(location) - or - type instanceof SHA3 and result = this.getSHA2OrSHA3DigestSize(location) - } + override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashFamily(), result) } - string getDigestSize(Location location) { - result = this.getTypeDigestSize(this.getHashType(), location) - } + int getDigestLength() { result = instance.asAlg().getDigestLength() } final override predicate properties(string key, string value, Location location) { super.properties(key, value, location) or // [KNOWN_OR_UNKNOWN] key = "DigestSize" and - if exists(this.getDigestSize(location)) - then value = this.getDigestSize(location) + if exists(this.getDigestLength()) + then value = this.getDigestLength().toString() and location = this.getLocation() else ( value instanceof UnknownPropertyValue and location instanceof UnknownLocation ) From 9cd0340d21aa8e582da299bb0a1c0c981317eb59 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Wed, 26 Mar 2025 13:26:45 +0100 Subject: [PATCH 074/336] Remove rankdir=LR; from DOT output --- misc/scripts/cryptography/generate_cbom.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/misc/scripts/cryptography/generate_cbom.py b/misc/scripts/cryptography/generate_cbom.py index 07400d6cd6a3..fa4c2cb1d023 100644 --- a/misc/scripts/cryptography/generate_cbom.py +++ b/misc/scripts/cryptography/generate_cbom.py @@ -39,8 +39,7 @@ def convert_dgml_to_dot(dgml_file, dot_file): # Form dot element sequence body_l = ["digraph cbom {", - "node [shape=box];", - "rankdir=LR;" + "node [shape=box];" ] # Process nodes From bec69ca1061875679086c7624165ffb001cc4f59 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Wed, 26 Mar 2025 13:27:32 +0100 Subject: [PATCH 075/336] Refactor consumer and generic source model --- java/ql/lib/experimental/Quantum/JCA.qll | 239 +++- java/ql/lib/experimental/Quantum/Language.qll | 20 +- .../codeql/cryptography/Model.qll | 1089 ++++++++++------- 3 files changed, 859 insertions(+), 489 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index eac400183b88..5cff0129b721 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -1,5 +1,6 @@ import java import semmle.code.java.dataflow.DataFlow +import semmle.code.java.dataflow.TaintTracking import semmle.code.java.controlflow.Dominance module JCAModel { @@ -43,6 +44,22 @@ module JCAModel { .toUpperCase()) } + bindingset[kdf] + predicate kdf_names(string kdf) { + kdf.toUpperCase().matches(["PBKDF2With%", "PBEWith%"].toUpperCase()) + } + + bindingset[name] + Crypto::TKeyDerivationType kdf_name_to_kdf_type(string name, string withSubstring) { + name.matches("PBKDF2With%") and + result instanceof Crypto::PBKDF2 and + withSubstring = name.regexpCapture("PBKDF2With(.*)", 1) + or + name.matches("PBEWith%") and + result instanceof Crypto::PBES and + withSubstring = name.regexpCapture("PBEWith(.*)", 1) + } + bindingset[name] Crypto::THashType hash_name_to_hash_type(string name, int digestLength) { name = "SHA-1" and result instanceof Crypto::SHA1 and digestLength = 160 @@ -132,7 +149,7 @@ module JCAModel { } } - module AlgorithmStringToFetchFlow = DataFlow::Global; + module AlgorithmStringToFetchFlow = TaintTracking::Global; /** * Note: padding and a mode of operation will only exist when the padding / mode (*and its type*) are determinable. @@ -303,7 +320,7 @@ module JCAModel { CipherGetInstanceAlgorithmArg() { this = call.getAlgorithmArg() } - override DataFlow::Node getInputNode() { result.asExpr() = this } + override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } CipherStringLiteral getOrigin(string value) { AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(result), @@ -447,13 +464,15 @@ module JCAModel { override Crypto::CipherOperationSubtype getCipherOperationSubtype() { result = mode } - override DataFlow::Node getNonceConsumer() { + override Crypto::ConsumerInputDataFlowNode getNonceConsumer() { result.asExpr() = sink.getState().(InitializedCipherModeFlowState).getInitCall().getNonceArg() } - override DataFlow::Node getInputConsumer() { result = doFinalize.getMessageArg() } + override Crypto::ConsumerInputDataFlowNode getInputConsumer() { + result = doFinalize.getMessageArg() + } - override DataFlow::Node getKeyConsumer() { + override Crypto::ConsumerInputDataFlowNode getKeyConsumer() { result.asExpr() = sink.getState().(InitializedCipherModeFlowState).getInitCall().getKeyArg() } @@ -611,7 +630,7 @@ module JCAModel { class CipherInitCallKeyConsumer extends Crypto::ArtifactConsumer { CipherInitCallKeyConsumer() { this = any(CipherInitCall call).getKeyArg() } - override DataFlow::Node getInputNode() { result.asExpr() = this } + override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } } class CipherOperationCallOutput extends Crypto::CipherOutputArtifactInstance { @@ -659,7 +678,7 @@ module JCAModel { MessageDigestAlgorithmValueConsumer() { this = call.getAlgorithmArg() } - override DataFlow::Node getInputNode() { result.asExpr() = this } + override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { exists(KnownHashAlgorithm l | l.getConsumer() = this and result = l) @@ -719,7 +738,7 @@ module JCAModel { KeyGeneratorCallAlgorithmValueConsumer() { this = call.getAlgorithmArg() } - override DataFlow::Node getInputNode() { result.asExpr() = this } + override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { result.(CipherStringLiteralAlgorithmInstance).getConsumer() = this @@ -780,6 +799,10 @@ module JCAModel { Crypto::AlgorithmInstance getAKnownAlgorithm() { result = this.getAnAlgorithmValueConsumer().getAKnownAlgorithmSource() } + + override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { none() } + + override string getKeySizeFixed() { none() } } /* @@ -845,7 +868,9 @@ module JCAModel { module MACInitCallToMACOperationFlowConfig implements DataFlow::ConfigSig { // TODO: use flow state with one config - predicate isSource(DataFlow::Node src) { src.asExpr() instanceof MACInitCall } + predicate isSource(DataFlow::Node src) { + exists(MACInitCall init | src.asExpr() = init.getQualifier()) + } predicate isSink(DataFlow::Node sink) { exists(MACOperationCall call | sink.asExpr() = call.(MethodCall).getQualifier()) @@ -884,7 +909,7 @@ module JCAModel { } MACInitCall getInitCall() { - MACInitCallToMACOperationFlow::flow(DataFlow::exprNode(this), + MACGetInstanceToMACOperationFlow::flow(DataFlow::exprNode(this), DataFlow::exprNode(result.getQualifier())) } } @@ -897,7 +922,7 @@ module JCAModel { } MACOperationCall getOperation() { - MACInitCallToMACOperationFlow::flow(DataFlow::exprNode(this), + MACInitCallToMACOperationFlow::flow(DataFlow::exprNode(this.getQualifier()), DataFlow::exprNode(result.(MethodCall).getQualifier())) } } @@ -907,7 +932,7 @@ module JCAModel { MACGetInstanceAlgorithmValueConsumer() { this = call.getAlgorithmArg() } - override DataFlow::Node getInputNode() { result.asExpr() = this } + override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { exists(KnownMACAlgorithm l | l.getConsumer() = this and result = l) @@ -933,7 +958,7 @@ module JCAModel { ) } - override DataFlow::Node getKeyConsumer() { + override Crypto::ConsumerInputDataFlowNode getKeyConsumer() { exists(MACGetInstanceCall instantiation, MACInitCall initCall | instantiation.getOperation() = this and initCall.getOperation() = this and @@ -942,9 +967,195 @@ module JCAModel { ) } - override DataFlow::Node getMessageConsumer() { + override Crypto::ConsumerInputDataFlowNode getMessageConsumer() { result.asExpr() = super.getArgument(0) and super.getMethod().getParameterType(0).hasName("byte[]") } } + + module SecretKeyFactoryGetInstanceToGenerateSecretFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + exists(SecretKeyFactoryGetInstanceCall call | src.asExpr() = call) + } + + predicate isSink(DataFlow::Node sink) { + exists(SecretKeyFactoryGenerateSecretCall call | + sink.asExpr() = call.(MethodCall).getQualifier() + ) + } + } + + module PBEKeySpecInstantiationToGenerateSecretFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + exists(PBEKeySpecInstantiation call | src.asExpr() = call) + } + + predicate isSink(DataFlow::Node sink) { + exists(SecretKeyFactoryGenerateSecretCall call | sink.asExpr() = call.getKeySpecArg()) + } + } + + module KDFAlgorithmStringToGetInstanceConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { kdf_names(src.asExpr().(StringLiteral).getValue()) } + + predicate isSink(DataFlow::Node sink) { + exists(SecretKeyFactoryGetInstanceCall call | sink.asExpr() = call.getAlgorithmArg()) + } + } + + module SecretKeyFactoryGetInstanceToGenerateSecretFlow = + DataFlow::Global; + + module PBEKeySpecInstantiationToGenerateSecretFlow = + DataFlow::Global; + + module KDFAlgorithmStringToGetInstanceFlow = + DataFlow::Global; + + class PBEKeySpecInstantiation extends ClassInstanceExpr { + PBEKeySpecInstantiation() { + this.getConstructedType().hasQualifiedName("javax.crypto.spec", "PBEKeySpec") + } + + Expr getPasswordArg() { result = this.getArgument(0) } + + Expr getSaltArg() { result = this.getArgument(1) } + + Expr getIterationCountArg() { result = this.getArgument(2) } + + Expr getKeyLengthArg() { result = this.getArgument(3) } + } + + class SecretKeyFactoryGetInstanceCall extends MethodCall { + SecretKeyFactoryGetInstanceCall() { + this.getCallee().hasQualifiedName("javax.crypto", "SecretKeyFactory", "getInstance") + } + + Expr getAlgorithmArg() { result = this.getArgument(0) } + + SecretKeyFactoryGenerateSecretCall getOperation() { + SecretKeyFactoryGetInstanceToGenerateSecretFlow::flow(DataFlow::exprNode(this), + DataFlow::exprNode(result.(MethodCall).getQualifier())) + } + } + + class KDFAlgorithmStringLiteral extends Crypto::KeyDerivationAlgorithmInstance instanceof StringLiteral + { + SecretKeyFactoryKDFAlgorithmValueConsumer consumer; + + KDFAlgorithmStringLiteral() { + kdf_names(this.getValue()) and + KDFAlgorithmStringToGetInstanceFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) + } + + override string getRawKDFAlgorithmName() { result = super.getValue() } + + override Crypto::TKeyDerivationType getKDFType() { + result = kdf_name_to_kdf_type(super.getValue(), _) + } + + SecretKeyFactoryKDFAlgorithmValueConsumer getConsumer() { result = consumer } + } + + class PBKDF2AlgorithmStringLiteral extends KDFAlgorithmStringLiteral, + Crypto::PBKDF2AlgorithmInstance, Crypto::HMACAlgorithmInstance, Crypto::HashAlgorithmInstance, + Crypto::AlgorithmValueConsumer + { + PBKDF2AlgorithmStringLiteral() { super.getKDFType() instanceof Crypto::PBKDF2 } + + override Crypto::ConsumerInputDataFlowNode getInputNode() { none() } + + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { result = this } + + override Crypto::THashType getHashFamily() { + result = hash_name_to_hash_type(this.getRawHashAlgorithmName(), _) + } + + override int getDigestLength() { + exists(hash_name_to_hash_type(this.getRawHashAlgorithmName(), result)) + } + + override string getRawMACAlgorithmName() { + result = super.getRawKDFAlgorithmName().splitAt("PBKDF2With", 1) + } + + override string getRawHashAlgorithmName() { + result = super.getRawKDFAlgorithmName().splitAt("WithHmac", 1) + } + + override Crypto::TMACType getMACType() { result instanceof Crypto::THMAC } + + override Crypto::AlgorithmValueConsumer getHMACAlgorithmValueConsumer() { result = this } + + override Crypto::AlgorithmValueConsumer getHashAlgorithmValueConsumer() { result = this } + } + + class SecretKeyFactoryKDFAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer instanceof Expr + { + SecretKeyFactoryGetInstanceCall call; + + SecretKeyFactoryKDFAlgorithmValueConsumer() { this = call.getAlgorithmArg() } + + override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } + + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + exists(KDFAlgorithmStringLiteral l | l.getConsumer() = this and result = l) + } + + SecretKeyFactoryGetInstanceCall getInstantiation() { result = call } + } + + class SecretKeyFactoryGenerateSecretCall extends Crypto::KeyDerivationOperationInstance instanceof MethodCall + { + SecretKeyFactoryGenerateSecretCall() { + super.getCallee().hasQualifiedName("javax.crypto", "SecretKeyFactory", "generateSecret") + } + + Expr getKeySpecArg() { + result = super.getArgument(0) and + super.getMethod().getParameterType(0).hasName("KeySpec") + } + + PBEKeySpecInstantiation getInstantiation() { + PBEKeySpecInstantiationToGenerateSecretFlow::flow(DataFlow::exprNode(result), + DataFlow::exprNode(this.getKeySpecArg())) + } + + override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { + exists(SecretKeyFactoryGetInstanceCall instantiation | + instantiation.getOperation() = this and result = instantiation.getAlgorithmArg() + ) + } + + override Crypto::ConsumerInputDataFlowNode getSaltConsumer() { + result.asExpr() = this.getInstantiation().getSaltArg() + } + + override Crypto::ConsumerInputDataFlowNode getInputConsumer() { + result.asExpr() = this.getInstantiation().getPasswordArg() + } + + override Crypto::ConsumerInputDataFlowNode getIterationCountConsumer() { + result.asExpr() = this.getInstantiation().getIterationCountArg() + } + + override DataFlow::Node getOutputKeyArtifact() { + result.asExpr() = this and + super.getMethod().getReturnType().hasName("SecretKey") + } + + override Crypto::ConsumerInputDataFlowNode getOutputKeySizeConsumer() { + result.asExpr() = this.getInstantiation().getKeyLengthArg() + } + + override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { + result.asExpr() = this.getInstantiation().getKeyLengthArg() + } + + override string getKeySizeFixed() { none() } + + override string getOutputKeySizeFixed() { none() } + + override string getIterationCountFixed() { none() } + } } diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 74edfec1d390..1621e9436c42 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -94,7 +94,7 @@ class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { override string getAdditionalDescription() { result = this.toString() } } -class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource instanceof Literal { +class ConstantDataSource extends Crypto::GenericConstantSourceInstance instanceof Literal { override DataFlow::Node getOutputNode() { result.asExpr() = this } override predicate flowsTo(Crypto::FlowAwareElement other) { @@ -141,7 +141,7 @@ module ArtifactUniversalFlow = DataFlow::Global; */ module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { - source = any(Crypto::GenericDataSourceInstance i).getOutputNode() + source = any(Crypto::GenericSourceInstance i).getOutputNode() } predicate isSink(DataFlow::Node sink) { @@ -189,7 +189,21 @@ module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { } } -module GenericDataSourceUniversalFlow = DataFlow::Global; +module GenericDataSourceUniversalFlow = TaintTracking::Global; + +/* + * class LiteralOrGenericDataSource extends Element { + * DataFlow::Node node; + * + * LiteralOrGenericDataSource() { + * node = this.(Crypto::GenericSourceInstance).getOutputNode() or + * node.asExpr() = this.(Literal) + * } + * + * bindingset[other] + * predicate localFlowsTo(DataFlow::Node other) { DataFlow::localFlow(node, other) } + * } + */ // Import library-specific modeling import JCA diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index f20681923800..8252b5138600 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -37,6 +37,10 @@ module CryptographyBase Input> { final class DataFlowNode = Input::DataFlowNode; + class ConsumerInputDataFlowNode extends DataFlowNode { + ConsumerElement getConsumer() { result.getInputNode() = this } + } + final class UnknownPropertyValue extends string { UnknownPropertyValue() { this = "" } } @@ -49,7 +53,10 @@ module CryptographyBase Input> { ( if location = root or location instanceof UnknownLocation then parsed = value - else parsed = "(" + value + "," + location.toString() + ")" + else + parsed = + "(" + value + "," + Input::locationToFileBaseNameAndLineNumberString(location) + + ")" ) | parsed @@ -57,15 +64,28 @@ module CryptographyBase Input> { ) } + bindingset[node] + predicate node_as_property(GenericSourceNode node, string value, Location location) { + value = + node.getInternalType() + ":" + + node.asElement().(GenericSourceInstance).getAdditionalDescription() and + location = node.getLocation() + } + NodeBase getPassthroughNodeChild(NodeBase node) { result = node.getChild(_) } + predicate isPassthroughNodeWithSource(NodeBase node) { + isPassthroughNode(node) and + exists(node.asElement().(ArtifactConsumerAndInstance).getASource()) + } + predicate isPassthroughNode(NodeBase node) { node.asElement() instanceof ArtifactConsumerAndInstance } predicate nodes_graph_impl(NodeBase node, string key, string value) { not node.isExcludedFromGraph() and - not isPassthroughNode(node) and // TODO: punt to fix known unknowns for passthrough nodes + not isPassthroughNodeWithSource(node) and // TODO: punt to fix known unknowns for passthrough nodes ( key = "semmle.label" and value = node.toString() @@ -102,23 +122,23 @@ module CryptographyBase Input> { */ abstract class FlowAwareElement extends LocatableElement { /** - * Gets the output node for this artifact, which should usually be the same as `this`. + * Gets the output node for this element, which should usually be the same as `this`. */ abstract DataFlowNode getOutputNode(); /** - * Gets the input node for this artifact. + * Gets the input node for this element which takes in data. * * If `getInput` is implemented as `none()`, the artifact will not have inbound flow analysis. */ - abstract DataFlowNode getInputNode(); + abstract ConsumerInputDataFlowNode getInputNode(); /** - * Holds if this artifact flows to `other`. + * Holds if this element flows to `other`. * * This predicate should be defined generically per-language with library-specific extension support. - * The expected implementation is to perform flow analysis from this artifact's output to another artifact's input. - * The `other` argument should be one or more `ArtifactLocatableElement` that are sinks of the flow. + * The expected implementation is to perform flow analysis from this element's output to another element's input. + * The `other` argument should be one or more `FlowAwareElement`s that are sinks of the flow. * * If `flowsTo` is implemented as `none()`, the artifact will not have outbound flow analysis. */ @@ -128,8 +148,8 @@ module CryptographyBase Input> { /** * An element that represents a _known_ cryptographic asset with a determinable value OR an artifact. * - * CROSS PRODUCT WARNING: Do not model any *other* element that is a `FlowAwareElement` to the same - * instance in the database, as every other `KnownElement` will share that output artifact's flow. + * CROSS PRODUCT WARNING: Modeling any *other* element that is a `FlowAwareElement` to the same + * instance in the database will result in every `FlowAwareElement` sharing the output flow. */ abstract class KnownElement extends LocatableElement { final ConsumerElement getAConsumer() { result.getAKnownSource() = this } @@ -151,33 +171,71 @@ module CryptographyBase Input> { abstract class AlgorithmInstance extends KnownElement { } /** - * An element that represents an _unknown_ data-source with a non-statically determinable value. + * An element that represents a generic source of data. + * + * A generic source of data is either: + * 1. A value (e.g., a string or integer literal) *or* + * 1. An input for which a value cannot be determined (e.g., `argv`, file system reads, and web request headers) */ - abstract class GenericDataSourceInstance extends FlowAwareElement { - final override DataFlowNode getInputNode() { none() } + abstract class GenericSourceInstance extends FlowAwareElement { + final override ConsumerInputDataFlowNode getInputNode() { none() } abstract string getInternalType(); string getAdditionalDescription() { none() } } - abstract class GenericConstantOrAllocationSource extends GenericDataSourceInstance { - final override string getInternalType() { result = "ConstantData" } // TODO: toString of source? + /** + * An element that has a constant value and is a generic source of data. + */ + abstract class GenericValueSourceInstance extends GenericSourceInstance { } + + /** + * An element with a constant value, such as a literal. + */ + abstract class GenericConstantSourceInstance extends GenericValueSourceInstance { + final override string getInternalType() { result = "Constant" } + } + + /** + * An element representing statically or dynamically allocated data. + */ + abstract class GenericAllocationSourceInstance extends GenericValueSourceInstance { + final override string getInternalType() { result = "Allocation" } } - abstract class GenericExternalCallSource extends GenericDataSourceInstance { + /** + * An element that does not have a determinable constant value and is a generic source of data. + */ + abstract class GenericNoValueSourceInstance extends GenericSourceInstance { } + + /** + * A call to or an output argument of an external function with no definition. + */ + abstract class GenericExternalCallSource extends GenericNoValueSourceInstance { final override string getInternalType() { result = "ExternalCall" } // TODO: call target name or toString of source? } - abstract class GenericUnreferencedParameterSource extends GenericDataSourceInstance { + /** + * A parameter of a function which has no identifiable callsite. + */ + abstract class GenericUnreferencedParameterSource extends GenericNoValueSourceInstance { final override string getInternalType() { result = "Parameter" } // TODO: toString of source? } - abstract class GenericRemoteDataSource extends GenericDataSourceInstance { + /** + * A source of remote or external data, such as web request headers. + */ + abstract class GenericRemoteDataSource extends GenericNoValueSourceInstance { + // TODO: avoid duplication with the above types?.. perhaps define the above generically then override final override string getInternalType() { result = "RemoteData" } // TODO: toString of source? } - abstract class GenericLocalDataSource extends GenericDataSourceInstance { + /** + * A source of local or environment data, such as environment variables or a local filesystem. + */ + abstract class GenericLocalDataSource extends GenericNoValueSourceInstance { + // TODO: avoid duplication with the above types final override string getInternalType() { result = "LocalData" } // TODO: toString of source? } @@ -185,7 +243,7 @@ module CryptographyBase Input> { * An element that consumes _known_ or _unknown_ cryptographic assets. * * Note that known assets are to be modeled explicitly with the `getAKnownSource` predicate, whereas - * unknown assets are modeled implicitly via flow analysis from any `GenericDataSourceInstance` to this element. + * unknown assets are modeled implicitly via flow analysis from any `GenericSourceInstance` to this element. * * A consumer can consume multiple instances and types of assets at once, e.g., both a `PaddingAlgorithm` and `CipherAlgorithm`. */ @@ -196,23 +254,46 @@ module CryptographyBase Input> { override DataFlowNode getOutputNode() { none() } - // for internal use only - final GenericDataSourceInstance getAnUnknownSource() { + final GenericSourceInstance getAGenericSource() { result.flowsTo(this) and not result = this.getAKnownSource() } - final GenericSourceNode getAnUnknownSourceNode() { - result.asElement() = this.getAnUnknownSource() + final GenericSourceNode getAGenericSourceNode() { + result.asElement() = this.getAGenericSource() } final NodeBase getAKnownSourceNode() { result.asElement() = this.getAKnownSource() } final LocatableElement getASource() { - result = this.getAnUnknownSource() or + result = this.getAGenericSource() or result = this.getAKnownSource() } } + /** + * A generic value consumer, e.g. for inputs such as key length. + * TODO: type hints or per-instantiation type hint config on the source/sink pairs. + */ + final private class GenericValueConsumer extends ConsumerElement { + ConsumerInputDataFlowNode input; + + GenericValueConsumer() { + ( + exists(KeyCreationOperationInstance op | input = op.getKeySizeConsumer()) + or + exists(KeyDerivationOperationInstance op | + input = op.getIterationCountConsumer() or + input = op.getOutputKeySizeConsumer() + ) + ) and + this = Input::dfn_to_element(input) + } + + final override KnownElement getAKnownSource() { none() } + + final override ConsumerInputDataFlowNode getInputNode() { result = input } + } + abstract class AlgorithmValueConsumer extends ConsumerElement { /** * DO NOT USE. @@ -279,45 +360,49 @@ module CryptographyBase Input> { } final private class NonceArtifactConsumer extends ArtifactConsumerAndInstance { - DataFlowNode inputNode; + ConsumerInputDataFlowNode inputNode; NonceArtifactConsumer() { exists(CipherOperationInstance op | inputNode = op.getNonceConsumer()) and this = Input::dfn_to_element(inputNode) } - final override DataFlowNode getInputNode() { result = inputNode } + final override ConsumerInputDataFlowNode getInputNode() { result = inputNode } } - final private class CipherInputArtifactConsumer extends ArtifactConsumerAndInstance { - DataFlowNode inputNode; + final private class MessageArtifactConsumer extends ArtifactConsumerAndInstance { + ConsumerInputDataFlowNode inputNode; - CipherInputArtifactConsumer() { - exists(CipherOperationInstance op | inputNode = op.getInputConsumer()) and + MessageArtifactConsumer() { + ( + exists(CipherOperationInstance op | inputNode = op.getInputConsumer()) + or + exists(KeyDerivationOperationInstance op | inputNode = op.getInputConsumer()) + or + exists(MACOperationInstance op | inputNode = op.getMessageConsumer()) + ) and this = Input::dfn_to_element(inputNode) } - final override DataFlowNode getInputNode() { result = inputNode } + final override ConsumerInputDataFlowNode getInputNode() { result = inputNode } } - final private class MACInputArtifactConsumer extends ArtifactConsumerAndInstance { - DataFlowNode inputNode; + final private class SaltArtifactConsumer extends ArtifactConsumerAndInstance { + ConsumerInputDataFlowNode inputNode; - MACInputArtifactConsumer() { - exists(MACOperationInstance op | inputNode = op.getMessageConsumer()) and + SaltArtifactConsumer() { + exists(KeyDerivationOperationInstance op | inputNode = op.getSaltConsumer()) and this = Input::dfn_to_element(inputNode) } - final override DataFlowNode getInputNode() { result = inputNode } + final override ConsumerInputDataFlowNode getInputNode() { result = inputNode } } // Output artifacts are determined solely by the element that produces them. - // Implementation guidance: these *do* need to be defined generically at the language-level - // in order for a flowsTo to be defined. At the per-modeling-instance level, extend that language-level class! abstract class OutputArtifactInstance extends ArtifactInstance { override predicate isConsumerArtifact() { none() } - override DataFlowNode getInputNode() { none() } + override ConsumerInputDataFlowNode getInputNode() { none() } final override predicate flowsTo(FlowAwareElement other) { Input::artifactOutputFlowsToGenericInput(this.getOutputNode(), other.getInputNode()) @@ -365,17 +450,20 @@ module CryptographyBase Input> { } final class KeyArtifactConsumer extends KeyArtifactInstance, ArtifactConsumerAndInstance { - DataFlowNode inputNode; + ConsumerInputDataFlowNode inputNode; // TODO: key type hint? e.g. hint: private || public KeyArtifactConsumer() { - exists(CipherOperationInstance op | inputNode = op.getKeyConsumer()) and + ( + exists(CipherOperationInstance op | inputNode = op.getKeyConsumer()) or + exists(MACOperationInstance op | inputNode = op.getKeyConsumer()) + ) and this = Input::dfn_to_element(inputNode) } override KeyArtifactType getKeyType() { result instanceof TUnknownKeyType } - final override DataFlowNode getInputNode() { result = inputNode } + final override ConsumerInputDataFlowNode getInputNode() { result = inputNode } } /** @@ -390,17 +478,17 @@ module CryptographyBase Input> { /** * Gets the consumer of nonces/IVs associated with this cipher operation. */ - abstract DataFlowNode getNonceConsumer(); + abstract ConsumerInputDataFlowNode getNonceConsumer(); /** * Gets the consumer of plaintext or ciphertext input associated with this cipher operation. */ - abstract DataFlowNode getInputConsumer(); + abstract ConsumerInputDataFlowNode getInputConsumer(); /** * Gets the consumer of a key. */ - abstract DataFlowNode getKeyConsumer(); + abstract ConsumerInputDataFlowNode getKeyConsumer(); /** * Gets the output artifact of this cipher operation. @@ -513,12 +601,12 @@ module CryptographyBase Input> { /** * Gets the message input used in this operation. */ - abstract DataFlowNode getMessageConsumer(); + abstract ConsumerInputDataFlowNode getMessageConsumer(); /** * Gets the key used in this operation. */ - abstract DataFlowNode getKeyConsumer(); + abstract ConsumerInputDataFlowNode getKeyConsumer(); } abstract class HMACAlgorithmInstance extends MACAlgorithmInstance { @@ -557,10 +645,6 @@ module CryptographyBase Input> { abstract int getDigestLength(); } - abstract class KeyDerivationOperationInstance extends OperationInstance { } - - abstract class KeyDerivationAlgorithmInstance extends AlgorithmInstance { } - abstract private class KeyCreationOperationInstance extends OperationInstance { abstract string getKeyCreationTypeDescription(); @@ -574,16 +658,69 @@ module CryptographyBase Input> { */ abstract KeyArtifactType getOutputKeyType(); - /** - * Gets the key size of the key produced by this operation. - */ - string getKeySize() { none() } // TODO: punt, might need a generic value consumer? + // Defaults or fixed values + abstract string getKeySizeFixed(); + + // Consumer input nodes + abstract ConsumerInputDataFlowNode getKeySizeConsumer(); final KeyArtifactOutputInstance getKeyArtifactOutputInstance() { result.getOutputNode() = this.getOutputKeyArtifact() } } + abstract class KeyDerivationOperationInstance extends KeyCreationOperationInstance { + final override KeyArtifactType getOutputKeyType() { result instanceof TSymmetricKeyType } + + final override string getKeyCreationTypeDescription() { result = "KeyDerivation" } + + // Defaults or fixed values + abstract string getIterationCountFixed(); + + abstract string getOutputKeySizeFixed(); + + // Generic consumer input nodes + abstract ConsumerInputDataFlowNode getIterationCountConsumer(); + + abstract ConsumerInputDataFlowNode getOutputKeySizeConsumer(); + + // Artifact consumer input nodes + abstract ConsumerInputDataFlowNode getInputConsumer(); + + abstract ConsumerInputDataFlowNode getSaltConsumer(); + } + + newtype TKeyDerivationType = + PBKDF2() or + PBES() or + HKDF() or + ARGON2() or + OtherKeyDerivationType() + + abstract class KeyDerivationAlgorithmInstance extends AlgorithmInstance { + /** + * Gets the type of this key derivation algorithm, e.g., "PBKDF2" or "HKDF". + */ + abstract TKeyDerivationType getKDFType(); + + /** + * Gets the isolated name as it appears in source, e.g., "PBKDF2WithHmacSHA256" in "PBKDF2WithHmacSHA256/UnrelatedInformation". + */ + abstract string getRawKDFAlgorithmName(); + } + + abstract class PBKDF2AlgorithmInstance extends KeyDerivationAlgorithmInstance { + PBKDF2AlgorithmInstance() { this.getKDFType() instanceof PBKDF2 } + + /** + * Gets the HMAC algorithm used by this PBKDF2 algorithm. + * + * Note: Other PRFs are not supported, as most cryptographic libraries + * only support HMAC for PBKDF2's PRF input. + */ + abstract AlgorithmValueConsumer getHMACAlgorithmValueConsumer(); + } + abstract class KeyGenerationOperationInstance extends KeyCreationOperationInstance { final override string getKeyCreationTypeDescription() { result = "KeyGeneration" } } @@ -601,11 +738,13 @@ module CryptographyBase Input> { { class Union extends LocatableElement { Union() { + // Either an AlgorithmInstance this instanceof Alg or + // Or an AlgorithmValueConsumer with unknown sources and no known sources isCandidateAVC(this) and not exists(this.(AlgorithmValueConsumer).getAKnownAlgorithmSource()) and - exists(this.(AlgorithmValueConsumer).getAnUnknownSource()) + exists(this.(AlgorithmValueConsumer).getAGenericSource()) } Alg asAlg() { result = this } @@ -624,7 +763,12 @@ module CryptographyBase Input> { } private predicate isMACAVC(AlgorithmValueConsumer avc) { - exists(MACOperationInstance op | op.getAnAlgorithmValueConsumer() = avc) + exists(MACOperationInstance op | op.getAnAlgorithmValueConsumer() = avc) or + exists(PBKDF2AlgorithmInstance alg | avc = alg.getHMACAlgorithmValueConsumer()) + } + + private predicate isKeyDerivationAVC(AlgorithmValueConsumer avc) { + exists(KeyDerivationOperationInstance op | op.getAnAlgorithmValueConsumer() = avc) } final private class CipherAlgorithmInstanceOrValueConsumer = @@ -633,21 +777,24 @@ module CryptographyBase Input> { final private class HashAlgorithmInstanceOrValueConsumer = AlgorithmInstanceOrValueConsumer::Union; - private class MACAlgorithmInstanceOrValueConsumer = + final private class MACAlgorithmInstanceOrValueConsumer = AlgorithmInstanceOrValueConsumer::Union; + final private class KeyDerivationAlgorithmInstanceOrValueConsumer = + AlgorithmInstanceOrValueConsumer::Union; + private newtype TNode = // Artifacts (data that is not an operation or algorithm, e.g., a key) TDigest(DigestArtifactInstance e) or TKey(KeyArtifactInstance e) or - TNonce(NonceArtifactConsumer e) or - TCipherInput(CipherInputArtifactConsumer e) or TCipherOutput(CipherOutputArtifactInstance e) or - TMACMessageInput(MACInputArtifactConsumer e) or + // Input artifact nodes (synthetic, used to differentiate input as entities) + TNonceInput(NonceArtifactConsumer e) or + TMessageInput(MessageArtifactConsumer e) or + TSaltInput(SaltArtifactConsumer e) or TRandomNumberGeneration(RandomNumberGenerationInstance e) { e.flowsTo(_) } or // Operations (e.g., hashing, encryption) THashOperation(HashOperationInstance e) or - TKeyDerivationOperation(KeyDerivationOperationInstance e) or TCipherOperation(CipherOperationInstance e) or TKeyEncapsulationOperation(KeyEncapsulationOperationInstance e) or TMACOperation(MACOperationInstance e) or @@ -657,7 +804,7 @@ module CryptographyBase Input> { TCipherAlgorithm(CipherAlgorithmInstanceOrValueConsumer e) or TEllipticCurveAlgorithm(EllipticCurveAlgorithmInstance e) or THashAlgorithm(HashAlgorithmInstanceOrValueConsumer e) or - TKeyDerivationAlgorithm(KeyDerivationAlgorithmInstance e) or + TKeyDerivationAlgorithm(KeyDerivationAlgorithmInstanceOrValueConsumer e) or TKeyEncapsulationAlgorithm(KeyEncapsulationAlgorithmInstance e) or TMACAlgorithm(MACAlgorithmInstanceOrValueConsumer e) or // Non-standalone Algorithms (e.g., Mode, Padding) @@ -670,8 +817,15 @@ module CryptographyBase Input> { TKeyAgreementHybridCryptosystem(CipherAlgorithmInstance ka) or TAsymmetricEncryptionMacHybridCryptosystem(CipherAlgorithmInstance enc) or TPostQuantumHybridCryptosystem(CipherAlgorithmInstance enc) or - // Unknown source node - TGenericSourceNode(GenericDataSourceInstance e) { e.flowsTo(_) } + // Generic source nodes + TGenericSourceNode(GenericSourceInstance e) { + // An element modelled as a `GenericSourceInstance` can also be modelled as a `KnownElement` + // For example, a string literal "AES" could be a generic constant but also an algorithm instance. + // Only create generic nodes tied to instances which are not also a `KnownElement`. + not e instanceof KnownElement and + // Only create nodes for generic sources which flow to other elements + e.flowsTo(_) + } /** * The base class for all cryptographic assets, such as operations and algorithms. @@ -689,11 +843,12 @@ module CryptographyBase Input> { * * _Example 1_: A seed of a random number generation algorithm has meaning beyond its value, as its reuse in multiple * random number generation algorithms is more relevant than its underlying value. In contrast, a key size is only - * relevant to analysis in terms of its underlying value. Therefore, an RNG seed is a node; a key size is not. + * relevant to analysis in terms of its underlying value. Therefore, an RNG seed is a node; a key size is not. However, + * the key size might have a `GenericSourceNode` source, even if it itself is not a node. * * _Example 2_: A salt for a key derivation function *is* an `ArtifactNode`. * - * _Example 3_: The iteration count of a key derivation function is *not* a node. + * _Example 3_: The iteration count of a key derivation function is *not* a node, but it may link to a generic node. * * _Example 4_: A nonce for a cipher operation *is* an `ArtifactNode`. */ @@ -743,11 +898,32 @@ module CryptographyBase Input> { predicate isExcludedFromGraph() { none() } } + signature string getDefaultValueSig(); + + signature ConsumerInputDataFlowNode getConsumerSig(); + + signature class NodeBaseSig instanceof NodeBase; + + module PropertyOutput { + bindingset[root] + predicate get(NodeBase root, string value, Location location) { + if not exists(getDefault()) and not exists(getConsumer().getConsumer().getASource()) + then value instanceof UnknownPropertyValue and location instanceof UnknownLocation + else ( + if exists(getDefault()) + then + value = "Default:" + getDefault() and + location = root.getLocation() + else node_as_property(getConsumer().getConsumer().getAGenericSourceNode(), value, location) + ) + } + } + /** * A generic source node is a source of data that is not resolvable to a specific value or type. */ private class GenericSourceNode extends NodeBase, TGenericSourceNode { - GenericDataSourceInstance instance; + GenericSourceInstance instance; GenericSourceNode() { this = TGenericSourceNode(instance) } @@ -765,12 +941,74 @@ module CryptographyBase Input> { } override predicate isExcludedFromGraph() { - not exists(NodeBase other | not other = this and other.getChild(_) = this) + // Exclude generic source instances that are not child nodes of another node + not exists(NodeBase other | other != this and other.getChild(_) = this) } } class AssetNode = NodeBase; + /** + * A cryptographic operation, such as hashing or encryption. + */ + abstract class OperationNode extends AssetNode { + /** + * Holds if `node` is a potential candidate for a known algorithm node. + * This predicate should be used to restrict the set of candidate algorithm node types. + */ + abstract predicate isCandidateKnownAlgorithmNode(AlgorithmNode node); + + /** + * Gets the algorithm or generic source nodes consumed as an algorithm associated with this operation. + */ + NodeBase getAnAlgorithmOrGenericSource() { + result = this.getAKnownAlgorithm() or + result = + this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAGenericSourceNode() + } + + /** + * Gets a known algorithm associated with this operation, subject to `isCandidateKnownAlgorithmNode`. + */ + AlgorithmNode getAKnownAlgorithm() { + result = + this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAKnownSourceNode() and + this.isCandidateKnownAlgorithmNode(result) + } + + override NodeBase getChild(string edgeName) { + result = super.getChild(edgeName) + or + // [KNOWN_OR_UNKNOWN] + edgeName = "Algorithm" and + if exists(this.getAnAlgorithmOrGenericSource()) + then result = this.getAnAlgorithmOrGenericSource() + else result = this + } + } + + abstract class AlgorithmNode extends AssetNode { + /** + * Gets the name of this algorithm, e.g., "AES" or "SHA". + */ + abstract string getAlgorithmName(); + + /** + * Gets the raw name of this algorithm from source (no parsing or formatting) + */ + abstract string getRawAlgorithmName(); + + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + // [ONLY_KNOWN] + key = "Name" and value = this.getAlgorithmName() and location = this.getLocation() + or + // [ONLY_KNOWN] + key = "RawName" and value = this.getRawAlgorithmName() and location = this.getLocation() + } + } + /** * An artifact is an instance of data that is used in a cryptographic operation or produced by one. */ @@ -803,18 +1041,18 @@ module CryptographyBase Input> { result = super.getChild(edgeName) or // [KNOWN_OR_UNKNOWN] - edgeName = this.getSourceNodeRelationship() and // only holds if not set to none() + edgeName = this.getSourceNodeRelationship() and // TODO: only holds if not set to none().. revisit this if exists(this.getSourceNode()) then result = this.getSourceNode() else result = this } } /** - * A nonce or initialization vector + * A nonce or initialization vector input */ - final class NonceArtifactNode extends ArtifactNode, TNonce { + final class NonceArtifactNode extends ArtifactNode, TNonceInput { NonceArtifactConsumer instance; - NonceArtifactNode() { this = TNonce(instance) } + NonceArtifactNode() { this = TNonceInput(instance) } final override string getInternalType() { result = "Nonce" } @@ -822,31 +1060,44 @@ module CryptographyBase Input> { } /** - * Output text from a cipher operation + * A message or plaintext/ciphertext input */ - final class CipherOutputNode extends ArtifactNode, TCipherOutput { - CipherOutputArtifactInstance instance; + final class MessageArtifactNode extends ArtifactNode, TMessageInput { + MessageArtifactConsumer instance; - CipherOutputNode() { this = TCipherOutput(instance) } + MessageArtifactNode() { this = TMessageInput(instance) } - final override string getInternalType() { result = "CipherOutput" } + final override string getInternalType() { result = "Message" } override LocatableElement asElement() { result = instance } + } - override string getSourceNodeRelationship() { none() } + /** + * A salt input + */ + final class SaltArtifactNode extends ArtifactNode, TSaltInput { + SaltArtifactConsumer instance; + + SaltArtifactNode() { this = TSaltInput(instance) } + + final override string getInternalType() { result = "Salt" } + + override LocatableElement asElement() { result = instance } } /** - * Input text to a cipher operation + * Output text from a cipher operation */ - final class CipherInputNode extends ArtifactNode, TCipherInput { - CipherInputArtifactConsumer instance; + final class CipherOutputNode extends ArtifactNode, TCipherOutput { + CipherOutputArtifactInstance instance; - CipherInputNode() { this = TCipherInput(instance) } + CipherOutputNode() { this = TCipherOutput(instance) } - final override string getInternalType() { result = "CipherInput" } + final override string getInternalType() { result = "CipherOutput" } override LocatableElement asElement() { result = instance } + + override string getSourceNodeRelationship() { none() } } /** @@ -876,30 +1127,28 @@ module CryptographyBase Input> { override LocatableElement asElement() { result = instance } - /** - * Gets the algorithm or unknown source nodes consumed as an algorithm associated with this operation. - */ - NodeBase getAnAlgorithmOrUnknown() { + NodeBase getAKnownAlgorithmOrGenericSourceNode() { result = this.getAKnownAlgorithm() or result = - this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAnUnknownSourceNode() + instance + .(KeyCreationOperationInstance) + .getAnAlgorithmValueConsumer() + .getAGenericSourceNode() } - /** - * Gets a known algorithm associated with this operation - */ CipherAlgorithmNode getAKnownAlgorithm() { result = - this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAKnownSourceNode() + instance.(KeyCreationOperationInstance).getAnAlgorithmValueConsumer().getAKnownSourceNode() } override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) or - // [KNOWN_OR_UNKNOWN] + // [KNOWN_OR_UNKNOWN] - only if asymmetric edgeName = "Algorithm" and - if exists(this.getAnAlgorithmOrUnknown()) - then result = this.getAnAlgorithmOrUnknown() + instance.getKeyType() instanceof TAsymmetricKeyType and + if exists(this.getAKnownAlgorithmOrGenericSourceNode()) + then result = this.getAKnownAlgorithmOrGenericSourceNode() else result = this } @@ -918,16 +1167,44 @@ module CryptographyBase Input> { } } - final class MACMessageInputNode extends ArtifactNode, TMACMessageInput { - MACInputArtifactConsumer instance; + /** + * A digest produced by a hash operation. + */ + final class DigestArtifactNode extends ArtifactNode, TDigest { + DigestArtifactInstance instance; - MACMessageInputNode() { this = TMACMessageInput(instance) } + DigestArtifactNode() { this = TDigest(instance) } - final override string getInternalType() { result = "MACMessageInput" } + final override string getInternalType() { result = "Digest" } override LocatableElement asElement() { result = instance } } + abstract class KeyCreationOperationNode extends OperationNode, TKeyCreationOperation { + KeyCreationOperationInstance instance; + + KeyCreationOperationNode() { this = TKeyCreationOperation(instance) } + + override LocatableElement asElement() { result = instance } + + override string getInternalType() { result = instance.getKeyCreationTypeDescription() } + + /** + * Gets the key artifact produced by this operation. + */ + KeyArtifactNode getOutputKeyArtifact() { + instance.getKeyArtifactOutputInstance() = result.asElement() + } + + override NodeBase getChild(string key) { + result = super.getChild(key) + or + // [ALWAYS_KNOWN] + key = "Output" and + result = this.getOutputKeyArtifact() + } + } + /** * A MAC operation that produces a MAC value. */ @@ -940,41 +1217,20 @@ module CryptographyBase Input> { override LocatableElement asElement() { result = instance } - MACMessageInputNode getAMessage() { - result.asElement() = Input::dfn_to_element(instance.getMessageConsumer()) + override predicate isCandidateKnownAlgorithmNode(AlgorithmNode node) { + node instanceof MACAlgorithmNode } - KeyArtifactNode getAKey() { - result.asElement() = Input::dfn_to_element(instance.getKeyConsumer()) + MessageArtifactNode getAMessage() { + result.asElement() = instance.getMessageConsumer().getConsumer() } - /** - * Gets the algorithm or unknown source nodes consumed as an algorithm associated with this operation. - */ - NodeBase getAMACAlgorithmOrUnknown() { - result = this.getAKnownMACAlgorithm() or - result = - this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAnUnknownSourceNode() - } - - /** - * Gets a known algorithm associated with this operation - */ - MACAlgorithmNode getAKnownMACAlgorithm() { - result = - this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAKnownSourceNode() - } + KeyArtifactNode getAKey() { result.asElement() = instance.getKeyConsumer().getConsumer() } override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) or // [KNOWN_OR_UNKNOWN] - edgeName = "Algorithm" and - if exists(this.getAMACAlgorithmOrUnknown()) - then result = this.getAMACAlgorithmOrUnknown() - else result = this - or - // [KNOWN_OR_UNKNOWN] edgeName = "Message" and if exists(this.getAMessage()) then result = this.getAMessage() else result = this or @@ -1006,9 +1262,6 @@ module CryptographyBase Input> { final private predicate macToNameMapping(TMACType type, string name) { type instanceof THMAC and name = "HMAC" - or - type instanceof TOtherMACType and - name = this.getRawAlgorithmName() } override string getAlgorithmName() { this.macToNameMapping(this.getMACType(), result) } @@ -1034,70 +1287,253 @@ module CryptographyBase Input> { } } - /** - * A digest produced by a hash operation. - */ - final class DigestArtifactNode extends ArtifactNode, TDigest { - DigestArtifactInstance instance; + class KeyGenerationOperationNode extends KeyCreationOperationNode { + KeyGenerationOperationInstance keyGenInstance; - DigestArtifactNode() { this = TDigest(instance) } + KeyGenerationOperationNode() { keyGenInstance = instance } - final override string getInternalType() { result = "Digest" } + override predicate isCandidateKnownAlgorithmNode(AlgorithmNode node) { + node instanceof CipherAlgorithmNode + } - override LocatableElement asElement() { result = instance } + override NodeBase getChild(string key) { + result = super.getChild(key) + or + // [ALWAYS_KNOWN] + key = "Output" and + result = this.getOutputKeyArtifact() + } } - /** - * A cryptographic operation, such as hashing or encryption. - */ - abstract class OperationNode extends AssetNode { } + class KeyDerivationOperationNode extends KeyCreationOperationNode { + KeyDerivationOperationInstance kdfInstance; - abstract class AlgorithmNode extends AssetNode { - /** - * Gets the name of this algorithm, e.g., "AES" or "SHA". - */ - abstract string getAlgorithmName(); + KeyDerivationOperationNode() { kdfInstance = instance } - /** - * Gets the raw name of this algorithm from source (no parsing or formatting) - */ - abstract string getRawAlgorithmName(); + MessageArtifactNode getInput() { + result.asElement() = kdfInstance.getInputConsumer().getConsumer() + } + + SaltArtifactNode getSalt() { + result.asElement().(SaltArtifactConsumer).getInputNode() = kdfInstance.getSaltConsumer() + } + + GenericSourceNode getIterationCount() { + result.asElement() = kdfInstance.getIterationCountConsumer().getConsumer().getAGenericSource() + } + + GenericSourceNode getOutputKeySize() { + result.asElement() = kdfInstance.getOutputKeySizeConsumer().getConsumer().getAGenericSource() + } + + override predicate isCandidateKnownAlgorithmNode(AlgorithmNode node) { + node instanceof KeyDerivationAlgorithmNode + } + + override NodeBase getChild(string key) { + result = super.getChild(key) + or + // [KNOWN_OR_UNKNOWN] + key = "Input" and + if exists(this.getInput()) then result = this.getInput() else result = this + or + // [KNOWN_OR_UNKNOWN] + key = "Salt" and + if exists(this.getSalt()) then result = this.getSalt() else result = this + } override predicate properties(string key, string value, Location location) { super.properties(key, value, location) or // [ONLY_KNOWN] - key = "Name" and value = this.getAlgorithmName() and location = this.getLocation() + key = "DefaultIterations" and + value = kdfInstance.getIterationCountFixed() and + location = this.getLocation() or // [ONLY_KNOWN] - key = "RawName" and value = this.getRawAlgorithmName() and location = this.getLocation() + key = "DefaultKeySize" and + value = kdfInstance.getKeySizeFixed() and + location = this.getLocation() + or + // [ONLY_KNOWN] - TODO: refactor for known unknowns + key = "Iterations" and + node_as_property(this.getIterationCount(), value, location) + or + // [ONLY_KNOWN] - TODO: refactor for known unknowns + key = "KeySize" and + node_as_property(this.getOutputKeySize(), value, location) } } - final class KeyCreationOperationNode extends OperationNode, TKeyCreationOperation { - KeyCreationOperationInstance instance; + class KeyDerivationAlgorithmNode extends AlgorithmNode, TKeyDerivationAlgorithm { + KeyDerivationAlgorithmInstanceOrValueConsumer instance; - KeyCreationOperationNode() { this = TKeyCreationOperation(instance) } + KeyDerivationAlgorithmNode() { this = TKeyDerivationAlgorithm(instance) } + + final override string getInternalType() { result = "KeyDerivationAlgorithm" } override LocatableElement asElement() { result = instance } - override string getInternalType() { result = instance.getKeyCreationTypeDescription() } + final override string getRawAlgorithmName() { + result = instance.asAlg().getRawKDFAlgorithmName() + } - /** - * Gets the key artifact produced by this operation. - */ - KeyArtifactNode getOutputKeyArtifact() { - instance.getKeyArtifactOutputInstance() = result.asElement() + final override string getAlgorithmName() { result = this.getRawAlgorithmName() } + } + + /** + * PBKDF2 key derivation function + */ + class PBKDF2AlgorithmNode extends KeyDerivationAlgorithmNode { + PBKDF2AlgorithmInstance pbkdf2Instance; + + PBKDF2AlgorithmNode() { pbkdf2Instance = instance.asAlg() } + + HMACAlgorithmNode getHMACAlgorithm() { + result.asElement() = pbkdf2Instance.getHMACAlgorithmValueConsumer().getASource() } override NodeBase getChild(string key) { result = super.getChild(key) or - // [ALWAYS_KNOWN] - key = "Output" and - result = this.getOutputKeyArtifact() - } - } + // [KNOWN_OR_UNKNOWN] + key = "PRF" and + if exists(this.getHMACAlgorithm()) then result = this.getHMACAlgorithm() else result = this + } + } + + // /** + // * PKCS12KDF key derivation function + // */ + // abstract class PKCS12KDF extends KeyDerivationWithDigestParameterNode { + // override string getAlgorithmName() { result = "PKCS12KDF" } + // /** + // * Gets the iteration count of this key derivation algorithm. + // */ + // abstract string getIterationCount(Location location); + // /** + // * Gets the raw ID argument specifying the intended use of the derived key. + // * + // * The intended use is defined in RFC 7292, appendix B.3, as follows: + // * + // * This standard specifies 3 different values for the ID byte mentioned above: + // * + // * 1. If ID=1, then the pseudorandom bits being produced are to be used + // * as key material for performing encryption or decryption. + // * + // * 2. If ID=2, then the pseudorandom bits being produced are to be used + // * as an IV (Initial Value) for encryption or decryption. + // * + // * 3. If ID=3, then the pseudorandom bits being produced are to be used + // * as an integrity key for MACing. + // */ + // abstract string getIDByte(Location location); + // override predicate properties(string key, string value, Location location) { + // super.properties(key, value, location) + // or + // ( + // // [KNOWN_OR_UNKNOWN] + // key = "Iterations" and + // if exists(this.getIterationCount(location)) + // then value = this.getIterationCount(location) + // else ( + // value instanceof UnknownPropertyValue and location instanceof UnknownLocation + // ) + // ) + // or + // ( + // // [KNOWN_OR_UNKNOWN] + // key = "IdByte" and + // if exists(this.getIDByte(location)) + // then value = this.getIDByte(location) + // else ( + // value instanceof UnknownPropertyValue and location instanceof UnknownLocation + // ) + // ) + // } + // } + // /** + // * scrypt key derivation function + // */ + // abstract class SCRYPT extends KeyDerivationAlgorithmNode { + // final override string getAlgorithmName() { result = "scrypt" } + // /** + // * Gets the iteration count (`N`) argument + // */ + // abstract string get_N(Location location); + // /** + // * Gets the block size (`r`) argument + // */ + // abstract string get_r(Location location); + // /** + // * Gets the parallelization factor (`p`) argument + // */ + // abstract string get_p(Location location); + // /** + // * Gets the derived key length argument + // */ + // abstract string getDerivedKeyLength(Location location); + // override predicate properties(string key, string value, Location location) { + // super.properties(key, value, location) + // or + // ( + // // [KNOWN_OR_UNKNOWN] + // key = "N" and + // if exists(this.get_N(location)) + // then value = this.get_N(location) + // else ( + // value instanceof UnknownPropertyValue and location instanceof UnknownLocation + // ) + // ) + // or + // ( + // // [KNOWN_OR_UNKNOWN] + // key = "r" and + // if exists(this.get_r(location)) + // then value = this.get_r(location) + // else ( + // value instanceof UnknownPropertyValue and location instanceof UnknownLocation + // ) + // ) + // or + // ( + // // [KNOWN_OR_UNKNOWN] + // key = "p" and + // if exists(this.get_p(location)) + // then value = this.get_p(location) + // else ( + // value instanceof UnknownPropertyValue and location instanceof UnknownLocation + // ) + // ) + // or + // ( + // // [KNOWN_OR_UNKNOWN] + // key = "KeyLength" and + // if exists(this.getDerivedKeyLength(location)) + // then value = this.getDerivedKeyLength(location) + // else ( + // value instanceof UnknownPropertyValue and location instanceof UnknownLocation + // ) + // ) + // } + // } + /* + * TODO: + * + * Rule: No newtype representing a type of algorithm should be modelled with multiple interfaces + * + * Example 1: HKDF and PKCS12KDF are both key derivation algorithms. + * However, PKCS12KDF also has a property: the iteration count. + * + * If we have HKDF and PKCS12KDF under TKeyDerivationType, + * someone modelling a library might try to make a generic identification of both of those algorithms. + * + * They will therefore not use the specialized type for PKCS12KDF, + * meaning "from PKCS12KDF algo select algo" will have no results. + * + * Example 2: Each type below represents a common family of elliptic curves, with a shared interface, i.e., + * predicates for library modellers to implement as well as the properties and edges reported. + */ newtype TCipherOperationSubtype = TEncryptionMode() or @@ -1149,56 +1585,28 @@ module CryptographyBase Input> { override string getInternalType() { result = "CipherOperation" } - /** - * Gets the algorithm or unknown source nodes consumed as an algorithm associated with this operation. - */ - NodeBase getACipherAlgorithmOrUnknown() { - result = this.getAKnownCipherAlgorithm() or - result = - this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAnUnknownSourceNode() - } - - /** - * Gets a known algorithm associated with this operation - */ - CipherAlgorithmNode getAKnownCipherAlgorithm() { - result = - this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAKnownSourceNode() + override predicate isCandidateKnownAlgorithmNode(AlgorithmNode node) { + node instanceof CipherAlgorithmNode } CipherOperationSubtype getCipherOperationSubtype() { result = instance.getCipherOperationSubtype() } - NonceArtifactNode getANonce() { - result.asElement() = - Input::dfn_to_element(this.asElement().(CipherOperationInstance).getNonceConsumer()) - } + NonceArtifactNode getANonce() { result.asElement() = instance.getNonceConsumer().getConsumer() } - CipherInputNode getAnInputArtifact() { - result.asElement() = - Input::dfn_to_element(this.asElement().(CipherOperationInstance).getInputConsumer()) + MessageArtifactNode getAnInputArtifact() { + result.asElement() = instance.getInputConsumer().getConsumer() } - CipherOutputNode getAnOutputArtifact() { - result.asElement() = this.asElement().(CipherOperationInstance).getOutputArtifact() - } + CipherOutputNode getAnOutputArtifact() { result.asElement() = instance.getOutputArtifact() } - KeyArtifactNode getAKey() { - result.asElement() = - Input::dfn_to_element(this.asElement().(CipherOperationInstance).getKeyConsumer()) - } + KeyArtifactNode getAKey() { result.asElement() = instance.getKeyConsumer().getConsumer() } override NodeBase getChild(string key) { result = super.getChild(key) or // [KNOWN_OR_UNKNOWN] - key = "Algorithm" and - if exists(this.getACipherAlgorithmOrUnknown()) - then result = this.getACipherAlgorithmOrUnknown() - else result = this - or - // [KNOWN_OR_UNKNOWN] key = "Nonce" and if exists(this.getANonce()) then result = this.getANonce() else result = this or @@ -1286,8 +1694,6 @@ module CryptographyBase Input> { type instanceof CFB and name = "CFB" or type instanceof OFB and name = "OFB" - or - type instanceof OtherMode and name = this.getRawAlgorithmName() } override string getAlgorithmName() { this.modeToNameMapping(this.getModeType(), result) } @@ -1326,8 +1732,6 @@ module CryptographyBase Input> { type instanceof NoPadding and name = "NoPadding" or type instanceof OAEP and name = "OAEP" - or - type instanceof OtherPadding and name = this.getRawAlgorithmName() } override string getAlgorithmName() { this.paddingToNameMapping(this.getPaddingType(), result) } @@ -1500,7 +1904,7 @@ module CryptographyBase Input> { type instanceof SM4 and name = "SM4" and s = Block() or type instanceof OtherCipherType and - name = this.getRawAlgorithmName() and + name instanceof UnknownPropertyValue and s = UnknownCipherStructureType() } @@ -1555,41 +1959,20 @@ module CryptographyBase Input> { override LocatableElement asElement() { result = instance } - /** - * Gets the algorithm or unknown source nodes consumed as an algorithm associated with this operation. - */ - NodeBase getAHashAlgorithmOrUnknown() { - result = this.getAKnownHashAlgorithm() or - result = - this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAnUnknownSourceNode() - } - - /** - * Gets a known algorithm associated with this operation - */ - HashAlgorithmNode getAKnownHashAlgorithm() { - result = - this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAKnownSourceNode() + override predicate isCandidateKnownAlgorithmNode(AlgorithmNode node) { + node instanceof HashAlgorithmNode } /** * Gets the output digest node */ - DigestArtifactNode getDigest() { - result.asElement() = this.asElement().(HashOperationInstance).getDigestArtifact() - } + DigestArtifactNode getDigest() { result.asElement() = instance.getDigestArtifact() } - override NodeBase getChild(string edgeName) { - result = super.getChild(edgeName) - or - // [KNOWN_OR_UNKNOWN] - edgeName = "Algorithm" and - if exists(this.getAHashAlgorithmOrUnknown()) - then result = this.getAHashAlgorithmOrUnknown() - else result = this + override NodeBase getChild(string key) { + result = super.getChild(key) or // [KNOWN_OR_UNKNOWN] - edgeName = "Digest" and + key = "Digest" and if exists(this.getDigest()) then result = this.getDigest() else result = this } } @@ -1652,8 +2035,6 @@ module CryptographyBase Input> { type instanceof SM3 and name = "SM3" or type instanceof WHIRLPOOL and name = "WHIRLPOOL" - or - type instanceof OtherHashType and name = this.getRawAlgorithmName() } /** @@ -1680,242 +2061,6 @@ module CryptographyBase Input> { } } - /** - * An operation that derives one or more keys from an input value. - */ - abstract class KeyDerivationOperationNode extends OperationNode, TKeyDerivationOperation { - final override Location getLocation() { - exists(LocatableElement le | this = TKeyDerivationOperation(le) and result = le.getLocation()) - } - - override string getInternalType() { result = "KeyDerivationOperation" } - } - - /** - * An algorithm that derives one or more keys from an input value. - * - * Only use this class to model UNKNOWN key derivation algorithms. - * - * For known algorithms, use the specialized classes, e.g., `HKDF` and `PKCS12KDF`. - */ - abstract class KeyDerivationAlgorithmNode extends AlgorithmNode, TKeyDerivationAlgorithm { - final override Location getLocation() { - exists(LocatableElement le | this = TKeyDerivationAlgorithm(le) and result = le.getLocation()) - } - - override string getInternalType() { result = "KeyDerivationAlgorithm" } - - override string getAlgorithmName() { result = this.getRawAlgorithmName() } - } - - /** - * An algorithm that derives one or more keys from an input value, using a configurable digest algorithm. - */ - abstract private class KeyDerivationWithDigestParameterNode extends KeyDerivationAlgorithmNode { - abstract HashAlgorithmNode getHashAlgorithm(); - - override NodeBase getChild(string edgeName) { - result = super.getChild(edgeName) - or - ( - // [KNOWN_OR_UNKNOWN] - edgeName = "Uses" and - if exists(this.getHashAlgorithm()) then result = this.getHashAlgorithm() else result = this - ) - } - } - - /** - * HKDF key derivation function - */ - abstract class HKDFNode extends KeyDerivationWithDigestParameterNode { - final override string getAlgorithmName() { result = "HKDF" } - } - - /** - * PBKDF2 key derivation function - */ - abstract class PBKDF2Node extends KeyDerivationWithDigestParameterNode { - final override string getAlgorithmName() { result = "PBKDF2" } - - /** - * Gets the iteration count of this key derivation algorithm. - */ - abstract string getIterationCount(Location location); - - /** - * Gets the bit-length of the derived key. - */ - abstract string getKeyLength(Location location); - - override predicate properties(string key, string value, Location location) { - super.properties(key, value, location) - or - ( - // [KNOWN_OR_UNKNOWN] - key = "Iterations" and - if exists(this.getIterationCount(location)) - then value = this.getIterationCount(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - ) - or - ( - // [KNOWN_OR_UNKNOWN] - key = "KeyLength" and - if exists(this.getKeyLength(location)) - then value = this.getKeyLength(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - ) - } - } - - /** - * PKCS12KDF key derivation function - */ - abstract class PKCS12KDF extends KeyDerivationWithDigestParameterNode { - override string getAlgorithmName() { result = "PKCS12KDF" } - - /** - * Gets the iteration count of this key derivation algorithm. - */ - abstract string getIterationCount(Location location); - - /** - * Gets the raw ID argument specifying the intended use of the derived key. - * - * The intended use is defined in RFC 7292, appendix B.3, as follows: - * - * This standard specifies 3 different values for the ID byte mentioned above: - * - * 1. If ID=1, then the pseudorandom bits being produced are to be used - * as key material for performing encryption or decryption. - * - * 2. If ID=2, then the pseudorandom bits being produced are to be used - * as an IV (Initial Value) for encryption or decryption. - * - * 3. If ID=3, then the pseudorandom bits being produced are to be used - * as an integrity key for MACing. - */ - abstract string getIDByte(Location location); - - override predicate properties(string key, string value, Location location) { - super.properties(key, value, location) - or - ( - // [KNOWN_OR_UNKNOWN] - key = "Iterations" and - if exists(this.getIterationCount(location)) - then value = this.getIterationCount(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - ) - or - ( - // [KNOWN_OR_UNKNOWN] - key = "IdByte" and - if exists(this.getIDByte(location)) - then value = this.getIDByte(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - ) - } - } - - /** - * scrypt key derivation function - */ - abstract class SCRYPT extends KeyDerivationAlgorithmNode { - final override string getAlgorithmName() { result = "scrypt" } - - /** - * Gets the iteration count (`N`) argument - */ - abstract string get_N(Location location); - - /** - * Gets the block size (`r`) argument - */ - abstract string get_r(Location location); - - /** - * Gets the parallelization factor (`p`) argument - */ - abstract string get_p(Location location); - - /** - * Gets the derived key length argument - */ - abstract string getDerivedKeyLength(Location location); - - override predicate properties(string key, string value, Location location) { - super.properties(key, value, location) - or - ( - // [KNOWN_OR_UNKNOWN] - key = "N" and - if exists(this.get_N(location)) - then value = this.get_N(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - ) - or - ( - // [KNOWN_OR_UNKNOWN] - key = "r" and - if exists(this.get_r(location)) - then value = this.get_r(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - ) - or - ( - // [KNOWN_OR_UNKNOWN] - key = "p" and - if exists(this.get_p(location)) - then value = this.get_p(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - ) - or - ( - // [KNOWN_OR_UNKNOWN] - key = "KeyLength" and - if exists(this.getDerivedKeyLength(location)) - then value = this.getDerivedKeyLength(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - ) - } - } - - /* - * TODO: - * - * Rule: No newtype representing a type of algorithm should be modelled with multiple interfaces - * - * Example 1: HKDF and PKCS12KDF are both key derivation algorithms. - * However, PKCS12KDF also has a property: the iteration count. - * - * If we have HKDF and PKCS12KDF under TKeyDerivationType, - * someone modelling a library might try to make a generic identification of both of those algorithms. - * - * They will therefore not use the specialized type for PKCS12KDF, - * meaning "from PKCS12KDF algo select algo" will have no results. - * - * Example 2: Each type below represents a common family of elliptic curves, with a shared interface, i.e., - * predicates for library modellers to implement as well as the properties and edges reported. - */ - /** * Elliptic curve algorithms */ From ac96649a02e78549110002fd42dc240bbd1279aa Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 1 Apr 2025 16:15:49 -0400 Subject: [PATCH 076/336] Misc. modifications to support elliptic curves and hooking them up to keygeneration. --- java/ql/lib/experimental/Quantum/JCA.qll | 239 ++++++++++++++---- java/ql/lib/experimental/Quantum/Language.qll | 8 + .../codeql/cryptography/Model.qll | 172 +++++++++++-- 3 files changed, 340 insertions(+), 79 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 5cff0129b721..bce4b117522e 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -6,6 +6,10 @@ import semmle.code.java.controlflow.Dominance module JCAModel { import Language + abstract class JCAAlgorithmInstance extends Crypto::AlgorithmInstance { + abstract Crypto::AlgorithmValueConsumer getConsumer(); + } + // TODO: Verify that the PBEWith% case works correctly bindingset[algo] predicate cipher_names(string algo) { @@ -49,6 +53,9 @@ module JCAModel { kdf.toUpperCase().matches(["PBKDF2With%", "PBEWith%"].toUpperCase()) } + bindingset[name] + predicate elliptic_curve_names(string name) { Crypto::isEllipticCurveAlgorithmName(name) } + bindingset[name] Crypto::TKeyDerivationType kdf_name_to_kdf_type(string name, string withSubstring) { name.matches("PBKDF2With%") and @@ -110,6 +117,12 @@ module JCAModel { string getPadding() { result = this.getValue().splitAt("/", 2) } } + class EllipticCurveStringLiteral extends StringLiteral { + EllipticCurveStringLiteral() { elliptic_curve_names(this.getValue()) } + + string getStandardEllipticCurveName() { result = this.getValue() } + } + class CipherGetInstanceCall extends Call { CipherGetInstanceCall() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "getInstance") @@ -139,9 +152,9 @@ module JCAModel { } /** - * Data-flow configuration modelling flow from a cipher string literal to a `CipherGetInstanceCall` argument. + * Data-flow configuration modelling flow from a cipher string literal to a value consumer argument. */ - private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { + private module CipherAlgorithmStringToFetchConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof CipherStringLiteral } predicate isSink(DataFlow::Node sink) { @@ -149,7 +162,22 @@ module JCAModel { } } - module AlgorithmStringToFetchFlow = TaintTracking::Global; + module CipherAlgorithmStringToFetchFlow = + TaintTracking::Global; + + /** + * Data-flow configuration modelling flow from a cipher string literal to a value consumer argument. + */ + private module EllipticCurveAlgorithmStringToFetchConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof EllipticCurveStringLiteral } + + predicate isSink(DataFlow::Node sink) { + exists(Crypto::AlgorithmValueConsumer consumer | sink = consumer.getInputNode()) + } + } + + module EllipticCurveAlgorithmStringToFetchFlow = + TaintTracking::Global; /** * Note: padding and a mode of operation will only exist when the padding / mode (*and its type*) are determinable. @@ -160,8 +188,8 @@ module JCAModel { * * TODO: Model the case of relying on a provider default, but alert on it as a bad practice. */ - class CipherStringLiteralPaddingAlgorithmInstance extends CipherStringLiteralAlgorithmInstance, - Crypto::PaddingAlgorithmInstance instanceof CipherStringLiteral + class CipherStringLiteralPaddingAlgorithmInstance extends JCAAlgorithmInstance, + CipherStringLiteralAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof CipherStringLiteral { CipherStringLiteralPaddingAlgorithmInstance() { exists(super.getPadding()) } // TODO: provider defaults @@ -183,8 +211,8 @@ module JCAModel { } } - class CipherStringLiteralModeAlgorithmInstance extends CipherStringLiteralPaddingAlgorithmInstance, - Crypto::ModeOfOperationAlgorithmInstance instanceof CipherStringLiteral + class CipherStringLiteralModeAlgorithmInstance extends JCAAlgorithmInstance, + CipherStringLiteralPaddingAlgorithmInstance, Crypto::ModeOfOperationAlgorithmInstance instanceof CipherStringLiteral { CipherStringLiteralModeAlgorithmInstance() { exists(super.getMode()) } // TODO: provider defaults @@ -216,15 +244,141 @@ module JCAModel { } } - class CipherStringLiteralAlgorithmInstance extends Crypto::CipherAlgorithmInstance instanceof CipherStringLiteral + class KeyGeneratorGetInstanceCall extends MethodCall { + KeyGeneratorGetInstanceCall() { + this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "getInstance") + or + this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "getInstance") + } + + Expr getAlgorithmArg() { result = super.getArgument(0) } + } + + // For general elliptic curves, getInstance("EC") is used + // and java.security.spec.ECGenParameterSpec("") is what sets the specific curve. + // The result of ECGenParameterSpec is passed to KeyPairGenerator.initialize + // If the curve is not specified, the default is used. + // We would trace the use of this inside a KeyPairGenerator.initialize + class ECGenParameterSpecCall extends ClassInstanceExpr { + ECGenParameterSpecCall() { + this.(ClassInstanceExpr) + .getConstructedType() + .hasQualifiedName("java.security.spec", "ECGenParameterSpec") + } + + Expr getAlgorithmArg() { result = super.getArgument(0) } + + KeyPairGeneratorInitializeCall getInitializeConsumerCall() { + exists(DataFlow::Node sink | + ECGenParameterSpecCallToInitializeFlow::flow(DataFlow::exprNode(this), sink) and + result.getAnArgument() = sink.asExpr() + ) + } + } + + abstract class KeyGenAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { + // abstract predicate flowsToKeyGenerateCallQualifier(KeyGeneratorGenerateCall sink); + abstract DataFlow::Node getResultNode(); + } + + class KeyPairGeneratorInitializeCall extends MethodCall { + KeyPairGeneratorInitializeCall() { + this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "initialize") + } + + Expr getKeyArg() { + result = this.getArgument(0) and + result.getType() instanceof IntegralType + } + } + + private module ECGenParameterSpecCallToInitializeConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ECGenParameterSpecCall } + + predicate isSink(DataFlow::Node sink) { + exists(KeyPairGeneratorInitializeCall c | c.getAnArgument() = sink.asExpr()) + } + } + + module ECGenParameterSpecCallToInitializeFlow = + DataFlow::Global; + + class ECGenParameterSpecAlgorithmValueConsumer extends KeyGenAlgorithmValueConsumer { + ECGenParameterSpecCall call; + + ECGenParameterSpecAlgorithmValueConsumer() { this = call.getAlgorithmArg() } + + override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } + + override DataFlow::Node getResultNode() { + // Traversing to the initialilzer directly and calling this the 'result' + // to simplify the trace. In theory you would trace from the call + // through the initializer, but we already have a trace to the initializer + // so using this instead of altering/creating data flow configs. + call.getInitializeConsumerCall().getQualifier() = result.asExpr() + } + + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + result.(JCAAlgorithmInstance).getConsumer() = this + } + } + + class KeyGeneratorGetInstanceAlgorithmValueConsumer extends KeyGenAlgorithmValueConsumer { + KeyGeneratorGetInstanceCall call; + + KeyGeneratorGetInstanceAlgorithmValueConsumer() { this = call.getAlgorithmArg() } + + override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } + + override DataFlow::Node getResultNode() { result.asExpr() = call } + + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + // The source is any instance whose consumer is this + result.(JCAAlgorithmInstance).getConsumer() = this + } + } + + class EllipticCurveStringLiteralAlgorithmInstance extends JCAAlgorithmInstance, + Crypto::EllipticCurveAlgorithmInstance instanceof StringLiteral + { + Crypto::AlgorithmValueConsumer consumer; + + EllipticCurveStringLiteralAlgorithmInstance() { + // Trace a known elliptic curve algorithm string literal to a key gen consumer + EllipticCurveAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), + consumer.getInputNode()) + } + + override Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } + + override string getRawEllipticCurveAlgorithmName() { result = super.getValue() } + + override string getStandardCurveName() { result = this.getRawEllipticCurveAlgorithmName() } + + override Crypto::TEllipticCurveType getEllipticCurveFamily() { + Crypto::isEllipticCurveAlgorithm(this.getRawEllipticCurveAlgorithmName(), _, result) + } + + override string getKeySize() { + exists(int keySize | + Crypto::isEllipticCurveAlgorithm(this.getRawEllipticCurveAlgorithmName(), keySize, _) and + result = keySize.toString() + ) + } + } + + class CipherStringLiteralAlgorithmInstance extends JCAAlgorithmInstance, + Crypto::CipherAlgorithmInstance instanceof CipherStringLiteral { + // NOTE: this consumer is generic, but cipher algorithms can be consumed + // by getInstance as well as key generation Crypto::AlgorithmValueConsumer consumer; CipherStringLiteralAlgorithmInstance() { - AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) + CipherAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) } - Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } + override Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { result = this // TODO: provider defaults @@ -302,8 +456,8 @@ module JCAModel { override int getDigestLength() { exists(hash_name_to_hash_type(hashName, result)) } } - class OAEPPaddingAlgorithmInstance extends Crypto::OAEPPaddingAlgorithmInstance, - CipherStringLiteralPaddingAlgorithmInstance + class OAEPPaddingAlgorithmInstance extends JCAAlgorithmInstance, + Crypto::OAEPPaddingAlgorithmInstance, CipherStringLiteralPaddingAlgorithmInstance { override Crypto::HashAlgorithmInstance getOAEPEncodingHashAlgorithm() { result = this } @@ -323,7 +477,7 @@ module JCAModel { override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } CipherStringLiteral getOrigin(string value) { - AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(result), + CipherAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(result), DataFlow::exprNode(this.(Expr).getAChildExpr*())) and value = result.getValue() } @@ -651,7 +805,8 @@ module JCAModel { module KnownHashAlgorithmLiteralToMessageDigestFlow = DataFlow::Global; - class KnownHashAlgorithm extends Crypto::HashAlgorithmInstance instanceof StringLiteral { + class KnownHashAlgorithm extends JCAAlgorithmInstance, Crypto::HashAlgorithmInstance instanceof StringLiteral + { MessageDigestAlgorithmValueConsumer consumer; KnownHashAlgorithm() { @@ -660,7 +815,7 @@ module JCAModel { consumer.getInputNode()) } - MessageDigestAlgorithmValueConsumer getConsumer() { result = consumer } + override MessageDigestAlgorithmValueConsumer getConsumer() { result = consumer } override string getRawHashAlgorithmName() { result = this.(StringLiteral).getValue() } @@ -733,22 +888,10 @@ module JCAModel { } } - class KeyGeneratorCallAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { - KeyGeneratorGetInstanceCall call; - - KeyGeneratorCallAlgorithmValueConsumer() { this = call.getAlgorithmArg() } - - override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } - - override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { - result.(CipherStringLiteralAlgorithmInstance).getConsumer() = this - } - } - // flow from instance created by getInstance to generateKey - module KeyGeneratorGetInstanceToGenerateConfig implements DataFlow::ConfigSig { + module KeyGeneratorAlgValueConsumerToGenerateConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { - exists(KeyGeneratorGetInstanceCall call | src.asExpr() = call) + exists(KeyGenAlgorithmValueConsumer consumer | consumer.getResultNode() = src) } predicate isSink(DataFlow::Node sink) { @@ -756,23 +899,8 @@ module JCAModel { } } - module KeyGeneratorGetInstanceToGenerateFlow = - DataFlow::Global; - - class KeyGeneratorGetInstanceCall extends MethodCall { - KeyGeneratorGetInstanceCall() { - this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "getInstance") - or - this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "getInstance") - } - - Expr getAlgorithmArg() { result = super.getArgument(0) } - - predicate flowsToKeyGenerateCallQualifier(KeyGeneratorGenerateCall sink) { - KeyGeneratorGetInstanceToGenerateFlow::flow(DataFlow::exprNode(this), - DataFlow::exprNode(sink.(MethodCall).getQualifier())) - } - } + module KeyGeneratorAlgValueConsumerToGenerateFlow = + DataFlow::Global; class KeyGeneratorGenerateCall extends Crypto::KeyGenerationOperationInstance instanceof MethodCall { @@ -791,8 +919,10 @@ module JCAModel { override Crypto::KeyArtifactType getOutputKeyType() { result = type } override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { - exists(KeyGeneratorGetInstanceCall getInstance | - getInstance.flowsToKeyGenerateCallQualifier(this) and result = getInstance.getAlgorithmArg() + exists(KeyGenAlgorithmValueConsumer consumer | + KeyGeneratorAlgValueConsumerToGenerateFlow::flow(consumer.getResultNode(), + DataFlow::exprNode(this.(Call).getQualifier())) and + result = consumer ) } @@ -879,7 +1009,8 @@ module JCAModel { module MACInitCallToMACOperationFlow = DataFlow::Global; - class KnownMACAlgorithm extends Crypto::MACAlgorithmInstance instanceof StringLiteral { + class KnownMACAlgorithm extends JCAAlgorithmInstance, Crypto::MACAlgorithmInstance instanceof StringLiteral + { MACGetInstanceAlgorithmValueConsumer consumer; KnownMACAlgorithm() { @@ -887,7 +1018,7 @@ module JCAModel { MACKnownAlgorithmToConsumerFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) } - MACGetInstanceAlgorithmValueConsumer getConsumer() { result = consumer } + override MACGetInstanceAlgorithmValueConsumer getConsumer() { result = consumer } override string getRawMACAlgorithmName() { result = super.getValue() } @@ -1039,7 +1170,8 @@ module JCAModel { } } - class KDFAlgorithmStringLiteral extends Crypto::KeyDerivationAlgorithmInstance instanceof StringLiteral + class KDFAlgorithmStringLiteral extends JCAAlgorithmInstance, + Crypto::KeyDerivationAlgorithmInstance instanceof StringLiteral { SecretKeyFactoryKDFAlgorithmValueConsumer consumer; @@ -1054,10 +1186,10 @@ module JCAModel { result = kdf_name_to_kdf_type(super.getValue(), _) } - SecretKeyFactoryKDFAlgorithmValueConsumer getConsumer() { result = consumer } + override SecretKeyFactoryKDFAlgorithmValueConsumer getConsumer() { result = consumer } } - class PBKDF2AlgorithmStringLiteral extends KDFAlgorithmStringLiteral, + class PBKDF2AlgorithmStringLiteral extends JCAAlgorithmInstance, KDFAlgorithmStringLiteral, Crypto::PBKDF2AlgorithmInstance, Crypto::HMACAlgorithmInstance, Crypto::HashAlgorithmInstance, Crypto::AlgorithmValueConsumer { @@ -1158,4 +1290,5 @@ module JCAModel { override string getIterationCountFixed() { none() } } + // TODO: flow the GCGenParametersSpecCall to an init, and the init to the operations } diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 1621e9436c42..55d4f497f8ef 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -95,6 +95,14 @@ class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { } class ConstantDataSource extends Crypto::GenericConstantSourceInstance instanceof Literal { + ConstantDataSource() { + // TODO: this is an API specific workaround for JCA, as 'EC' is a constant that may be used + // where typical algorithms are specified, but EC specifically means set up a + // default curve container, that will later be specified explicitly (or if not a default) + // curve is used. + this = any(Literal l | l.getValue() != "EC") + } + override DataFlow::Node getOutputNode() { result.asExpr() = this } override predicate flowsTo(Crypto::FlowAwareElement other) { diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 8252b5138600..f202db6f8e67 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -622,7 +622,30 @@ module CryptographyBase Input> { abstract class KeyEncapsulationAlgorithmInstance extends AlgorithmInstance { } - abstract class EllipticCurveAlgorithmInstance extends AlgorithmInstance { } + abstract class EllipticCurveAlgorithmInstance extends AlgorithmInstance { + /** + * Gets the isolated name as it appears in source + * + * This name should not be parsed or formatted beyond isolating the raw name if necessary. + */ + abstract string getRawEllipticCurveAlgorithmName(); + + /** + * The 'standard' curve name, e.g., "P-256" or "secp256r1". + * meaning the full name of the curve, including the family, key size, and other + * typical parameters found on the name. In many cases this will + * be equivalent to `getRawEllipticCurveAlgorithmName()`, but not always + * (e.g., if the curve is specified through a raw NID). + * In cases like an NID, we want the standardized name so users can quickly + * understand what the curve is, while also parsing out the family and key size + * separately. + */ + abstract string getStandardCurveName(); + + abstract TEllipticCurveType getEllipticCurveFamily(); + + abstract string getKeySize(); + } abstract class HashOperationInstance extends OperationInstance { abstract DigestArtifactInstance getDigestArtifact(); @@ -783,6 +806,9 @@ module CryptographyBase Input> { final private class KeyDerivationAlgorithmInstanceOrValueConsumer = AlgorithmInstanceOrValueConsumer::Union; + final private class EllipticCurveAlgorithmInstanceOrValueConsumer = + AlgorithmInstanceOrValueConsumer::Union; + private newtype TNode = // Artifacts (data that is not an operation or algorithm, e.g., a key) TDigest(DigestArtifactInstance e) or @@ -802,7 +828,7 @@ module CryptographyBase Input> { TKeyCreationOperation(KeyCreationOperationInstance e) or // Algorithms (e.g., SHA-256, AES) TCipherAlgorithm(CipherAlgorithmInstanceOrValueConsumer e) or - TEllipticCurveAlgorithm(EllipticCurveAlgorithmInstance e) or + TEllipticCurveAlgorithm(EllipticCurveAlgorithmInstanceOrValueConsumer e) or THashAlgorithm(HashAlgorithmInstanceOrValueConsumer e) or TKeyDerivationAlgorithm(KeyDerivationAlgorithmInstanceOrValueConsumer e) or TKeyEncapsulationAlgorithm(KeyEncapsulationAlgorithmInstance e) or @@ -2077,39 +2103,133 @@ module CryptographyBase Input> { ES() or OtherEllipticCurveType() - abstract class EllipticCurve extends AlgorithmNode, TEllipticCurveAlgorithm { - abstract string getKeySize(Location location); + private predicate isBrainpoolCurve(string curveName, int keySize) { + // ALL BRAINPOOL CURVES + keySize in [160, 192, 224, 256, 320, 384, 512] and + ( + curveName = "BRAINPOOLP" + keySize.toString() + "R1" + or + curveName = "BRAINPOOLP" + keySize.toString() + "T1" + ) + } + + private predicate isSecCurve(string curveName, int keySize) { + // ALL SEC CURVES + keySize in [112, 113, 128, 131, 160, 163, 192, 193, 224, 233, 239, 256, 283, 384, 409, 521, 571] and + exists(string suff | suff in ["R1", "R2", "K1"] | + curveName = "SECT" + keySize.toString() + suff or + curveName = "SECP" + keySize.toString() + suff + ) + } + + private predicate isC2Curve(string curveName, int keySize) { + // ALL C2 CURVES + keySize in [163, 176, 191, 208, 239, 272, 304, 359, 368, 431] and + exists(string pre, string suff | + pre in ["PNB", "ONB", "TNB"] and suff in ["V1", "V2", "V3", "V4", "V5", "W1", "R1"] + | + curveName = "C2" + pre + keySize.toString() + suff + ) + } + + private predicate isPrimeCurve(string curveName, int keySize) { + // ALL PRIME CURVES + keySize in [192, 239, 256] and + exists(string suff | suff in ["V1", "V2", "V3"] | + curveName = "PRIME" + keySize.toString() + suff + ) + } + + private predicate isNumsCurve(string curveName, int keySize) { + // ALL NUMS CURVES + keySize in [256, 384, 512] and + exists(string suff | suff in ["T1"] | curveName = "NUMSP" + keySize.toString() + suff) + } + + bindingset[curveName] + predicate isEllipticCurveAlgorithmName(string curveName) { + isEllipticCurveAlgorithm(curveName, _, _) + } + + /** + * Holds if `name` corresponds to a known elliptic curve. + */ + bindingset[rawName] + predicate isEllipticCurveAlgorithm(string rawName, int keySize, TEllipticCurveType curveFamily) { + exists(string curveName | curveName = rawName.toUpperCase() | + isSecCurve(curveName, keySize) and curveFamily = SEC() + or + isBrainpoolCurve(curveName, keySize) and curveFamily = BRAINPOOL() + or + isC2Curve(curveName, keySize) and curveFamily = C2() + or + isPrimeCurve(curveName, keySize) and curveFamily = PRIME() + or + isNumsCurve(curveName, keySize) and curveFamily = NUMS() + or + curveName = "ES256" and keySize = 256 and curveFamily = ES() + or + curveName = "CURVE25519" and keySize = 255 and curveFamily = CURVE25519() + or + curveName = "X25519" and keySize = 255 and curveFamily = CURVE25519() + or + curveName = "ED25519" and keySize = 255 and curveFamily = CURVE25519() + or + curveName = "CURVE448" and keySize = 448 and curveFamily = CURVE448() + or + curveName = "ED448" and keySize = 448 and curveFamily = CURVE448() + or + curveName = "X448" and keySize = 448 and curveFamily = CURVE448() + or + curveName = "SM2" and keySize in [256, 512] and curveFamily = SM2() + ) + } + + final class EllipticCurveNode extends AlgorithmNode, TEllipticCurveAlgorithm { + EllipticCurveAlgorithmInstanceOrValueConsumer instance; + + EllipticCurveNode() { this = TEllipticCurveAlgorithm(instance) } - abstract TEllipticCurveType getCurveFamily(); + override string getInternalType() { result = "EllipticCurveAlgorithm" } + + final override string getRawAlgorithmName() { + result = instance.asAlg().getRawEllipticCurveAlgorithmName() + } + + // NICK QUESTION: do I repeat the key size and curve family predicates here as wrappers of the instance? + override LocatableElement asElement() { result = instance } + + TEllipticCurveType getEllipticCurveFamily() { + result = instance.asAlg().getEllipticCurveFamily() + } override predicate properties(string key, string value, Location location) { super.properties(key, value, location) or - // [KNOWN_OR_UNKNOWN] + // [ONLY_KNOWN] key = "KeySize" and - if exists(this.getKeySize(location)) - then value = this.getKeySize(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - // other properties, like field type are possible, but not modeled until considered necessary + value = instance.asAlg().getKeySize() and + location = this.getLocation() + or + key = "StdCurveName" and + value = instance.asAlg().getStandardCurveName().toUpperCase() and + location = this.getLocation() } override string getAlgorithmName() { result = this.getRawAlgorithmName().toUpperCase() } - - /** - * Mandating that for Elliptic Curves specifically, users are responsible - * for providing as the 'raw' name, the official name of the algorithm. - * - * Casing doesn't matter, we will enforce further naming restrictions on - * `getAlgorithmName` by default. - * - * Rationale: elliptic curve names can have a lot of variation in their components - * (e.g., "secp256r1" vs "P-256"), trying to produce generalized set of properties - * is possible to capture all cases, but such modeling is likely not necessary. - * if all properties need to be captured, we can reassess how names are generated. - */ - abstract override string getRawAlgorithmName(); + // /** + // * Mandating that for Elliptic Curves specifically, users are responsible + // * for providing as the 'raw' name, the official name of the algorithm. + // * + // * Casing doesn't matter, we will enforce further naming restrictions on + // * `getAlgorithmName` by default. + // * + // * Rationale: elliptic curve names can have a lot of variation in their components + // * (e.g., "secp256r1" vs "P-256"), trying to produce generalized set of properties + // * is possible to capture all cases, but such modeling is likely not necessary. + // * if all properties need to be captured, we can reassess how names are generated. + // */ + // abstract override string getRawAlgorithmName(); } abstract class KEMAlgorithm extends TKeyEncapsulationAlgorithm, AlgorithmNode { From 50507586ac3faf9b00ff9a9d0c9fe47e3b92f88c Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Wed, 2 Apr 2025 19:44:57 +0200 Subject: [PATCH 077/336] Refactor output artifact type --- java/ql/lib/experimental/Quantum/JCA.qll | 6 +- java/ql/lib/experimental/Quantum/Language.qll | 14 ----- .../codeql/cryptography/Model.qll | 57 +++++++------------ 3 files changed, 24 insertions(+), 53 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 5cff0129b721..4a9082bf91c2 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -419,7 +419,7 @@ module JCAModel { src.asExpr() instanceof CipherGetInstanceCall } - predicate isSink(DataFlow::Node sink, FlowState state) { none() } + predicate isSink(DataFlow::Node sink, FlowState state) { none() } // TODO: document this, but this is intentional (avoid cross products?) predicate isSink(DataFlow::Node sink) { exists(CipherOperationCall c | c.getQualifier() = sink.asExpr()) @@ -786,7 +786,7 @@ module JCAModel { type instanceof Crypto::TAsymmetricKeyType } - override DataFlow::Node getOutputKeyArtifact() { result.asExpr() = this } + override Crypto::ArtifactOutputDataFlowNode getOutputKeyArtifact() { result.asExpr() = this } override Crypto::KeyArtifactType getOutputKeyType() { result = type } @@ -1139,7 +1139,7 @@ module JCAModel { result.asExpr() = this.getInstantiation().getIterationCountArg() } - override DataFlow::Node getOutputKeyArtifact() { + override Crypto::ArtifactOutputDataFlowNode getOutputKeyArtifact() { result.asExpr() = this and super.getMethod().getReturnType().hasName("SecretKey") } diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 1621e9436c42..9e27fedf7faf 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -191,19 +191,5 @@ module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { module GenericDataSourceUniversalFlow = TaintTracking::Global; -/* - * class LiteralOrGenericDataSource extends Element { - * DataFlow::Node node; - * - * LiteralOrGenericDataSource() { - * node = this.(Crypto::GenericSourceInstance).getOutputNode() or - * node.asExpr() = this.(Literal) - * } - * - * bindingset[other] - * predicate localFlowsTo(DataFlow::Node other) { DataFlow::localFlow(node, other) } - * } - */ - // Import library-specific modeling import JCA diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 8252b5138600..33c75c556ef3 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -41,6 +41,10 @@ module CryptographyBase Input> { ConsumerElement getConsumer() { result.getInputNode() = this } } + class ArtifactOutputDataFlowNode extends DataFlowNode { + OutputArtifactInstance getArtifact() { result.getOutputNode() = this } + } + final class UnknownPropertyValue extends string { UnknownPropertyValue() { this = "" } } @@ -461,7 +465,7 @@ module CryptographyBase Input> { this = Input::dfn_to_element(inputNode) } - override KeyArtifactType getKeyType() { result instanceof TUnknownKeyType } + override KeyArtifactType getKeyType() { result instanceof TUnknownKeyType } // A consumer node does not have a key type, refer to source (TODO: refine, should this be none()) final override ConsumerInputDataFlowNode getInputNode() { result = inputNode } } @@ -651,7 +655,7 @@ module CryptographyBase Input> { /** * Gets the key artifact produced by this operation. */ - abstract DataFlowNode getOutputKeyArtifact(); + abstract ArtifactOutputDataFlowNode getOutputKeyArtifact(); /** * Gets the key artifact type produced. @@ -898,29 +902,8 @@ module CryptographyBase Input> { predicate isExcludedFromGraph() { none() } } - signature string getDefaultValueSig(); - - signature ConsumerInputDataFlowNode getConsumerSig(); - - signature class NodeBaseSig instanceof NodeBase; - - module PropertyOutput { - bindingset[root] - predicate get(NodeBase root, string value, Location location) { - if not exists(getDefault()) and not exists(getConsumer().getConsumer().getASource()) - then value instanceof UnknownPropertyValue and location instanceof UnknownLocation - else ( - if exists(getDefault()) - then - value = "Default:" + getDefault() and - location = root.getLocation() - else node_as_property(getConsumer().getConsumer().getAGenericSourceNode(), value, location) - ) - } - } - /** - * A generic source node is a source of data that is not resolvable to a specific value or type. + * A generic source node is a source of data that is not resolvable to a specific asset. */ private class GenericSourceNode extends NodeBase, TGenericSourceNode { GenericSourceInstance instance; @@ -956,7 +939,7 @@ module CryptographyBase Input> { * Holds if `node` is a potential candidate for a known algorithm node. * This predicate should be used to restrict the set of candidate algorithm node types. */ - abstract predicate isCandidateKnownAlgorithmNode(AlgorithmNode node); + abstract predicate isCandidateAlgorithmNode(AlgorithmNode node); /** * Gets the algorithm or generic source nodes consumed as an algorithm associated with this operation. @@ -968,12 +951,12 @@ module CryptographyBase Input> { } /** - * Gets a known algorithm associated with this operation, subject to `isCandidateKnownAlgorithmNode`. + * Gets a known algorithm associated with this operation, subject to `isCandidateAlgorithmNode`. */ AlgorithmNode getAKnownAlgorithm() { result = this.asElement().(OperationInstance).getAnAlgorithmValueConsumer().getAKnownSourceNode() and - this.isCandidateKnownAlgorithmNode(result) + this.isCandidateAlgorithmNode(result) } override NodeBase getChild(string edgeName) { @@ -1147,9 +1130,11 @@ module CryptographyBase Input> { // [KNOWN_OR_UNKNOWN] - only if asymmetric edgeName = "Algorithm" and instance.getKeyType() instanceof TAsymmetricKeyType and - if exists(this.getAKnownAlgorithmOrGenericSourceNode()) - then result = this.getAKnownAlgorithmOrGenericSourceNode() - else result = this + ( + if exists(this.getAKnownAlgorithmOrGenericSourceNode()) + then result = this.getAKnownAlgorithmOrGenericSourceNode() + else result = this + ) } override predicate properties(string key, string value, Location location) { @@ -1217,7 +1202,7 @@ module CryptographyBase Input> { override LocatableElement asElement() { result = instance } - override predicate isCandidateKnownAlgorithmNode(AlgorithmNode node) { + override predicate isCandidateAlgorithmNode(AlgorithmNode node) { node instanceof MACAlgorithmNode } @@ -1292,7 +1277,7 @@ module CryptographyBase Input> { KeyGenerationOperationNode() { keyGenInstance = instance } - override predicate isCandidateKnownAlgorithmNode(AlgorithmNode node) { + override predicate isCandidateAlgorithmNode(AlgorithmNode node) { node instanceof CipherAlgorithmNode } @@ -1326,7 +1311,7 @@ module CryptographyBase Input> { result.asElement() = kdfInstance.getOutputKeySizeConsumer().getConsumer().getAGenericSource() } - override predicate isCandidateKnownAlgorithmNode(AlgorithmNode node) { + override predicate isCandidateAlgorithmNode(AlgorithmNode node) { node instanceof KeyDerivationAlgorithmNode } @@ -1585,7 +1570,7 @@ module CryptographyBase Input> { override string getInternalType() { result = "CipherOperation" } - override predicate isCandidateKnownAlgorithmNode(AlgorithmNode node) { + override predicate isCandidateAlgorithmNode(AlgorithmNode node) { node instanceof CipherAlgorithmNode } @@ -1904,7 +1889,7 @@ module CryptographyBase Input> { type instanceof SM4 and name = "SM4" and s = Block() or type instanceof OtherCipherType and - name instanceof UnknownPropertyValue and + name instanceof UnknownPropertyValue and // TODO: get rid of this hack to bind structure and type s = UnknownCipherStructureType() } @@ -1959,7 +1944,7 @@ module CryptographyBase Input> { override LocatableElement asElement() { result = instance } - override predicate isCandidateKnownAlgorithmNode(AlgorithmNode node) { + override predicate isCandidateAlgorithmNode(AlgorithmNode node) { node instanceof HashAlgorithmNode } From 697c9f0bb0e03272a6d6c964a4891582e1526697 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Fri, 4 Apr 2025 09:02:09 -0400 Subject: [PATCH 078/336] Elliptic curve AVCs are incorrect, but I'm not sure how to fix them generally. Putting in a stop gap to use 'isCipherAVC' for now. --- shared/cryptography/codeql/cryptography/Model.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 1c2e655314cf..09f67f156c2a 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -811,7 +811,7 @@ module CryptographyBase Input> { AlgorithmInstanceOrValueConsumer::Union; final private class EllipticCurveAlgorithmInstanceOrValueConsumer = - AlgorithmInstanceOrValueConsumer::Union; + AlgorithmInstanceOrValueConsumer::Union; private newtype TNode = // Artifacts (data that is not an operation or algorithm, e.g., a key) From a2fe19af38acc7e4a7acef3c61ff66ea93c6605a Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Fri, 4 Apr 2025 16:00:05 -0400 Subject: [PATCH 079/336] Initial progress on key agreement. --- java/ql/lib/experimental/Quantum/JCA.qll | 135 +++++++++++++++++- .../codeql/cryptography/Model.qll | 53 +++++++ 2 files changed, 186 insertions(+), 2 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 2bce7fa68438..7d4b36ebe276 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -56,6 +56,9 @@ module JCAModel { bindingset[name] predicate elliptic_curve_names(string name) { Crypto::isEllipticCurveAlgorithmName(name) } + bindingset[name] + predicate key_agreement_names(string name) { Crypto::isKeyAgreementAlgorithmName(name) } + bindingset[name] Crypto::TKeyDerivationType kdf_name_to_kdf_type(string name, string withSubstring) { name.matches("PBKDF2With%") and @@ -123,6 +126,10 @@ module JCAModel { string getStandardEllipticCurveName() { result = this.getValue() } } + class KeyAgreementStringLiteral extends StringLiteral { + KeyAgreementStringLiteral() { key_agreement_names(this.getValue()) } + } + class CipherGetInstanceCall extends Call { CipherGetInstanceCall() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "getInstance") @@ -166,7 +173,7 @@ module JCAModel { TaintTracking::Global; /** - * Data-flow configuration modelling flow from a cipher string literal to a value consumer argument. + * Data-flow configuration modelling flow from a elliptic curve literal to a value consumer argument. */ private module EllipticCurveAlgorithmStringToFetchConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof EllipticCurveStringLiteral } @@ -211,6 +218,89 @@ module JCAModel { } } + /** + * Data-flow configuration modelling flow from a key agreement literal to a value consumer argument. + */ + private module KeyAgreementAlgorithmStringToFetchConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof KeyAgreementStringLiteral } + + predicate isSink(DataFlow::Node sink) { + exists(Crypto::AlgorithmValueConsumer consumer | sink = consumer.getInputNode()) + } + } + + module KeyAgreementAlgorithmStringToFetchFlow = + TaintTracking::Global; + + class KeyAgreementInitCall extends MethodCall { + KeyAgreementInitCall() { + this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "init") + } + + Expr getServerKeyArg() { result = this.getArgument(0) } + } + + private module KeyAgreementInitQualifierToSecretGenQualifierConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + exists(KeyAgreementInitCall init | src.asExpr() = init.getQualifier()) + } + + predicate isSink(DataFlow::Node sink) { + exists(KeyAgreementGenerateSecretCall c | sink.asExpr() = c.getQualifier()) + } + + /** + * Barrier if we go into another init, assume the second init overwrites the first + */ + predicate isBarrierIn(DataFlow::Node node) { isSource(node) } + } + + module KeyAgreementInitQualifierToSecretGenQualifierFlow = + DataFlow::Global; + + class KeyAgreementGenerateSecretCall extends MethodCall { + KeyAgreementGenerateSecretCall() { + this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "generateSecret") + } + + KeyAgreementInitCall getKeyAgreementInitCall() { + KeyAgreementInitQualifierToSecretGenQualifierFlow::flow(DataFlow::exprNode(result + .getQualifier()), DataFlow::exprNode(this.getQualifier())) + } + } + + private module KeyAgreementAVCToInitQualifierConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + exists(KeyAgreementAlgorithmValueConsumer consumer | consumer.getResultNode() = src) + } + + predicate isSink(DataFlow::Node sink) { + exists(KeyAgreementInitCall init | sink.asExpr() = init.getQualifier()) + } + } + + module KeyAgreementAVCToInitQualifierFlow = + DataFlow::Global; + + class KeyAgreementSecretGenerationOperationInstance extends Crypto::KeyAgreementSecretGenerationOperationInstance instanceof KeyAgreementGenerateSecretCall + { + override Crypto::ConsumerInputDataFlowNode getServerKeyConsumer() { + this.(KeyAgreementGenerateSecretCall).getKeyAgreementInitCall().getServerKeyArg() = + result.asExpr() + } + + override Crypto::ConsumerInputDataFlowNode getPeerKeyConsumer() { + none() //TODO + } + + override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { + none() // TODO: key agreeement has it's own algorithm consumer, separate from the key + // TODO: the char pred must trace from the consumer to here, + // in theory, along that path we would get the init and doPhase, but can I just get those + // separately avoiding a complicated config state for dataflow? + } + } + class CipherStringLiteralModeAlgorithmInstance extends JCAAlgorithmInstance, CipherStringLiteralPaddingAlgorithmInstance, Crypto::ModeOfOperationAlgorithmInstance instanceof CipherStringLiteral { @@ -339,7 +429,7 @@ module JCAModel { } class EllipticCurveStringLiteralAlgorithmInstance extends JCAAlgorithmInstance, - Crypto::EllipticCurveAlgorithmInstance instanceof StringLiteral + Crypto::EllipticCurveAlgorithmInstance instanceof EllipticCurveStringLiteral { Crypto::AlgorithmValueConsumer consumer; @@ -367,6 +457,47 @@ module JCAModel { } } + class KeyAgreementGetInstanceCall extends MethodCall { + KeyAgreementGetInstanceCall() { + this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "getInstance") + } + + Expr getAlgorithmArg() { result = super.getArgument(0) } + } + + class KeyAgreementAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { + KeyAgreementGetInstanceCall call; + + KeyAgreementAlgorithmValueConsumer() { this = call.getAlgorithmArg() } + + DataFlow::Node getResultNode() { result.asExpr() = call } + + override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } + + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + result.(KeyAgreementStringLiteralAlgorithmInstance).getConsumer() = this + } + } + + class KeyAgreementStringLiteralAlgorithmInstance extends JCAAlgorithmInstance, + Crypto::KeyAgreementAlgorithmInstance instanceof KeyAgreementStringLiteral + { + Crypto::AlgorithmValueConsumer consumer; + + KeyAgreementStringLiteralAlgorithmInstance() { + KeyAgreementAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) + } + + override Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } + // override Crypto::EllipticCurveAlgorithmInstance getEllipticCurveAlgorithm() { + // this.(KeyAgreementStringLiteral).getValue().toUpperCase() in ["X25519", "X448"] and + // // NOTE: this relies upon modeling the elliptic curve on 'this' separately + // result = this + // // TODO: or is ecdh and go find the curve + // // this.(KeyAgreementStringLiteral).toString().toUpperCase() = ["ECDH"] + // } + } + class CipherStringLiteralAlgorithmInstance extends JCAAlgorithmInstance, Crypto::CipherAlgorithmInstance instanceof CipherStringLiteral { diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 09f67f156c2a..fe397c6247f3 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -837,6 +837,7 @@ module CryptographyBase Input> { TKeyDerivationAlgorithm(KeyDerivationAlgorithmInstanceOrValueConsumer e) or TKeyEncapsulationAlgorithm(KeyEncapsulationAlgorithmInstance e) or TMACAlgorithm(MACAlgorithmInstanceOrValueConsumer e) or + TKeyAgreementAlgorithm(KeyAgreementAlgorithmInstance e) or // Non-standalone Algorithms (e.g., Mode, Padding) // TODO: need to rename this, as "mode" is getting reused in different contexts, be precise TModeOfOperationAlgorithm(ModeOfOperationAlgorithmInstance e) or @@ -2220,4 +2221,56 @@ module CryptographyBase Input> { abstract class KEMAlgorithm extends TKeyEncapsulationAlgorithm, AlgorithmNode { final override string getInternalType() { result = "KeyEncapsulationAlgorithm" } } + + /** + * Key agreement algorithms + */ + newtype TKeyAgreementType = + DH() or // Diffie-Hellman + EDH() or // Ephemeral Diffie-Hellman + ECDH() or // Elliptic Curve Diffie-Hellman + // Note: x25519 and x448 are applications of ECDH + OtherKeyAgreementType() + + bindingset[name] + predicate isKeyAgreementAlgorithmName(string name) { isKeyAgreementAlgorithm(name, _) } + + bindingset[name] + predicate isKeyAgreementAlgorithm(string name, TKeyAgreementType type) { + exists(string name2 | name2 = name.toUpperCase() | + name2 = "DH" and type = DH() + or + name2 = "EDH" and type = EDH() + or + name2 = "ECDH" and type = ECDH() + or + name2 = "X25519" and type = ECDH() + or + name2 = "X448" and type = ECDH() + ) + } + + abstract class KeyAgreementAlgorithmInstance extends AlgorithmInstance { + // /** + // * If the key agreement uses a curve, (e.g., ECDH) point to the curve instance. + // * none() if the agreement is not curve based (e.g., plain DH). + // * Note that if the curve is inherent to the algorithm (e.g., x25519), this will be + // * the key agreement algorithm instance itself (this). + // */ + // abstract EllipticCurveAlgorithmInstance getEllipticCurveAlgorithm(); + } + + abstract class KeyAgreementSecretGenerationOperationInstance extends OperationInstance { + /** + * The private key used in the key agreement operation. + * This key represents the local party in the key agreement. + */ + abstract ConsumerInputDataFlowNode getServerKeyConsumer(); + + /** + * The public key used in the key agreement operation, coming + * from the peer (the other party in the key agreement). + */ + abstract ConsumerInputDataFlowNode getPeerKeyConsumer(); + } } From b9d0abda632b05ddaa74e3747defa1eb8cc2b0a4 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Wed, 9 Apr 2025 21:19:00 +0200 Subject: [PATCH 080/336] Move CipherOperation into KeyOperation, refactor - KeyOperation and Algorithm now encompasses encryption, decryption, wrapping, unwrapping, signing, and verifying. - Removed elliptic curve implementation from JCA.qll pending rewrite - Removed JCAAlgorithmInstance abstraction from JCA.qll - Cleaned up and removed JCA-specific naming from Model.qll - Added and clarified documentation --- cpp/ql/lib/experimental/Quantum/Language.qll | 2 +- java/ql/lib/experimental/Quantum/JCA.qll | 754 +++++------ .../InsecureOrUnknownNonceAtOperation.ql | 9 +- .../Quantum/PossibleReusedNonce.ql | 17 +- .../ql/src/experimental/Quantum/TestCipher.ql | 8 +- .../src/experimental/Quantum/TestCipherKey.ql | 4 +- .../codeql/cryptography/Model.qll | 1176 +++++++++-------- 7 files changed, 970 insertions(+), 1000 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index 2dc17f5e267a..0d0caf7f49b5 100644 --- a/cpp/ql/lib/experimental/Quantum/Language.qll +++ b/cpp/ql/lib/experimental/Quantum/Language.qll @@ -112,7 +112,7 @@ module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { module ArtifactUniversalFlow = DataFlow::Global; -abstract class CipherOutputArtifact extends Crypto::CipherOutputArtifactInstance { +abstract class CipherOutputArtifact extends Crypto::KeyOperationOutputArtifactInstance { override predicate flowsTo(Crypto::FlowAwareElement other) { ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) } diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 7d4b36ebe276..b75c00c35498 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -5,10 +5,7 @@ import semmle.code.java.controlflow.Dominance module JCAModel { import Language - - abstract class JCAAlgorithmInstance extends Crypto::AlgorithmInstance { - abstract Crypto::AlgorithmValueConsumer getConsumer(); - } + import Crypto::KeyOpAlg as KeyOpAlg // TODO: Verify that the PBEWith% case works correctly bindingset[algo] @@ -54,10 +51,48 @@ module JCAModel { } bindingset[name] - predicate elliptic_curve_names(string name) { Crypto::isEllipticCurveAlgorithmName(name) } + predicate elliptic_curve_names(string name) { + // Note: as a one-off exception, we use the internal Crypto module implementation of `isEllipticCurveAlgorithmName` + Crypto::isEllipticCurveAlgorithmName(name) + } + + /* + * TODO: + * + * MAC Algorithms possible (JCA Default + BouncyCastle Extensions) + * + * Name Type Description + * --------------------------------------------------------------------------- + * "HmacMD5" HMAC HMAC with MD5 (not recommended) + * "HmacSHA1" HMAC HMAC with SHA-1 (not recommended) + * "HmacSHA224" HMAC HMAC with SHA-224 + * "HmacSHA256" HMAC HMAC with SHA-256 + * "HmacSHA384" HMAC HMAC with SHA-384 + * "HmacSHA512" HMAC HMAC with SHA-512 + * + * (BouncyCastle and Other Provider Extensions) + * "AESCMAC" CMAC Cipher-based MAC using AES + * "DESCMAC" CMAC CMAC with DES (legacy) + * "GMAC" GCM-based MAC Authenticates AAD only (GCM-style) + * "Poly1305" AEAD-style MAC Used with ChaCha20 + * "SipHash" Hash-based MAC Fast MAC for short inputs + * "BLAKE2BMAC" HMAC-style BLAKE2b MAC (cryptographic hash) + * "HmacRIPEMD160" HMAC HMAC with RIPEMD160 hash + */ + + bindingset[name] + predicate mac_names(string name) { + name.toUpperCase() + .matches([ + "HMAC%", "AESCMAC", "DESCMAC", "GMAC", "Poly1305", "SipHash", "BLAKE2BMAC", + "HMACRIPEMD160" + ].toUpperCase()) + } bindingset[name] - predicate key_agreement_names(string name) { Crypto::isKeyAgreementAlgorithmName(name) } + predicate key_agreement_names(string name) { + name.toUpperCase().matches(["DH", "EDH", "ECDH", "X25519", "X448"].toUpperCase()) + } bindingset[name] Crypto::TKeyDerivationType kdf_name_to_kdf_type(string name, string withSubstring) { @@ -107,6 +142,77 @@ module JCAModel { digestLength = 512 // TODO: verify } + bindingset[name] + private predicate mode_name_to_type_known( + Crypto::TBlockCipherModeOfOperationType type, string name + ) { + type = Crypto::ECB() and name = "ECB" + or + type = Crypto::CBC() and name = "CBC" + or + type = Crypto::GCM() and name = "GCM" + or + type = Crypto::CTR() and name = "CTR" + or + type = Crypto::XTS() and name = "XTS" + or + type = Crypto::CCM() and name = "CCM" + or + type = Crypto::SIV() and name = "SIV" + or + type = Crypto::OCB() and name = "OCB" + } + + bindingset[name] + private predicate cipher_name_to_type_known(KeyOpAlg::TAlgorithm type, string name) { + exists(string upper | upper = name.toUpperCase() | + upper.matches("AES%") and + type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::AES()) + or + upper = "DES" and + type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::DES()) + or + upper = "TRIPLEDES" and + type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::TripleDES()) + or + upper = "IDEA" and + type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::IDEA()) + or + upper = "CAST5" and + type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::CAST5()) + or + upper = "CHACHA20" and + type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::CHACHA20()) + or + upper = "RC4" and + type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::RC4()) + or + upper = "RC5" and + type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::RC5()) + or + upper = "RSA" and + type = KeyOpAlg::TAsymmetricCipher(KeyOpAlg::RSA()) + ) + } + + bindingset[name] + predicate mac_name_to_mac_type_known(Crypto::TMACType type, string name) { + type = Crypto::THMAC() and + name.toUpperCase().matches("HMAC%") + } + + bindingset[name] + predicate key_agreement_name_to_type_known(Crypto::TKeyAgreementType type, string name) { + type = Crypto::DH() and + name.toUpperCase() = "DH" + or + type = Crypto::EDH() and + name.toUpperCase() = "EDH" + or + type = Crypto::ECDH() and + name.toUpperCase() in ["ECDH", "X25519", "X448"] + } + /** * A `StringLiteral` in the `"ALG/MODE/PADDING"` or `"ALG"` format */ @@ -120,16 +226,6 @@ module JCAModel { string getPadding() { result = this.getValue().splitAt("/", 2) } } - class EllipticCurveStringLiteral extends StringLiteral { - EllipticCurveStringLiteral() { elliptic_curve_names(this.getValue()) } - - string getStandardEllipticCurveName() { result = this.getValue() } - } - - class KeyAgreementStringLiteral extends StringLiteral { - KeyAgreementStringLiteral() { key_agreement_names(this.getValue()) } - } - class CipherGetInstanceCall extends Call { CipherGetInstanceCall() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "getInstance") @@ -159,9 +255,9 @@ module JCAModel { } /** - * Data-flow configuration modelling flow from a cipher string literal to a value consumer argument. + * Data-flow configuration modelling flow from a cipher string literal to a `CipherGetInstanceCall` argument. */ - private module CipherAlgorithmStringToFetchConfig implements DataFlow::ConfigSig { + private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof CipherStringLiteral } predicate isSink(DataFlow::Node sink) { @@ -169,22 +265,7 @@ module JCAModel { } } - module CipherAlgorithmStringToFetchFlow = - TaintTracking::Global; - - /** - * Data-flow configuration modelling flow from a elliptic curve literal to a value consumer argument. - */ - private module EllipticCurveAlgorithmStringToFetchConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { src.asExpr() instanceof EllipticCurveStringLiteral } - - predicate isSink(DataFlow::Node sink) { - exists(Crypto::AlgorithmValueConsumer consumer | sink = consumer.getInputNode()) - } - } - - module EllipticCurveAlgorithmStringToFetchFlow = - TaintTracking::Global; + module AlgorithmStringToFetchFlow = TaintTracking::Global; /** * Note: padding and a mode of operation will only exist when the padding / mode (*and its type*) are determinable. @@ -195,8 +276,8 @@ module JCAModel { * * TODO: Model the case of relying on a provider default, but alert on it as a bad practice. */ - class CipherStringLiteralPaddingAlgorithmInstance extends JCAAlgorithmInstance, - CipherStringLiteralAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof CipherStringLiteral + class CipherStringLiteralPaddingAlgorithmInstance extends CipherStringLiteralAlgorithmInstance, + Crypto::PaddingAlgorithmInstance instanceof CipherStringLiteral { CipherStringLiteralPaddingAlgorithmInstance() { exists(super.getPadding()) } // TODO: provider defaults @@ -218,298 +299,29 @@ module JCAModel { } } - /** - * Data-flow configuration modelling flow from a key agreement literal to a value consumer argument. - */ - private module KeyAgreementAlgorithmStringToFetchConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { src.asExpr() instanceof KeyAgreementStringLiteral } - - predicate isSink(DataFlow::Node sink) { - exists(Crypto::AlgorithmValueConsumer consumer | sink = consumer.getInputNode()) - } - } - - module KeyAgreementAlgorithmStringToFetchFlow = - TaintTracking::Global; - - class KeyAgreementInitCall extends MethodCall { - KeyAgreementInitCall() { - this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "init") - } - - Expr getServerKeyArg() { result = this.getArgument(0) } - } - - private module KeyAgreementInitQualifierToSecretGenQualifierConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { - exists(KeyAgreementInitCall init | src.asExpr() = init.getQualifier()) - } - - predicate isSink(DataFlow::Node sink) { - exists(KeyAgreementGenerateSecretCall c | sink.asExpr() = c.getQualifier()) - } - - /** - * Barrier if we go into another init, assume the second init overwrites the first - */ - predicate isBarrierIn(DataFlow::Node node) { isSource(node) } - } - - module KeyAgreementInitQualifierToSecretGenQualifierFlow = - DataFlow::Global; - - class KeyAgreementGenerateSecretCall extends MethodCall { - KeyAgreementGenerateSecretCall() { - this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "generateSecret") - } - - KeyAgreementInitCall getKeyAgreementInitCall() { - KeyAgreementInitQualifierToSecretGenQualifierFlow::flow(DataFlow::exprNode(result - .getQualifier()), DataFlow::exprNode(this.getQualifier())) - } - } - - private module KeyAgreementAVCToInitQualifierConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { - exists(KeyAgreementAlgorithmValueConsumer consumer | consumer.getResultNode() = src) - } - - predicate isSink(DataFlow::Node sink) { - exists(KeyAgreementInitCall init | sink.asExpr() = init.getQualifier()) - } - } - - module KeyAgreementAVCToInitQualifierFlow = - DataFlow::Global; - - class KeyAgreementSecretGenerationOperationInstance extends Crypto::KeyAgreementSecretGenerationOperationInstance instanceof KeyAgreementGenerateSecretCall - { - override Crypto::ConsumerInputDataFlowNode getServerKeyConsumer() { - this.(KeyAgreementGenerateSecretCall).getKeyAgreementInitCall().getServerKeyArg() = - result.asExpr() - } - - override Crypto::ConsumerInputDataFlowNode getPeerKeyConsumer() { - none() //TODO - } - - override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { - none() // TODO: key agreeement has it's own algorithm consumer, separate from the key - // TODO: the char pred must trace from the consumer to here, - // in theory, along that path we would get the init and doPhase, but can I just get those - // separately avoiding a complicated config state for dataflow? - } - } - - class CipherStringLiteralModeAlgorithmInstance extends JCAAlgorithmInstance, - CipherStringLiteralPaddingAlgorithmInstance, Crypto::ModeOfOperationAlgorithmInstance instanceof CipherStringLiteral + class CipherStringLiteralModeAlgorithmInstance extends CipherStringLiteralPaddingAlgorithmInstance, + Crypto::ModeOfOperationAlgorithmInstance instanceof CipherStringLiteral { CipherStringLiteralModeAlgorithmInstance() { exists(super.getMode()) } // TODO: provider defaults override string getRawModeAlgorithmName() { result = super.getMode() } - bindingset[name] - private predicate modeToNameMappingKnown(Crypto::TBlockCipherModeOperationType type, string name) { - type instanceof Crypto::ECB and name = "ECB" - or - type instanceof Crypto::CBC and name = "CBC" - or - type instanceof Crypto::GCM and name = "GCM" - or - type instanceof Crypto::CTR and name = "CTR" - or - type instanceof Crypto::XTS and name = "XTS" - or - type instanceof Crypto::CCM and name = "CCM" - or - type instanceof Crypto::SIV and name = "SIV" - or - type instanceof Crypto::OCB and name = "OCB" - } - - override Crypto::TBlockCipherModeOperationType getModeType() { - if this.modeToNameMappingKnown(_, super.getMode()) - then this.modeToNameMappingKnown(result, super.getMode()) + override Crypto::TBlockCipherModeOfOperationType getModeType() { + if mode_name_to_type_known(_, super.getMode()) + then mode_name_to_type_known(result, super.getMode()) else result instanceof Crypto::OtherMode } } - class KeyGeneratorGetInstanceCall extends MethodCall { - KeyGeneratorGetInstanceCall() { - this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "getInstance") - or - this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "getInstance") - } - - Expr getAlgorithmArg() { result = super.getArgument(0) } - } - - // For general elliptic curves, getInstance("EC") is used - // and java.security.spec.ECGenParameterSpec("") is what sets the specific curve. - // The result of ECGenParameterSpec is passed to KeyPairGenerator.initialize - // If the curve is not specified, the default is used. - // We would trace the use of this inside a KeyPairGenerator.initialize - class ECGenParameterSpecCall extends ClassInstanceExpr { - ECGenParameterSpecCall() { - this.(ClassInstanceExpr) - .getConstructedType() - .hasQualifiedName("java.security.spec", "ECGenParameterSpec") - } - - Expr getAlgorithmArg() { result = super.getArgument(0) } - - KeyPairGeneratorInitializeCall getInitializeConsumerCall() { - exists(DataFlow::Node sink | - ECGenParameterSpecCallToInitializeFlow::flow(DataFlow::exprNode(this), sink) and - result.getAnArgument() = sink.asExpr() - ) - } - } - - abstract class KeyGenAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { - // abstract predicate flowsToKeyGenerateCallQualifier(KeyGeneratorGenerateCall sink); - abstract DataFlow::Node getResultNode(); - } - - class KeyPairGeneratorInitializeCall extends MethodCall { - KeyPairGeneratorInitializeCall() { - this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "initialize") - } - - Expr getKeyArg() { - result = this.getArgument(0) and - result.getType() instanceof IntegralType - } - } - - private module ECGenParameterSpecCallToInitializeConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ECGenParameterSpecCall } - - predicate isSink(DataFlow::Node sink) { - exists(KeyPairGeneratorInitializeCall c | c.getAnArgument() = sink.asExpr()) - } - } - - module ECGenParameterSpecCallToInitializeFlow = - DataFlow::Global; - - class ECGenParameterSpecAlgorithmValueConsumer extends KeyGenAlgorithmValueConsumer { - ECGenParameterSpecCall call; - - ECGenParameterSpecAlgorithmValueConsumer() { this = call.getAlgorithmArg() } - - override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } - - override DataFlow::Node getResultNode() { - // Traversing to the initialilzer directly and calling this the 'result' - // to simplify the trace. In theory you would trace from the call - // through the initializer, but we already have a trace to the initializer - // so using this instead of altering/creating data flow configs. - call.getInitializeConsumerCall().getQualifier() = result.asExpr() - } - - override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { - result.(JCAAlgorithmInstance).getConsumer() = this - } - } - - class KeyGeneratorGetInstanceAlgorithmValueConsumer extends KeyGenAlgorithmValueConsumer { - KeyGeneratorGetInstanceCall call; - - KeyGeneratorGetInstanceAlgorithmValueConsumer() { this = call.getAlgorithmArg() } - - override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } - - override DataFlow::Node getResultNode() { result.asExpr() = call } - - override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { - // The source is any instance whose consumer is this - result.(JCAAlgorithmInstance).getConsumer() = this - } - } - - class EllipticCurveStringLiteralAlgorithmInstance extends JCAAlgorithmInstance, - Crypto::EllipticCurveAlgorithmInstance instanceof EllipticCurveStringLiteral - { - Crypto::AlgorithmValueConsumer consumer; - - EllipticCurveStringLiteralAlgorithmInstance() { - // Trace a known elliptic curve algorithm string literal to a key gen consumer - EllipticCurveAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), - consumer.getInputNode()) - } - - override Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } - - override string getRawEllipticCurveAlgorithmName() { result = super.getValue() } - - override string getStandardCurveName() { result = this.getRawEllipticCurveAlgorithmName() } - - override Crypto::TEllipticCurveType getEllipticCurveFamily() { - Crypto::isEllipticCurveAlgorithm(this.getRawEllipticCurveAlgorithmName(), _, result) - } - - override string getKeySize() { - exists(int keySize | - Crypto::isEllipticCurveAlgorithm(this.getRawEllipticCurveAlgorithmName(), keySize, _) and - result = keySize.toString() - ) - } - } - - class KeyAgreementGetInstanceCall extends MethodCall { - KeyAgreementGetInstanceCall() { - this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "getInstance") - } - - Expr getAlgorithmArg() { result = super.getArgument(0) } - } - - class KeyAgreementAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { - KeyAgreementGetInstanceCall call; - - KeyAgreementAlgorithmValueConsumer() { this = call.getAlgorithmArg() } - - DataFlow::Node getResultNode() { result.asExpr() = call } - - override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } - - override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { - result.(KeyAgreementStringLiteralAlgorithmInstance).getConsumer() = this - } - } - - class KeyAgreementStringLiteralAlgorithmInstance extends JCAAlgorithmInstance, - Crypto::KeyAgreementAlgorithmInstance instanceof KeyAgreementStringLiteral + class CipherStringLiteralAlgorithmInstance extends Crypto::KeyOperationAlgorithmInstance instanceof CipherStringLiteral { Crypto::AlgorithmValueConsumer consumer; - KeyAgreementStringLiteralAlgorithmInstance() { - KeyAgreementAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) - } - - override Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } - // override Crypto::EllipticCurveAlgorithmInstance getEllipticCurveAlgorithm() { - // this.(KeyAgreementStringLiteral).getValue().toUpperCase() in ["X25519", "X448"] and - // // NOTE: this relies upon modeling the elliptic curve on 'this' separately - // result = this - // // TODO: or is ecdh and go find the curve - // // this.(KeyAgreementStringLiteral).toString().toUpperCase() = ["ECDH"] - // } - } - - class CipherStringLiteralAlgorithmInstance extends JCAAlgorithmInstance, - Crypto::CipherAlgorithmInstance instanceof CipherStringLiteral - { - // NOTE: this consumer is generic, but cipher algorithms can be consumed - // by getInstance as well as key generation - Crypto::AlgorithmValueConsumer consumer; - CipherStringLiteralAlgorithmInstance() { - CipherAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) + AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) } - override Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } + Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { result = this // TODO: provider defaults @@ -519,42 +331,16 @@ module JCAModel { result = this // TODO: provider defaults } - override string getRawCipherAlgorithmName() { result = super.getValue() } + override string getRawAlgorithmName() { result = super.getValue() } - override Crypto::TCipherType getCipherFamily() { - if this.cipherNameMappingKnown(_, super.getAlgorithmName()) - then this.cipherNameMappingKnown(result, super.getAlgorithmName()) - else result instanceof Crypto::OtherCipherType + override KeyOpAlg::Algorithm getAlgorithmType() { + if cipher_name_to_type_known(_, super.getAlgorithmName()) + then cipher_name_to_type_known(result, super.getAlgorithmName()) + else result instanceof KeyOpAlg::TUnknownKeyOperationAlgorithmType } - bindingset[name] - private predicate cipherNameMappingKnown(Crypto::TCipherType type, string name) { - name = "AES" and - type instanceof Crypto::AES - or - name = "DES" and - type instanceof Crypto::DES - or - name = "TripleDES" and - type instanceof Crypto::TripleDES - or - name = "IDEA" and - type instanceof Crypto::IDEA - or - name = "CAST5" and - type instanceof Crypto::CAST5 - or - name = "ChaCha20" and - type instanceof Crypto::CHACHA20 - or - name = "RC4" and - type instanceof Crypto::RC4 - or - name = "RC5" and - type instanceof Crypto::RC5 - or - name = "RSA" and - type instanceof Crypto::RSA + override string getKeySize() { + none() // TODO: implement to handle variants such as AES-128 } } @@ -587,12 +373,14 @@ module JCAModel { override int getDigestLength() { exists(hash_name_to_hash_type(hashName, result)) } } - class OAEPPaddingAlgorithmInstance extends JCAAlgorithmInstance, - Crypto::OAEPPaddingAlgorithmInstance, CipherStringLiteralPaddingAlgorithmInstance + class OAEPPaddingAlgorithmInstance extends Crypto::OAEPPaddingAlgorithmInstance, + CipherStringLiteralPaddingAlgorithmInstance { override Crypto::HashAlgorithmInstance getOAEPEncodingHashAlgorithm() { result = this } override Crypto::HashAlgorithmInstance getMGF1HashAlgorithm() { none() } // TODO + + override string getKeySize() { none() } } /** @@ -608,7 +396,7 @@ module JCAModel { override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } CipherStringLiteral getOrigin(string value) { - CipherAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(result), + AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(result), DataFlow::exprNode(this.(Expr).getAChildExpr*())) and value = result.getValue() } @@ -650,14 +438,14 @@ module JCAModel { this = TInitializedCipherModeFlowState(_) and result = "initialized" } - abstract Crypto::CipherOperationSubtype getCipherOperationMode(); + abstract Crypto::KeyOperationSubtype getKeyOperationMode(); } private class UninitializedCipherModeFlowState extends CipherModeFlowState, TUninitializedCipherModeFlowState { - override Crypto::CipherOperationSubtype getCipherOperationMode() { - result instanceof Crypto::UnknownCipherOperationSubtype + override Crypto::KeyOperationSubtype getKeyOperationMode() { + result instanceof Crypto::TUnknownKeyOperationMode } } @@ -667,7 +455,7 @@ module JCAModel { CipherInitCall call; DataFlow::Node node1; DataFlow::Node node2; - Crypto::CipherOperationSubtype mode; + Crypto::KeyOperationSubtype mode; InitializedCipherModeFlowState() { this = TInitializedCipherModeFlowState(call) and @@ -687,7 +475,7 @@ module JCAModel { */ DataFlow::Node getSndNode() { result = node2 } - override Crypto::CipherOperationSubtype getCipherOperationMode() { result = mode } + override Crypto::KeyOperationSubtype getKeyOperationMode() { result = mode } } /** @@ -730,8 +518,8 @@ module JCAModel { module CipherGetInstanceToCipherOperationFlow = DataFlow::GlobalWithState; - class CipherOperationInstance extends Crypto::CipherOperationInstance instanceof Call { - Crypto::CipherOperationSubtype mode; + class CipherOperationInstance extends Crypto::KeyOperationInstance instanceof Call { + Crypto::KeyOperationSubtype mode; CipherGetInstanceToCipherOperationFlow::PathNode sink; CipherOperationCall doFinalize; CipherGetInstanceAlgorithmArg consumer; @@ -741,13 +529,13 @@ module JCAModel { CipherGetInstanceToCipherOperationFlow::flowPath(src, sink) and src.getNode().asExpr() = getCipher and sink.getNode().asExpr() = doFinalize.getQualifier() and - sink.getState().(CipherModeFlowState).getCipherOperationMode() = mode and + sink.getState().(CipherModeFlowState).getKeyOperationMode() = mode and this = doFinalize and consumer = getCipher.getAlgorithmArg() ) } - override Crypto::CipherOperationSubtype getCipherOperationSubtype() { result = mode } + override Crypto::KeyOperationSubtype getKeyOperationSubtype() { result = mode } override Crypto::ConsumerInputDataFlowNode getNonceConsumer() { result.asExpr() = sink.getState().(InitializedCipherModeFlowState).getInitCall().getNonceArg() @@ -763,8 +551,8 @@ module JCAModel { override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { result = consumer } - override Crypto::CipherOutputArtifactInstance getOutputArtifact() { - result = doFinalize.getOutput() + override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { + result.asExpr() = doFinalize.getOutput() } } @@ -865,15 +653,15 @@ module JCAModel { module JavaxCipherModeAccessToInitFlow = DataFlow::Global; private predicate cipher_mode_str_to_cipher_mode_known( - string mode, Crypto::CipherOperationSubtype cipher_mode + string mode, Crypto::KeyOperationSubtype cipher_mode ) { - mode = "ENCRYPT_MODE" and cipher_mode instanceof Crypto::EncryptionSubtype + mode = "ENCRYPT_MODE" and cipher_mode = Crypto::TEncryptMode() or - mode = "WRAP_MODE" and cipher_mode instanceof Crypto::WrapSubtype + mode = "WRAP_MODE" and cipher_mode = Crypto::TWrapMode() or - mode = "DECRYPT_MODE" and cipher_mode instanceof Crypto::DecryptionSubtype + mode = "DECRYPT_MODE" and cipher_mode = Crypto::TDecryptMode() or - mode = "UNWRAP_MODE" and cipher_mode instanceof Crypto::UnwrapSubtype + mode = "UNWRAP_MODE" and cipher_mode = Crypto::TUnwrapMode() } class CipherInitCall extends MethodCall { @@ -896,10 +684,10 @@ module JCAModel { ) } - Crypto::CipherOperationSubtype getCipherOperationModeType() { + Crypto::KeyOperationSubtype getCipherOperationModeType() { if cipher_mode_str_to_cipher_mode_known(this.getModeOrigin().getField().getName(), _) then cipher_mode_str_to_cipher_mode_known(this.getModeOrigin().getField().getName(), result) - else result instanceof Crypto::UnknownCipherOperationSubtype + else result = Crypto::TUnknownKeyOperationMode() } Expr getKeyArg() { @@ -918,12 +706,6 @@ module JCAModel { override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } } - class CipherOperationCallOutput extends Crypto::CipherOutputArtifactInstance { - CipherOperationCallOutput() { this = any(CipherOperationCall call).getOutput() } - - override DataFlow::Node getOutputNode() { result.asExpr() = this } - } - // flow config from a known hash algorithm literal to MessageDigest.getInstance module KnownHashAlgorithmLiteralToMessageDigestConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { hash_names(src.asExpr().(StringLiteral).getValue()) } @@ -936,8 +718,7 @@ module JCAModel { module KnownHashAlgorithmLiteralToMessageDigestFlow = DataFlow::Global; - class KnownHashAlgorithm extends JCAAlgorithmInstance, Crypto::HashAlgorithmInstance instanceof StringLiteral - { + class KnownHashAlgorithm extends Crypto::HashAlgorithmInstance instanceof StringLiteral { MessageDigestAlgorithmValueConsumer consumer; KnownHashAlgorithm() { @@ -946,7 +727,7 @@ module JCAModel { consumer.getInputNode()) } - override MessageDigestAlgorithmValueConsumer getConsumer() { result = consumer } + MessageDigestAlgorithmValueConsumer getConsumer() { result = consumer } override string getRawHashAlgorithmName() { result = this.(StringLiteral).getValue() } @@ -1019,10 +800,22 @@ module JCAModel { } } + class KeyGeneratorCallAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { + KeyGeneratorGetInstanceCall call; + + KeyGeneratorCallAlgorithmValueConsumer() { this = call.getAlgorithmArg() } + + override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } + + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + result.(CipherStringLiteralAlgorithmInstance).getConsumer() = this + } + } + // flow from instance created by getInstance to generateKey - module KeyGeneratorAlgValueConsumerToGenerateConfig implements DataFlow::ConfigSig { + module KeyGeneratorGetInstanceToGenerateConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { - exists(KeyGenAlgorithmValueConsumer consumer | consumer.getResultNode() = src) + exists(KeyGeneratorGetInstanceCall call | src.asExpr() = call) } predicate isSink(DataFlow::Node sink) { @@ -1030,8 +823,23 @@ module JCAModel { } } - module KeyGeneratorAlgValueConsumerToGenerateFlow = - DataFlow::Global; + module KeyGeneratorGetInstanceToGenerateFlow = + DataFlow::Global; + + class KeyGeneratorGetInstanceCall extends MethodCall { + KeyGeneratorGetInstanceCall() { + this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "getInstance") + or + this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "getInstance") + } + + Expr getAlgorithmArg() { result = super.getArgument(0) } + + predicate flowsToKeyGenerateCallQualifier(KeyGeneratorGenerateCall sink) { + KeyGeneratorGetInstanceToGenerateFlow::flow(DataFlow::exprNode(this), + DataFlow::exprNode(sink.(MethodCall).getQualifier())) + } + } class KeyGeneratorGenerateCall extends Crypto::KeyGenerationOperationInstance instanceof MethodCall { @@ -1050,10 +858,8 @@ module JCAModel { override Crypto::KeyArtifactType getOutputKeyType() { result = type } override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { - exists(KeyGenAlgorithmValueConsumer consumer | - KeyGeneratorAlgValueConsumerToGenerateFlow::flow(consumer.getResultNode(), - DataFlow::exprNode(this.(Call).getQualifier())) and - result = consumer + exists(KeyGeneratorGetInstanceCall getInstance | + getInstance.flowsToKeyGenerateCallQualifier(this) and result = getInstance.getAlgorithmArg() ) } @@ -1066,45 +872,6 @@ module JCAModel { override string getKeySizeFixed() { none() } } - /* - * TODO: - * - * MAC Algorithms possible (JCA Default + BouncyCastle Extensions) - * - * Name Type Description - * --------------------------------------------------------------------------- - * "HmacMD5" HMAC HMAC with MD5 (not recommended) - * "HmacSHA1" HMAC HMAC with SHA-1 (not recommended) - * "HmacSHA224" HMAC HMAC with SHA-224 - * "HmacSHA256" HMAC HMAC with SHA-256 - * "HmacSHA384" HMAC HMAC with SHA-384 - * "HmacSHA512" HMAC HMAC with SHA-512 - * - * (BouncyCastle and Other Provider Extensions) - * "AESCMAC" CMAC Cipher-based MAC using AES - * "DESCMAC" CMAC CMAC with DES (legacy) - * "GMAC" GCM-based MAC Authenticates AAD only (GCM-style) - * "Poly1305" AEAD-style MAC Used with ChaCha20 - * "SipHash" Hash-based MAC Fast MAC for short inputs - * "BLAKE2BMAC" HMAC-style BLAKE2b MAC (cryptographic hash) - * "HmacRIPEMD160" HMAC HMAC with RIPEMD160 hash - */ - - bindingset[name] - predicate mac_names(string name) { - name.toUpperCase() - .matches([ - "HMAC%", "AESCMAC", "DESCMAC", "GMAC", "Poly1305", "SipHash", "BLAKE2BMAC", - "HMACRIPEMD160" - ].toUpperCase()) - } - - bindingset[name] - predicate mac_name_to_mac_type_known(Crypto::TMACType type, string name) { - type instanceof Crypto::THMAC and - name.toUpperCase().matches("HMAC%") - } - module MACKnownAlgorithmToConsumerConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { mac_names(src.asExpr().(StringLiteral).getValue()) } @@ -1140,8 +907,7 @@ module JCAModel { module MACInitCallToMACOperationFlow = DataFlow::Global; - class KnownMACAlgorithm extends JCAAlgorithmInstance, Crypto::MACAlgorithmInstance instanceof StringLiteral - { + class KnownMACAlgorithm extends Crypto::MACAlgorithmInstance instanceof StringLiteral { MACGetInstanceAlgorithmValueConsumer consumer; KnownMACAlgorithm() { @@ -1149,7 +915,7 @@ module JCAModel { MACKnownAlgorithmToConsumerFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) } - override MACGetInstanceAlgorithmValueConsumer getConsumer() { result = consumer } + MACGetInstanceAlgorithmValueConsumer getConsumer() { result = consumer } override string getRawMACAlgorithmName() { result = super.getValue() } @@ -1301,8 +1067,7 @@ module JCAModel { } } - class KDFAlgorithmStringLiteral extends JCAAlgorithmInstance, - Crypto::KeyDerivationAlgorithmInstance instanceof StringLiteral + class KDFAlgorithmStringLiteral extends Crypto::KeyDerivationAlgorithmInstance instanceof StringLiteral { SecretKeyFactoryKDFAlgorithmValueConsumer consumer; @@ -1317,10 +1082,10 @@ module JCAModel { result = kdf_name_to_kdf_type(super.getValue(), _) } - override SecretKeyFactoryKDFAlgorithmValueConsumer getConsumer() { result = consumer } + SecretKeyFactoryKDFAlgorithmValueConsumer getConsumer() { result = consumer } } - class PBKDF2AlgorithmStringLiteral extends JCAAlgorithmInstance, KDFAlgorithmStringLiteral, + class PBKDF2AlgorithmStringLiteral extends KDFAlgorithmStringLiteral, Crypto::PBKDF2AlgorithmInstance, Crypto::HMACAlgorithmInstance, Crypto::HashAlgorithmInstance, Crypto::AlgorithmValueConsumer { @@ -1421,5 +1186,132 @@ module JCAModel { override string getIterationCountFixed() { none() } } - // TODO: flow the GCGenParametersSpecCall to an init, and the init to the operations + + class KeyAgreementStringLiteral extends StringLiteral { + KeyAgreementStringLiteral() { key_agreement_names(this.getValue()) } + } + + /** + * Data-flow configuration modelling flow from a key agreement literal to a value consumer argument. + */ + private module KeyAgreementAlgorithmStringToFetchConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof KeyAgreementStringLiteral } + + predicate isSink(DataFlow::Node sink) { + exists(Crypto::AlgorithmValueConsumer consumer | sink = consumer.getInputNode()) + } + } + + module KeyAgreementAlgorithmStringToFetchFlow = + TaintTracking::Global; + + class KeyAgreementInitCall extends MethodCall { + KeyAgreementInitCall() { + this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "init") + } + + Expr getServerKeyArg() { result = this.getArgument(0) } + } + + private module KeyAgreementInitQualifierToSecretGenQualifierConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + exists(KeyAgreementInitCall init | src.asExpr() = init.getQualifier()) + } + + predicate isSink(DataFlow::Node sink) { + exists(KeyAgreementGenerateSecretCall c | sink.asExpr() = c.getQualifier()) + } + + /** + * Barrier if we go into another init, assume the second init overwrites the first + */ + predicate isBarrierIn(DataFlow::Node node) { isSource(node) } + } + + module KeyAgreementInitQualifierToSecretGenQualifierFlow = + DataFlow::Global; + + class KeyAgreementGetInstanceCall extends MethodCall { + KeyAgreementGetInstanceCall() { + this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "getInstance") + } + + Expr getAlgorithmArg() { result = super.getArgument(0) } + } + + class KeyAgreementAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { + KeyAgreementGetInstanceCall call; + + KeyAgreementAlgorithmValueConsumer() { this = call.getAlgorithmArg() } + + DataFlow::Node getResultNode() { result.asExpr() = call } + + override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } + + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + result.(KeyAgreementStringLiteralAlgorithmInstance).getConsumer() = this + } + } + + class KeyAgreementStringLiteralAlgorithmInstance extends Crypto::KeyAgreementAlgorithmInstance instanceof KeyAgreementStringLiteral + { + Crypto::AlgorithmValueConsumer consumer; + + KeyAgreementStringLiteralAlgorithmInstance() { + KeyAgreementAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) + } + + Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } + + override string getRawKeyAgreementAlgorithmName() { result = super.getValue() } + + override Crypto::TKeyAgreementType getKeyAgreementType() { + if key_agreement_name_to_type_known(_, super.getValue()) + then key_agreement_name_to_type_known(result, super.getValue()) + else result = Crypto::UnknownKeyAgreementType() + } + } + + class KeyAgreementGenerateSecretCall extends MethodCall { + KeyAgreementGenerateSecretCall() { + this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "generateSecret") + } + + KeyAgreementInitCall getKeyAgreementInitCall() { + KeyAgreementInitQualifierToSecretGenQualifierFlow::flow(DataFlow::exprNode(result + .getQualifier()), DataFlow::exprNode(this.getQualifier())) + } + } + + private module KeyAgreementAVCToInitQualifierConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + exists(KeyAgreementAlgorithmValueConsumer consumer | consumer.getResultNode() = src) + } + + predicate isSink(DataFlow::Node sink) { + exists(KeyAgreementInitCall init | sink.asExpr() = init.getQualifier()) + } + } + + module KeyAgreementAVCToInitQualifierFlow = + DataFlow::Global; + + class KeyAgreementSecretGenerationOperationInstance extends Crypto::KeyAgreementSecretGenerationOperationInstance instanceof KeyAgreementGenerateSecretCall + { + override Crypto::ConsumerInputDataFlowNode getServerKeyConsumer() { + this.(KeyAgreementGenerateSecretCall).getKeyAgreementInitCall().getServerKeyArg() = + result.asExpr() + } + + override Crypto::ConsumerInputDataFlowNode getPeerKeyConsumer() { + none() //TODO + } + + override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { + none() // TODO: key agreeement has its own algorithm consumer, separate from the key + // TODO: the char pred must trace from the consumer to here, + // in theory, along that path we would get the init and doPhase, but can I just get those + // separately avoiding a complicated config state for dataflow? + } + } } diff --git a/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql b/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql index 7fea3515b7dd..a9eb70076a0a 100644 --- a/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql +++ b/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql @@ -7,18 +7,17 @@ import experimental.Quantum.Language from - Crypto::NonceArtifactNode n, Crypto::CipherOperationNode op, Crypto::FlowAwareElement src, - string msg + Crypto::NonceArtifactNode n, Crypto::KeyOperationNode op, Crypto::FlowAwareElement src, string msg where op.getANonce() = n and // Only encryption mode is relevant for insecure nonces, consder any 'unknown' subtype // as possibly encryption. ( - op.getCipherOperationSubtype() instanceof Crypto::EncryptionSubtype + op.getKeyOperationSubtype() instanceof Crypto::EncryptionSubtype or - op.getCipherOperationSubtype() instanceof Crypto::WrapSubtype + op.getKeyOperationSubtype() instanceof Crypto::WrapSubtype or - op.getCipherOperationSubtype() instanceof Crypto::UnwrapSubtype + op.getKeyOperationSubtype() instanceof Crypto::UnwrapSubtype ) and ( // Known sources cases that are not secure diff --git a/java/ql/src/experimental/Quantum/PossibleReusedNonce.ql b/java/ql/src/experimental/Quantum/PossibleReusedNonce.ql index f9fc7a873db1..2263f05d56eb 100644 --- a/java/ql/src/experimental/Quantum/PossibleReusedNonce.ql +++ b/java/ql/src/experimental/Quantum/PossibleReusedNonce.ql @@ -8,9 +8,8 @@ import experimental.Quantum.Language import semmle.code.java.dataflow.DataFlow from - Crypto::CipherOperationNode op1, Crypto::CipherOperationNode op2, - Crypto::NonceArtifactNode nonce1, Crypto::NonceArtifactNode nonce2, Crypto::FlowAwareElement src1, - Crypto::FlowAwareElement src2 + Crypto::KeyOperationNode op1, Crypto::KeyOperationNode op2, Crypto::NonceArtifactNode nonce1, + Crypto::NonceArtifactNode nonce2, Crypto::FlowAwareElement src1, Crypto::FlowAwareElement src2 where // NOTE: not looking at value of the nonce, if we knew value, it would be insecure (hard coded) // Instead trying to find nonce sources that trace to multiple operations. @@ -18,14 +17,14 @@ where // (the encryption happened else where) or we are able to see the encryption and decryption operation and // reuse for encryption is the concern) ( - op1.getCipherOperationSubtype() instanceof Crypto::EncryptionSubtype or - op1.getCipherOperationSubtype() instanceof Crypto::WrapSubtype or - op1.getCipherOperationSubtype() instanceof Crypto::UnknownCipherOperationSubtype + op1.getKeyOperationSubtype() instanceof Crypto::EncryptionSubtype or + op1.getKeyOperationSubtype() instanceof Crypto::WrapSubtype or + op1.getKeyOperationSubtype() instanceof Crypto::UnknownCipherOperationSubtype ) and ( - op2.getCipherOperationSubtype() instanceof Crypto::EncryptionSubtype or - op2.getCipherOperationSubtype() instanceof Crypto::WrapSubtype or - op2.getCipherOperationSubtype() instanceof Crypto::UnknownCipherOperationSubtype + op2.getKeyOperationSubtype() instanceof Crypto::EncryptionSubtype or + op2.getKeyOperationSubtype() instanceof Crypto::WrapSubtype or + op2.getKeyOperationSubtype() instanceof Crypto::UnknownCipherOperationSubtype ) and nonce1 = op1.getANonce() and nonce2 = op2.getANonce() and diff --git a/java/ql/src/experimental/Quantum/TestCipher.ql b/java/ql/src/experimental/Quantum/TestCipher.ql index 8743ef3aa19b..d56e16804408 100644 --- a/java/ql/src/experimental/Quantum/TestCipher.ql +++ b/java/ql/src/experimental/Quantum/TestCipher.ql @@ -5,14 +5,14 @@ import experimental.Quantum.Language from - Crypto::CipherOperationNode op, Crypto::CipherAlgorithmNode a, + Crypto::CipherOperationNode op, Crypto::KeyOperationAlgorithmNode a, Crypto::ModeOfOperationAlgorithmNode m, Crypto::PaddingAlgorithmNode p, Crypto::NonceArtifactNode nonce, Crypto::KeyArtifactNode k where - a = op.getAKnownCipherAlgorithm() and + a = op.getAKnownAlgorithm() and m = a.getModeOfOperation() and p = a.getPaddingAlgorithm() and nonce = op.getANonce() and k = op.getAKey() -select op, op.getCipherOperationSubtype(), a, a.getRawAlgorithmName(), m, m.getRawAlgorithmName(), - p, p.getRawAlgorithmName(), nonce, k, k.getSourceElement() +select op, op.getKeyOperationSubtype(), a, a.getRawAlgorithmName(), m, m.getRawAlgorithmName(), p, + p.getRawAlgorithmName(), nonce, k, k.getSourceElement() diff --git a/java/ql/src/experimental/Quantum/TestCipherKey.ql b/java/ql/src/experimental/Quantum/TestCipherKey.ql index 1ae0cdfd89f0..c489320528d0 100644 --- a/java/ql/src/experimental/Quantum/TestCipherKey.ql +++ b/java/ql/src/experimental/Quantum/TestCipherKey.ql @@ -4,11 +4,11 @@ import experimental.Quantum.Language -from Crypto::CipherOperationNode op, Crypto::CipherAlgorithmNode a, Crypto::KeyArtifactNode k +from Crypto::KeyOperationNode op, Crypto::CipherAlgorithmNode a, Crypto::KeyArtifactNode k where a = op.getAKnownCipherAlgorithm() and k = op.getAKey() -select op, op.getCipherOperationSubtype(), a, a.getRawAlgorithmName(), k, k.getSourceNode() +select op, op.getKeyOperationSubtype(), a, a.getRawAlgorithmName(), k, k.getSourceNode() /* * from Crypto::CipherOperationNode op * where op.getLocation().getFile().getBaseName() = "AsymmetricEncryptionMacHybridCryptosystem.java" diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index fe397c6247f3..782c53e1043f 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -334,7 +334,6 @@ module CryptographyBase Input> { */ abstract class ArtifactConsumer extends ConsumerElement { /** - * DO NOT USE: * Use `getAKnownArtifactSource() instead. The behaviour of these two predicates is equivalent. */ final override KnownElement getAKnownSource() { result = this.getAKnownArtifactSource() } @@ -348,26 +347,22 @@ module CryptographyBase Input> { * For example: * A `NonceArtifactConsumer` is always the `NonceArtifactInstance` itself, since data only becomes (i.e., is determined to be) * a `NonceArtifactInstance` when it is consumed in a context that expects a nonce (e.g., an argument expecting nonce data). - * In this case, the artifact (nonce) is fully defined by the context in which it is consumed, and the consumer embodies + * + * In this case, the artifact (nonce) is fully defined by the context in which it is consumed, and the consumer embodies * that identity without the need for additional differentiation. Without the context a consumer provides, that data could * otherwise be any other type of artifact or even simply random data. * - * TODO: what if a Nonce from hypothetical func `generateNonce()` flows to this instance which is also a Nonce? - * TODO: potential solution is creating another artifact type called NonceData or treating it as a generic source. - * - * TODO: An alternative is simply having a predicate DataFlowNode getNonceInputNode() on (for example) operations. - * Under the hood, in Model.qll, we would create the instance for the modeller, thus avoiding the need for the modeller - * to create a separate consumer class / instance themselves using this class. + * This class is used to create synthetic nodes for the artifact at any place where it is consumed. */ abstract private class ArtifactConsumerAndInstance extends ArtifactConsumer, ArtifactInstance { - override predicate isConsumerArtifact() { any() } + final override predicate isConsumerArtifact() { any() } } final private class NonceArtifactConsumer extends ArtifactConsumerAndInstance { ConsumerInputDataFlowNode inputNode; NonceArtifactConsumer() { - exists(CipherOperationInstance op | inputNode = op.getNonceConsumer()) and + exists(KeyOperationInstance op | inputNode = op.getNonceConsumer()) and this = Input::dfn_to_element(inputNode) } @@ -379,7 +374,7 @@ module CryptographyBase Input> { MessageArtifactConsumer() { ( - exists(CipherOperationInstance op | inputNode = op.getInputConsumer()) + exists(KeyOperationInstance op | inputNode = op.getInputConsumer()) or exists(KeyDerivationOperationInstance op | inputNode = op.getInputConsumer()) or @@ -402,7 +397,9 @@ module CryptographyBase Input> { final override ConsumerInputDataFlowNode getInputNode() { result = inputNode } } - // Output artifacts are determined solely by the element that produces them. + /** + * An artifact that is produced by an operation, representing a concrete artifact instance rather than a synthetic consumer artifact. + */ abstract class OutputArtifactInstance extends ArtifactInstance { override predicate isConsumerArtifact() { none() } @@ -413,13 +410,33 @@ module CryptographyBase Input> { } } + /** + * An artifact representing a hash function's digest output. + */ abstract class DigestArtifactInstance extends OutputArtifactInstance { } + /** + * An artifact representing a random number generator's output. + */ abstract class RandomNumberGenerationInstance extends OutputArtifactInstance { // TODO: input seed? } - abstract class CipherOutputArtifactInstance extends OutputArtifactInstance { } + /** + * An artifact representing a key operation's output, e.g.: + * 1. Encryption/decryption output (ciphertext or plaintext) + * 1. Signing output (signature) + * 1. Key encapsulation output (wrapped or unwrapped key) + */ + final class KeyOperationOutputArtifactInstance extends OutputArtifactInstance { + KeyOperationInstance creator; + + KeyOperationOutputArtifactInstance() { + Input::dfn_to_element(creator.getOutputArtifact()) = this + } + + override DataFlowNode getOutputNode() { result = creator.getOutputArtifact() } + } // Artifacts that may be outputs or inputs newtype TKeyArtifactType = @@ -459,7 +476,7 @@ module CryptographyBase Input> { // TODO: key type hint? e.g. hint: private || public KeyArtifactConsumer() { ( - exists(CipherOperationInstance op | inputNode = op.getKeyConsumer()) or + exists(KeyOperationInstance op | inputNode = op.getKeyConsumer()) or exists(MACOperationInstance op | inputNode = op.getKeyConsumer()) ) and this = Input::dfn_to_element(inputNode) @@ -471,68 +488,291 @@ module CryptographyBase Input> { } /** - * A cipher operation instance, such as encryption or decryption. + * The `KeyOpAlg` module defines key operation algorithms types (e.g., symmetric ciphers, signatures, etc.) + * and provides mapping of those types to string names and structural properties. */ - abstract class CipherOperationInstance extends OperationInstance { + module KeyOpAlg { /** - * Gets the subtype of this cipher operation, distinguishing encryption, decryption, key wrapping, and key unwrapping. + * An algorithm used in key operations. */ - abstract CipherOperationSubtype getCipherOperationSubtype(); + newtype TAlgorithm = + TSymmetricCipher(TSymmetricCipherType t) or + TAsymmetricCipher(TAsymmetricCipherType t) or + TSignature(TSignatureAlgorithmType t) or + TKeyEncapsulation(TKEMAlgorithmType t) or + TUnknownKeyOperationAlgorithmType() + + // Parameterized algorithm types + newtype TSymmetricCipherType = + AES() or + ARIA() or + BLOWFISH() or + CAMELLIA() or + CAST5() or + CHACHA20() or + DES() or + DESX() or + GOST() or + IDEA() or + KUZNYECHIK() or + MAGMA() or + TripleDES() or + DoubleDES() or + RC2() or + RC4() or + RC5() or + SEED() or + SM4() or + OtherSymmetricCipherType() + + newtype TAsymmetricCipherType = + RSA() or + OtherAsymmetricCipherType() + + newtype TSignatureAlgorithmType = + DSA() or + ECDSA() or + Ed25519() or + Ed448() or + OtherSignatureAlgorithmType() + + newtype TKEMAlgorithmType = + Kyber() or + FrodoKEM() or + OtherKEMAlgorithmType() + + newtype TCipherStructureType = + Block() or + Stream() or + UnknownCipherStructureType() + + class CipherStructureType extends TCipherStructureType { + string toString() { + result = "Block" and this = Block() + or + result = "Stream" and this = Stream() + or + result = "Unknown" and this = UnknownCipherStructureType() + } + } + + bindingset[type] + predicate symmetric_cipher_to_name_and_structure( + TSymmetricCipherType type, string name, CipherStructureType s + ) { + type = AES() and name = "AES" and s = Block() + or + type = ARIA() and name = "ARIA" and s = Block() + or + type = BLOWFISH() and name = "Blowfish" and s = Block() + or + type = CAMELLIA() and name = "Camellia" and s = Block() + or + type = CAST5() and name = "CAST5" and s = Block() + or + type = CHACHA20() and name = "ChaCha20" and s = Stream() + or + type = DES() and name = "DES" and s = Block() + or + type = DESX() and name = "DESX" and s = Block() + or + type = GOST() and name = "GOST" and s = Block() + or + type = IDEA() and name = "IDEA" and s = Block() + or + type = KUZNYECHIK() and name = "Kuznyechik" and s = Block() + or + type = MAGMA() and name = "Magma" and s = Block() + or + type = TripleDES() and name = "TripleDES" and s = Block() + or + type = DoubleDES() and name = "DoubleDES" and s = Block() + or + type = RC2() and name = "RC2" and s = Block() + or + type = RC4() and name = "RC4" and s = Stream() + or + type = RC5() and name = "RC5" and s = Block() + or + type = SEED() and name = "SEED" and s = Block() + or + type = SM4() and name = "SM4" and s = Block() + or + type = OtherSymmetricCipherType() and + name = "UnknownSymmetricCipher" and + s = UnknownCipherStructureType() + } + + bindingset[type] + predicate type_to_name(Algorithm type, string name) { + // Symmetric cipher algorithm + symmetric_cipher_to_name_and_structure(type.(SymmetricCipherAlgorithm).getType(), name, _) + or + // Asymmetric cipher algorithms + type = TAsymmetricCipher(RSA()) and name = "RSA" + or + type = TAsymmetricCipher(OtherAsymmetricCipherType()) and name = "UnknownAsymmetricCipher" + or + // Signature algorithms + type = TSignature(DSA()) and name = "DSA" + or + type = TSignature(ECDSA()) and name = "ECDSA" + or + type = TSignature(Ed25519()) and name = "Ed25519" + or + type = TSignature(Ed448()) and name = "Ed448" + or + type = TSignature(OtherSignatureAlgorithmType()) and name = "UnknownSignature" + or + // Key Encapsulation Mechanisms + type = TKeyEncapsulation(Kyber()) and name = "Kyber" + or + type = TKeyEncapsulation(FrodoKEM()) and name = "FrodoKEM" + or + type = TKeyEncapsulation(OtherKEMAlgorithmType()) and name = "UnknownKEM" + or + // Unknown + type = TUnknownKeyOperationAlgorithmType() and name = "Unknown" + } + + class Algorithm extends TAlgorithm { + string toString() { type_to_name(this, result) } + } + + class SymmetricCipherAlgorithm extends Algorithm, TSymmetricCipher { + TSymmetricCipherType type; + + SymmetricCipherAlgorithm() { this = TSymmetricCipher(type) } + + TSymmetricCipherType getType() { result = type } + } + } + + /** + * A key-based cryptographic operation instance, encompassing: + * 1. **Ciphers**: Encryption and decryption, both symmetric and asymmetric + * 1. **Signing**: Signing and verifying, **NOT** including MACs (see `MACOperationInstance`) + * 1. **Key encapsulation**: Key wrapping and unwrapping + * + * This class represents a generic key operation that transforms input data + * using a cryptographic key, producing an output artifact such as ciphertext, + * plaintext, a signature, or an (un-)wrapped key. + */ + abstract class KeyOperationInstance extends OperationInstance { + final KeyOperationOutputArtifactInstance getOutputArtifactInstance() { + result.getOutputNode() = this.getOutputArtifact() + } /** - * Gets the consumer of nonces/IVs associated with this cipher operation. + * Gets the subtype of this key operation, distinguishing operations such as + * encryption, decryption, signing, verification, key wrapping, and key unwrapping. */ - abstract ConsumerInputDataFlowNode getNonceConsumer(); + abstract KeyOperationSubtype getKeyOperationSubtype(); /** - * Gets the consumer of plaintext or ciphertext input associated with this cipher operation. + * Gets the consumer of the cryptographic key used in this key operation. + * The key may be symmetric or asymmetric, depending on the operation subtype. */ - abstract ConsumerInputDataFlowNode getInputConsumer(); + abstract ConsumerInputDataFlowNode getKeyConsumer(); /** - * Gets the consumer of a key. + * Gets the consumer of nonces or initialization vectors (IVs) associated with this key operation. + * These are typically required for encryption, AEAD, or wrap modes. + * + * If the operation does not require a nonce, this predicate should be implemented as `none()`. */ - abstract ConsumerInputDataFlowNode getKeyConsumer(); + abstract ConsumerInputDataFlowNode getNonceConsumer(); /** - * Gets the output artifact of this cipher operation. + * Gets the consumer of the primary message input for this key operation. + * For example: plaintext (for encryption), ciphertext (for decryption), + * message to be signed, or wrapped key to be unwrapped. + */ + abstract ConsumerInputDataFlowNode getInputConsumer(); + + /** + * Gets the output artifact produced by this key operation. + * This may represent ciphertext, a digital signature, a wrapped key, or any + * other data resulting from the operation. * * Implementation guidelines: - * 1. Each unique output target should have an artifact. - * 1. Discarded outputs from intermittent calls should not be artifacts. + * 1. Each semantically meaningful output should result in an artifact. + * 2. Discarded or transient intermediate values should not be artifacts. */ - abstract CipherOutputArtifactInstance getOutputArtifact(); + abstract ArtifactOutputDataFlowNode getOutputArtifact(); } - abstract class CipherAlgorithmInstance extends AlgorithmInstance { + /** + * A key-based algorithm instance used in cryptographic operations such as encryption, decryption, + * signing, verification, and key wrapping. + */ + abstract class KeyOperationAlgorithmInstance extends AlgorithmInstance { /** - * Gets the raw name as it appears in source, e.g., "AES/CBC/PKCS7Padding". - * This name is not parsed or formatted. + * Gets the raw algorithm name as provided in source, e.g., "AES/CBC/PKCS7Padding". + * This name is not parsed or normalized. */ - abstract string getRawCipherAlgorithmName(); + abstract string getRawAlgorithmName(); /** - * Gets the type of this cipher, e.g., "AES" or "ChaCha20". + * Gets the key operation algorithm type, e.g., `TSignature(Ed25519())` or `TSymmetricCipher(AES())`. + * + * If the category of algorithm is known, but the precise algorithm is not, the following type hints should be used: + * - `TSymmetricCipher(OtherSymmetricCipherType())` + * - `TAsymmetricCipher(OtherAsymmetricCipherType())` + * - `TSignature(OtherSignatureAlgorithmType())` + * - `TKeyEncapsulation(OtherKEMAlgorithmType())` + * + * If the category of algorithm is not known, the following type should be used: + * - `TUnknownKeyOperationAlgorithmType()` + * + * This predicate should always hold. */ - abstract TCipherType getCipherFamily(); + abstract KeyOpAlg::Algorithm getAlgorithmType(); /** - * Gets the mode of operation of this cipher, e.g., "GCM" or "CBC". + * Gets the mode of operation, such as "CBC", "GCM", or "ECB". * - * IMPLEMENTATION NOTE: as a tradeoff, this is not a consumer but always either an instance or unknown. - * A mode of operation is therefore assumed to always be part of the cipher algorithm itself. + * Edge-cases and modeling guidance: + * - Mode of operation not identifiable: result is `none()`. + * - No mode possible (e.g., RSA, DSA, or ChaCha20): result is `none()`. + * - Mode of operation explicitly specified as none: result is `ModeOfOperationAlgorithmInstance`. + * + * IMPLEMENTATION NOTE: This is treated as part of the algorithm identity and + * not modeled as a separate algorithm value consumer. */ abstract ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm(); /** - * Gets the padding scheme of this cipher, e.g., "PKCS7" or "NoPadding". + * Gets the padding scheme, such as "PKCS7", "OAEP", or "NoPadding". * - * IMPLEMENTATION NOTE: as a tradeoff, this is not a consumer but always either an instance or unknown. - * A padding algorithm is therefore assumed to always be defined as part of the cipher algorithm itself. + * See the modeling guidance for `getModeOfOperationAlgorithm` for modeling guidance. */ abstract PaddingAlgorithmInstance getPaddingAlgorithm(); + + /** + * Gets the key size in bits specified for this algorithm variant, for example, "128" for "AES-128". This predicate is only + * necessary to specify if there are multiple variants of the algorithm defined by key size and a specific key size is known. + * + * If a specific key size is unknown, this predicate should be implemented as `none()`. + * + * If the algorithm accepts a range of key sizes without a particular one specified, this predicate should be implemented as `none()`. + */ + abstract string getKeySize(); } + newtype TBlockCipherModeOfOperationType = + ECB() or // Not secure, widely used + CBC() or // Vulnerable to padding oracle attacks + CFB() or + GCM() or // Widely used AEAD mode (TLS 1.3, SSH, IPsec) + CTR() or // Fast stream-like encryption (SSH, disk encryption) + XTS() or // Standard for full-disk encryption (BitLocker, LUKS, FileVault) + CCM() or // Used in lightweight cryptography (IoT, WPA2) + SIV() or // Misuse-resistant encryption, used in secure storage + OCB() or // Efficient AEAD mode + OFB() or + OtherMode() + abstract class ModeOfOperationAlgorithmInstance extends AlgorithmInstance { /** * Gets the type of this mode of operation, e.g., "ECB" or "CBC". @@ -541,7 +781,7 @@ module CryptographyBase Input> { * * If a type cannot be determined, the result is `OtherMode`. */ - abstract TBlockCipherModeOperationType getModeType(); + abstract TBlockCipherModeOfOperationType getModeType(); /** * Gets the isolated name as it appears in source, e.g., "CBC" in "AES/CBC/PKCS7Padding". @@ -570,7 +810,7 @@ module CryptographyBase Input> { } abstract class OAEPPaddingAlgorithmInstance extends PaddingAlgorithmInstance { - OAEPPaddingAlgorithmInstance() { this.getPaddingType() = OAEP() } + OAEPPaddingAlgorithmInstance() { this.getPaddingType() instanceof OAEP } /** * Gets the hash algorithm used in this padding scheme. @@ -585,6 +825,7 @@ module CryptographyBase Input> { newtype TMACType = THMAC() or + TCMAC() or TOtherMACType() abstract class MACAlgorithmInstance extends AlgorithmInstance { @@ -622,33 +863,31 @@ module CryptographyBase Input> { abstract AlgorithmValueConsumer getHashAlgorithmValueConsumer(); } - abstract class KeyEncapsulationOperationInstance extends OperationInstance { } - - abstract class KeyEncapsulationAlgorithmInstance extends AlgorithmInstance { } - - abstract class EllipticCurveAlgorithmInstance extends AlgorithmInstance { + abstract class EllipticCurveInstance extends AlgorithmInstance { /** * Gets the isolated name as it appears in source * * This name should not be parsed or formatted beyond isolating the raw name if necessary. */ - abstract string getRawEllipticCurveAlgorithmName(); + abstract string getRawEllipticCurveName(); + + abstract TEllipticCurveType getEllipticCurveFamily(); + + abstract string getKeySize(); /** - * The 'standard' curve name, e.g., "P-256" or "secp256r1". - * meaning the full name of the curve, including the family, key size, and other - * typical parameters found on the name. In many cases this will - * be equivalent to `getRawEllipticCurveAlgorithmName()`, but not always - * (e.g., if the curve is specified through a raw NID). + * The 'parsed' curve name, e.g., "P-256" or "secp256r1" + * The parsed name is full name of the curve, including the family, key size, and other + * typical parameters found on the name. + * + * In many cases this will be equivalent to `getRawEllipticCurveAlgorithmName()`, + * but not always (e.g., if the curve is specified through a raw NID). + * * In cases like an NID, we want the standardized name so users can quickly * understand what the curve is, while also parsing out the family and key size * separately. */ - abstract string getStandardCurveName(); - - abstract TEllipticCurveType getEllipticCurveFamily(); - - abstract string getKeySize(); + string getParsedEllipticCurveName() { result = this.getRawEllipticCurveName() } } abstract class HashOperationInstance extends OperationInstance { @@ -686,7 +925,7 @@ module CryptographyBase Input> { abstract KeyArtifactType getOutputKeyType(); // Defaults or fixed values - abstract string getKeySizeFixed(); + string getKeySizeFixed() { none() } // Consumer input nodes abstract ConsumerInputDataFlowNode getKeySizeConsumer(); @@ -702,9 +941,9 @@ module CryptographyBase Input> { final override string getKeyCreationTypeDescription() { result = "KeyDerivation" } // Defaults or fixed values - abstract string getIterationCountFixed(); + string getIterationCountFixed() { none() } - abstract string getOutputKeySizeFixed(); + string getOutputKeySizeFixed() { none() } // Generic consumer input nodes abstract ConsumerInputDataFlowNode getIterationCountConsumer(); @@ -722,6 +961,7 @@ module CryptographyBase Input> { PBES() or HKDF() or ARGON2() or + SCRYPT() or OtherKeyDerivationType() abstract class KeyDerivationAlgorithmInstance extends AlgorithmInstance { @@ -748,6 +988,18 @@ module CryptographyBase Input> { abstract AlgorithmValueConsumer getHMACAlgorithmValueConsumer(); } + abstract class ScryptAlgorithmInstance extends KeyDerivationAlgorithmInstance { + ScryptAlgorithmInstance() { this.getKDFType() instanceof SCRYPT } + + /** + * Gets the HMAC algorithm used by this PBKDF2 algorithm. + * + * Note: Other PRFs are not supported, as most cryptographic libraries + * only support HMAC for PBKDF2's PRF input. + */ + abstract AlgorithmValueConsumer getHMACAlgorithmValueConsumer(); + } + abstract class KeyGenerationOperationInstance extends KeyCreationOperationInstance { final override string getKeyCreationTypeDescription() { result = "KeyGeneration" } } @@ -756,10 +1008,55 @@ module CryptographyBase Input> { final override string getKeyCreationTypeDescription() { result = "KeyLoad" } } + // Key agreement algorithms + newtype TKeyAgreementType = + DH() or // Diffie-Hellman + EDH() or // Ephemeral Diffie-Hellman + ECDH() or // Elliptic Curve Diffie-Hellman + // Note: x25519 and x448 are applications of ECDH + UnknownKeyAgreementType() + + abstract class KeyAgreementAlgorithmInstance extends AlgorithmInstance { + abstract TKeyAgreementType getKeyAgreementType(); + + abstract string getRawKeyAgreementAlgorithmName(); + } + + abstract class ECDHKeyAgreementAlgorithmInstance extends KeyAgreementAlgorithmInstance { + ECDHKeyAgreementAlgorithmInstance() { this.getKeyAgreementType() instanceof ECDH } + + /** + * Gets the consumer for the elliptic curve used in the key agreement operation. + */ + abstract AlgorithmValueConsumer getEllipticCurveAlgorithmValueConsumer(); + } + + abstract class KeyAgreementSecretGenerationOperationInstance extends OperationInstance { + /** + * The private key used in the key agreement operation. + * This key represents the local party in the key agreement. + */ + abstract ConsumerInputDataFlowNode getServerKeyConsumer(); + + /** + * The public key used in the key agreement operation, coming + * from the peer (the other party in the key agreement). + */ + abstract ConsumerInputDataFlowNode getPeerKeyConsumer(); + } + private signature class AlgorithmInstanceType instanceof AlgorithmInstance; private signature predicate isCandidateAVCSig(AlgorithmValueConsumer avc); + /** + * An element that is either an `AlgorithmInstance` or an `AlgorithmValueConsumer` with no known sources. + * + * This concept is used to model consumers that have no known source as an algorithm node. + * + * The `isCandidateAVCSig` predicate is used to restrict the set of consumers that expect inputs of `AlgorithmInstanceType`. + * These "total unknown" algorithm nodes would otherwise not exist if not modelled as a consumer node. + */ module AlgorithmInstanceOrValueConsumer< AlgorithmInstanceType Alg, isCandidateAVCSig/1 isCandidateAVC> { @@ -785,8 +1082,8 @@ module CryptographyBase Input> { exists(HMACAlgorithmInstance alg | avc = alg.getAConsumer()) } - private predicate isCipherAVC(AlgorithmValueConsumer avc) { - exists(CipherOperationInstance op | op.getAnAlgorithmValueConsumer() = avc) + private predicate isKeyOperationAlgorithmAVC(AlgorithmValueConsumer avc) { + exists(KeyOperationInstance op | op.getAnAlgorithmValueConsumer() = avc) } private predicate isMACAVC(AlgorithmValueConsumer avc) { @@ -798,8 +1095,14 @@ module CryptographyBase Input> { exists(KeyDerivationOperationInstance op | op.getAnAlgorithmValueConsumer() = avc) } - final private class CipherAlgorithmInstanceOrValueConsumer = - AlgorithmInstanceOrValueConsumer::Union; + private predicate isEllipticCurveAVC(AlgorithmValueConsumer avc) { + exists(ECDHKeyAgreementAlgorithmInstance alg | + avc = alg.getEllipticCurveAlgorithmValueConsumer() + ) + } + + final private class KeyOperationAlgorithmInstanceOrValueConsumer = + AlgorithmInstanceOrValueConsumer::Union; final private class HashAlgorithmInstanceOrValueConsumer = AlgorithmInstanceOrValueConsumer::Union; @@ -810,51 +1113,47 @@ module CryptographyBase Input> { final private class KeyDerivationAlgorithmInstanceOrValueConsumer = AlgorithmInstanceOrValueConsumer::Union; - final private class EllipticCurveAlgorithmInstanceOrValueConsumer = - AlgorithmInstanceOrValueConsumer::Union; + final private class EllipticCurveInstanceOrValueConsumer = + AlgorithmInstanceOrValueConsumer::Union; private newtype TNode = - // Artifacts (data that is not an operation or algorithm, e.g., a key) + // Output artifacts (data that is not an operation or algorithm, e.g., a key) TDigest(DigestArtifactInstance e) or TKey(KeyArtifactInstance e) or - TCipherOutput(CipherOutputArtifactInstance e) or - // Input artifact nodes (synthetic, used to differentiate input as entities) + // Input artifacts (synthetic nodes, used to differentiate input as entities) TNonceInput(NonceArtifactConsumer e) or TMessageInput(MessageArtifactConsumer e) or TSaltInput(SaltArtifactConsumer e) or TRandomNumberGeneration(RandomNumberGenerationInstance e) { e.flowsTo(_) } or - // Operations (e.g., hashing, encryption) + // Key Creation Operation union type (e.g., key generation, key load) + TKeyCreationOperation(KeyCreationOperationInstance e) or + // Key operations, algorithms, and artifacts + // These types are union types of encryption, signing, encapsulation and their algorithms/artifacts. + // The artifacts are the outputs, e.g., ciphertext, signature, wrapped key. + TKeyOperation(KeyOperationInstance e) or + TKeyOperationAlgorithm(KeyOperationAlgorithmInstanceOrValueConsumer e) or + TKeyOperationOutput(KeyOperationOutputArtifactInstance e) or + // Non-Standalone Algorithms (e.g., Mode, Padding) + // These algorithms are always tied to a key operation algorithm + TModeOfOperationAlgorithm(ModeOfOperationAlgorithmInstance e) or + TPaddingAlgorithm(PaddingAlgorithmInstance e) or + // All other operations THashOperation(HashOperationInstance e) or - TCipherOperation(CipherOperationInstance e) or - TKeyEncapsulationOperation(KeyEncapsulationOperationInstance e) or TMACOperation(MACOperationInstance e) or - // Key Creation Operations - TKeyCreationOperation(KeyCreationOperationInstance e) or - // Algorithms (e.g., SHA-256, AES) - TCipherAlgorithm(CipherAlgorithmInstanceOrValueConsumer e) or - TEllipticCurveAlgorithm(EllipticCurveAlgorithmInstanceOrValueConsumer e) or + // All other algorithms + TEllipticCurve(EllipticCurveInstanceOrValueConsumer e) or THashAlgorithm(HashAlgorithmInstanceOrValueConsumer e) or TKeyDerivationAlgorithm(KeyDerivationAlgorithmInstanceOrValueConsumer e) or - TKeyEncapsulationAlgorithm(KeyEncapsulationAlgorithmInstance e) or TMACAlgorithm(MACAlgorithmInstanceOrValueConsumer e) or TKeyAgreementAlgorithm(KeyAgreementAlgorithmInstance e) or - // Non-standalone Algorithms (e.g., Mode, Padding) - // TODO: need to rename this, as "mode" is getting reused in different contexts, be precise - TModeOfOperationAlgorithm(ModeOfOperationAlgorithmInstance e) or - TPaddingAlgorithm(PaddingAlgorithmInstance e) or - // Composite and hybrid cryptosystems (e.g., RSA-OAEP used with AES, post-quantum hybrid cryptosystems) - // These nodes are always parent nodes and are not modeled but rather defined via library-agnostic patterns. - TKemDemHybridCryptosystem(CipherAlgorithmNode dem) or // TODO, change this relation and the below ones - TKeyAgreementHybridCryptosystem(CipherAlgorithmInstance ka) or - TAsymmetricEncryptionMacHybridCryptosystem(CipherAlgorithmInstance enc) or - TPostQuantumHybridCryptosystem(CipherAlgorithmInstance enc) or - // Generic source nodes + // Generic source nodes, i.e., sources of data that are not resolvable to a specific known asset. TGenericSourceNode(GenericSourceInstance e) { // An element modelled as a `GenericSourceInstance` can also be modelled as a `KnownElement` // For example, a string literal "AES" could be a generic constant but also an algorithm instance. - // Only create generic nodes tied to instances which are not also a `KnownElement`. + // + // Therefore, only create generic nodes tied to instances which are not also a `KnownElement`... not e instanceof KnownElement and - // Only create nodes for generic sources which flow to other elements + // ... and that flow to other elements e.flowsTo(_) } @@ -863,25 +1162,8 @@ module CryptographyBase Input> { * * Each `NodeBase` is a node in a graph of cryptographic operations, where the edges are the relationships between the nodes. * - * A node, as opposed to a property, is a construct that can reference or be referenced by more than one node. - * For example: a key size is a single value configuring a cipher algorithm, but a single mode of operation algorithm - * can be referenced by multiple disjoint cipher algorithms. For example, even if the same key size value is reused - * for multiple cipher algorithms, the key size holds no information when devolved to that simple value, and it is - * therefore not a "construct" or "element" being reused by multiple nodes. - * - * As a rule of thumb, a node is an algorithm or the use of an algorithm (an operation), as well as structured data - * consumed by or produced by an operation or algorithm (an artifact) that represents a construct beyond its data. - * - * _Example 1_: A seed of a random number generation algorithm has meaning beyond its value, as its reuse in multiple - * random number generation algorithms is more relevant than its underlying value. In contrast, a key size is only - * relevant to analysis in terms of its underlying value. Therefore, an RNG seed is a node; a key size is not. However, - * the key size might have a `GenericSourceNode` source, even if it itself is not a node. - * - * _Example 2_: A salt for a key derivation function *is* an `ArtifactNode`. - * - * _Example 3_: The iteration count of a key derivation function is *not* a node, but it may link to a generic node. - * - * _Example 4_: A nonce for a cipher operation *is* an `ArtifactNode`. + * As a rule of thumb, a node is an algorithm or the use of an algorithm (an operation), as well as structured data (an artifact) + * consumed by or produced by an operation or algorithm. */ abstract class NodeBase extends TNode { /** @@ -1057,7 +1339,7 @@ module CryptographyBase Input> { } /** - * A nonce or initialization vector input + * A nonce or initialization vector input. */ final class NonceArtifactNode extends ArtifactNode, TNonceInput { NonceArtifactConsumer instance; @@ -1070,7 +1352,7 @@ module CryptographyBase Input> { } /** - * A message or plaintext/ciphertext input + * A message or plaintext/ciphertext input. */ final class MessageArtifactNode extends ArtifactNode, TMessageInput { MessageArtifactConsumer instance; @@ -1083,7 +1365,7 @@ module CryptographyBase Input> { } /** - * A salt input + * A salt input. */ final class SaltArtifactNode extends ArtifactNode, TSaltInput { SaltArtifactConsumer instance; @@ -1096,14 +1378,16 @@ module CryptographyBase Input> { } /** - * Output text from a cipher operation + * The base class for output nodes from key operations. + * + * This class represents the output of key generation, key derivation, encryption, decryption, signing, and verification. */ - final class CipherOutputNode extends ArtifactNode, TCipherOutput { - CipherOutputArtifactInstance instance; + class KeyOperationOutputNode extends ArtifactNode, TKeyOperationOutput { + KeyOperationOutputArtifactInstance instance; - CipherOutputNode() { this = TCipherOutput(instance) } + KeyOperationOutputNode() { this = TKeyOperationOutput(instance) } - final override string getInternalType() { result = "CipherOutput" } + final override string getInternalType() { result = "KeyOperationOutput" } override LocatableElement asElement() { result = instance } @@ -1111,7 +1395,7 @@ module CryptographyBase Input> { } /** - * A source of random number generation + * A source of random number generation. */ final class RandomNumberGenerationNode extends ArtifactNode, TRandomNumberGeneration { RandomNumberGenerationInstance instance; @@ -1125,6 +1409,22 @@ module CryptographyBase Input> { override string getSourceNodeRelationship() { none() } // TODO: seed? } + /** + * A union type of all algorithm types that can be used in key creation operations. + */ + class TKeyCreationCandidateAlgorithm = + TKeyOperationAlgorithm or TEllipticCurve or TKeyAgreementAlgorithm or TKeyDerivationAlgorithm; + + /** + * A candidate algorithm node for key creation. + * + * Note: This is not an independent node type, but a subset of `AlgorithmNode` that is of type `TKeyCreationCandidateAlgorithm`. + */ + private class KeyCreationCandidateAlgorithmNode extends TKeyCreationCandidateAlgorithm instanceof AlgorithmNode + { + string toString() { result = super.getAlgorithmName() } + } + /** * A cryptographic key, such as a symmetric key or asymmetric key pair. */ @@ -1146,7 +1446,7 @@ module CryptographyBase Input> { .getAGenericSourceNode() } - CipherAlgorithmNode getAKnownAlgorithm() { + KeyCreationCandidateAlgorithmNode getAKnownAlgorithm() { result = instance.(KeyCreationOperationInstance).getAnAlgorithmValueConsumer().getAKnownSourceNode() } @@ -1180,7 +1480,7 @@ module CryptographyBase Input> { } /** - * A digest produced by a hash operation. + * A digest artifact produced by a hash operation. */ final class DigestArtifactNode extends ArtifactNode, TDigest { DigestArtifactInstance instance; @@ -1305,7 +1605,7 @@ module CryptographyBase Input> { KeyGenerationOperationNode() { keyGenInstance = instance } override predicate isCandidateAlgorithmNode(AlgorithmNode node) { - node instanceof CipherAlgorithmNode + node instanceof KeyCreationCandidateAlgorithmNode } override NodeBase getChild(string key) { @@ -1390,7 +1690,7 @@ module CryptographyBase Input> { result = instance.asAlg().getRawKDFAlgorithmName() } - final override string getAlgorithmName() { result = this.getRawAlgorithmName() } + override string getAlgorithmName() { result = this.getRawAlgorithmName() } // TODO: standardize? } /** @@ -1414,195 +1714,97 @@ module CryptographyBase Input> { } } - // /** - // * PKCS12KDF key derivation function - // */ - // abstract class PKCS12KDF extends KeyDerivationWithDigestParameterNode { - // override string getAlgorithmName() { result = "PKCS12KDF" } - // /** - // * Gets the iteration count of this key derivation algorithm. - // */ - // abstract string getIterationCount(Location location); - // /** - // * Gets the raw ID argument specifying the intended use of the derived key. - // * - // * The intended use is defined in RFC 7292, appendix B.3, as follows: - // * - // * This standard specifies 3 different values for the ID byte mentioned above: - // * - // * 1. If ID=1, then the pseudorandom bits being produced are to be used - // * as key material for performing encryption or decryption. - // * - // * 2. If ID=2, then the pseudorandom bits being produced are to be used - // * as an IV (Initial Value) for encryption or decryption. - // * - // * 3. If ID=3, then the pseudorandom bits being produced are to be used - // * as an integrity key for MACing. - // */ - // abstract string getIDByte(Location location); - // override predicate properties(string key, string value, Location location) { - // super.properties(key, value, location) - // or - // ( - // // [KNOWN_OR_UNKNOWN] - // key = "Iterations" and - // if exists(this.getIterationCount(location)) - // then value = this.getIterationCount(location) - // else ( - // value instanceof UnknownPropertyValue and location instanceof UnknownLocation - // ) - // ) - // or - // ( - // // [KNOWN_OR_UNKNOWN] - // key = "IdByte" and - // if exists(this.getIDByte(location)) - // then value = this.getIDByte(location) - // else ( - // value instanceof UnknownPropertyValue and location instanceof UnknownLocation - // ) - // ) - // } - // } - // /** - // * scrypt key derivation function - // */ - // abstract class SCRYPT extends KeyDerivationAlgorithmNode { - // final override string getAlgorithmName() { result = "scrypt" } - // /** - // * Gets the iteration count (`N`) argument - // */ - // abstract string get_N(Location location); - // /** - // * Gets the block size (`r`) argument - // */ - // abstract string get_r(Location location); - // /** - // * Gets the parallelization factor (`p`) argument - // */ - // abstract string get_p(Location location); - // /** - // * Gets the derived key length argument - // */ - // abstract string getDerivedKeyLength(Location location); - // override predicate properties(string key, string value, Location location) { - // super.properties(key, value, location) - // or - // ( - // // [KNOWN_OR_UNKNOWN] - // key = "N" and - // if exists(this.get_N(location)) - // then value = this.get_N(location) - // else ( - // value instanceof UnknownPropertyValue and location instanceof UnknownLocation - // ) - // ) - // or - // ( - // // [KNOWN_OR_UNKNOWN] - // key = "r" and - // if exists(this.get_r(location)) - // then value = this.get_r(location) - // else ( - // value instanceof UnknownPropertyValue and location instanceof UnknownLocation - // ) - // ) - // or - // ( - // // [KNOWN_OR_UNKNOWN] - // key = "p" and - // if exists(this.get_p(location)) - // then value = this.get_p(location) - // else ( - // value instanceof UnknownPropertyValue and location instanceof UnknownLocation - // ) - // ) - // or - // ( - // // [KNOWN_OR_UNKNOWN] - // key = "KeyLength" and - // if exists(this.getDerivedKeyLength(location)) - // then value = this.getDerivedKeyLength(location) - // else ( - // value instanceof UnknownPropertyValue and location instanceof UnknownLocation - // ) - // ) - // } - // } - /* - * TODO: - * - * Rule: No newtype representing a type of algorithm should be modelled with multiple interfaces - * - * Example 1: HKDF and PKCS12KDF are both key derivation algorithms. - * However, PKCS12KDF also has a property: the iteration count. - * - * If we have HKDF and PKCS12KDF under TKeyDerivationType, - * someone modelling a library might try to make a generic identification of both of those algorithms. - * - * They will therefore not use the specialized type for PKCS12KDF, - * meaning "from PKCS12KDF algo select algo" will have no results. - * - * Example 2: Each type below represents a common family of elliptic curves, with a shared interface, i.e., - * predicates for library modellers to implement as well as the properties and edges reported. + /** + * scrypt key derivation function */ + class ScryptAlgorithmNode extends KeyDerivationAlgorithmNode { + ScryptAlgorithmInstance scryptInstance; - newtype TCipherOperationSubtype = - TEncryptionMode() or - TDecryptionMode() or - TWrapMode() or - TUnwrapMode() or - TSignatureMode() or - TUnknownCipherOperationMode() - - abstract class CipherOperationSubtype extends TCipherOperationSubtype { - abstract string toString(); - } - - class EncryptionSubtype extends CipherOperationSubtype, TEncryptionMode { - override string toString() { result = "Encrypt" } - } + ScryptAlgorithmNode() { scryptInstance = instance.asAlg() } - class DecryptionSubtype extends CipherOperationSubtype, TDecryptionMode { - override string toString() { result = "Decrypt" } - } + /** + * Gets the iteration count (`N`) argument + */ + GenericSourceNode get_N() { none() } // TODO - class WrapSubtype extends CipherOperationSubtype, TWrapMode { - override string toString() { result = "Wrap" } - } + /** + * Gets the block size (`r`) argument + */ + GenericSourceNode get_r() { none() } // TODO - class UnwrapSubtype extends CipherOperationSubtype, TUnwrapMode { - override string toString() { result = "Unwrap" } + /** + * Gets the parallelization factor (`p`) argument + */ + GenericSourceNode get_p() { none() } // TODO } - class SignatureSubtype extends CipherOperationSubtype, TSignatureMode { - override string toString() { result = "Sign" } - } + /** + * A type defining the subtype type of a key operation. + */ + newtype TKeyOperationSubtype = + TEncryptMode() or + TDecryptMode() or + TWrapMode() or + TUnwrapMode() or + TSignMode() or + TVerifyMode() or + TUnknownKeyOperationMode() - class UnknownCipherOperationSubtype extends CipherOperationSubtype, TUnknownCipherOperationMode { - override string toString() { result = "Unknown" } + /** + * A class defining the subtype of a key operation. + */ + class KeyOperationSubtype extends TKeyOperationSubtype { + string toString() { + result = "Encrypt" and this = TEncryptMode() + or + result = "Decrypt" and this = TDecryptMode() + or + result = "Wrap" and this = TWrapMode() + or + result = "Unwrap" and this = TUnwrapMode() + or + result = "Sign" and this = TSignMode() + or + result = "Verify" and this = TVerifyMode() + or + result = "Unknown" and this = TUnknownKeyOperationMode() + } } /** - * An encryption operation that processes plaintext to generate a ciphertext. - * This operation takes an input message (plaintext) of arbitrary content and length - * and produces a ciphertext as the output using a specified encryption algorithm (with a mode and padding). + * A key-based cryptographic transformation that operates on data using either a symmetric or asymmetric cryptographic key. + * + * This operation class covers operations based on symmetric ciphers or broader asymmetric algorithms, including: + * + * - **Encryption / Decryption**: + * Symmetric (e.g., AES-GCM) or asymmetric (e.g., RSA-OAEP, ECIES) encryption of plaintext to ciphertext or vice-versa. + * + * - **Key Wrapping / Unwrapping**: + * Encapsulation of symmetric keys using algorithms such as Kyber, AES-KW, RSA-KEM, RSA-OAEP, etc. + * + * - **Signing / Verifying**: + * Digital signatures using private/public keypairs (e.g., Ed25519, RSA-PSS, ECDSA) + * + * Each sub-operation is represented by a `CipherOperationSubtype`, such as `Encrypt`, `Sign`, `Wrap`, etc. + * + * Note: This class does _not_ include symmetric message authentication operations (MACs) like HMAC or CMAC. + * These are handled separately in the `MacOperationNode` class. */ - final class CipherOperationNode extends OperationNode, TCipherOperation { - CipherOperationInstance instance; + class KeyOperationNode extends OperationNode, TKeyOperation { + KeyOperationInstance instance; + + KeyOperationNode() { this = TKeyOperation(instance) } - CipherOperationNode() { this = TCipherOperation(instance) } + final KeyOperationSubtype getKeyOperationSubtype() { + result = instance.getKeyOperationSubtype() + } override LocatableElement asElement() { result = instance } - override string getInternalType() { result = "CipherOperation" } + override string getInternalType() { result = "KeyOperation" } override predicate isCandidateAlgorithmNode(AlgorithmNode node) { - node instanceof CipherAlgorithmNode - } - - CipherOperationSubtype getCipherOperationSubtype() { - result = instance.getCipherOperationSubtype() + node instanceof KeyOperationAlgorithmNode } NonceArtifactNode getANonce() { result.asElement() = instance.getNonceConsumer().getConsumer() } @@ -1611,25 +1813,29 @@ module CryptographyBase Input> { result.asElement() = instance.getInputConsumer().getConsumer() } - CipherOutputNode getAnOutputArtifact() { result.asElement() = instance.getOutputArtifact() } + KeyOperationOutputNode getAnOutputArtifact() { + result.asElement() = instance.getOutputArtifactInstance() + } KeyArtifactNode getAKey() { result.asElement() = instance.getKeyConsumer().getConsumer() } override NodeBase getChild(string key) { result = super.getChild(key) or - // [KNOWN_OR_UNKNOWN] + // [KNOWN_OR_UNKNOWN] - but only if not sign/verify + not this instanceof SignatureOperationNode and key = "Nonce" and if exists(this.getANonce()) then result = this.getANonce() else result = this or // [KNOWN_OR_UNKNOWN] - key = "InputText" and + key = "Input" and if exists(this.getAnInputArtifact()) then result = this.getAnInputArtifact() else result = this or - // [KNOWN_OR_UNKNOWN] - key = "OutputText" and + // [KNOWN_OR_UNKNOWN] - but only if not verify + not this.getKeyOperationSubtype() instanceof TVerifyMode and + key = "Output" and if exists(this.getAnOutputArtifact()) then result = this.getAnOutputArtifact() else result = this @@ -1638,33 +1844,47 @@ module CryptographyBase Input> { key = "Key" and if exists(this.getAKey()) then result = this.getAKey() else result = this } + } - override predicate properties(string key, string value, Location location) { - super.properties(key, value, location) + class CipherOperationNode extends KeyOperationNode { + string nodeName; + + CipherOperationNode() { + this.getKeyOperationSubtype() = TEncryptMode() and nodeName = "EncryptOperation" or - // [ALWAYS_KNOWN] - Unknown is handled in getCipherOperationMode() - key = "Operation" and - value = this.getCipherOperationSubtype().toString() and - location = this.getLocation() + this.getKeyOperationSubtype() = TDecryptMode() and nodeName = "DecryptOperation" } + + override string getInternalType() { result = nodeName } + } + + class KeyEncapsulationOperationNode extends KeyOperationNode { + string nodeName; + + KeyEncapsulationOperationNode() { + this.getKeyOperationSubtype() = TWrapMode() and nodeName = "WrapOperation" + or + this.getKeyOperationSubtype() = TUnwrapMode() and nodeName = "UnwrapOperation" + } + + override string getInternalType() { result = nodeName } + } + + class SignatureOperationNode extends KeyOperationNode { + string nodeName; + + SignatureOperationNode() { + this.getKeyOperationSubtype() = TSignMode() and nodeName = "SignOperation" + or + this.getKeyOperationSubtype() = TVerifyMode() and nodeName = "VerifyOperation" + } + + override string getInternalType() { result = nodeName } } /** * Block cipher modes of operation algorithms */ - newtype TBlockCipherModeOperationType = - ECB() or // Not secure, widely used - CBC() or // Vulnerable to padding oracle attacks - CFB() or - GCM() or // Widely used AEAD mode (TLS 1.3, SSH, IPsec) - CTR() or // Fast stream-like encryption (SSH, disk encryption) - XTS() or // Standard for full-disk encryption (BitLocker, LUKS, FileVault) - CCM() or // Used in lightweight cryptography (IoT, WPA2) - SIV() or // Misuse-resistant encryption, used in secure storage - OCB() or // Efficient AEAD mode - OFB() or - OtherMode() - class ModeOfOperationAlgorithmNode extends AlgorithmNode, TModeOfOperationAlgorithm { ModeOfOperationAlgorithmInstance instance; @@ -1683,29 +1903,29 @@ module CryptographyBase Input> { * * If a type cannot be determined, the result is `OtherMode`. */ - TBlockCipherModeOperationType getModeType() { result = instance.getModeType() } + TBlockCipherModeOfOperationType getModeType() { result = instance.getModeType() } bindingset[type] - final private predicate modeToNameMapping(TBlockCipherModeOperationType type, string name) { - type instanceof ECB and name = "ECB" + final private predicate modeToNameMapping(TBlockCipherModeOfOperationType type, string name) { + type = ECB() and name = "ECB" or - type instanceof CBC and name = "CBC" + type = CBC() and name = "CBC" or - type instanceof GCM and name = "GCM" + type = GCM() and name = "GCM" or - type instanceof CTR and name = "CTR" + type = CTR() and name = "CTR" or - type instanceof XTS and name = "XTS" + type = XTS() and name = "XTS" or - type instanceof CCM and name = "CCM" + type = CCM() and name = "CCM" or - type instanceof SIV and name = "SIV" + type = SIV() and name = "SIV" or - type instanceof OCB and name = "OCB" + type = OCB() and name = "OCB" or - type instanceof CFB and name = "CFB" + type = CFB() and name = "CFB" or - type instanceof OFB and name = "OFB" + type = OFB() and name = "OFB" } override string getAlgorithmName() { this.modeToNameMapping(this.getModeType(), result) } @@ -1733,17 +1953,17 @@ module CryptographyBase Input> { bindingset[type] final private predicate paddingToNameMapping(TPaddingType type, string name) { - type instanceof PKCS1_v1_5 and name = "PKCS1_v1_5" + type = ANSI_X9_23() and name = "ANSI_X9_23" or - type instanceof PSS and name = "PSS" + type = NoPadding() and name = "NoPadding" or - type instanceof PKCS7 and name = "PKCS7" + type = OAEP() and name = "OAEP" or - type instanceof ANSI_X9_23 and name = "ANSI_X9_23" + type = PKCS1_v1_5() and name = "PKCS1_v1_5" or - type instanceof NoPadding and name = "NoPadding" + type = PKCS7() and name = "PKCS7" or - type instanceof OAEP and name = "OAEP" + type = PSS() and name = "PSS" } override string getAlgorithmName() { this.paddingToNameMapping(this.getPaddingType(), result) } @@ -1781,81 +2001,36 @@ module CryptographyBase Input> { } } - /** - * A helper type for distinguishing between block and stream ciphers. - */ - newtype TCipherStructureType = - Block() or - Stream() or - Asymmetric() or - UnknownCipherStructureType() - - private string getCipherStructureTypeString(TCipherStructureType type) { - type instanceof Block and result = "Block" - or - type instanceof Stream and result = "Stream" - or - type instanceof Asymmetric and result = "Asymmetric" - or - type instanceof UnknownCipherStructureType and result instanceof UnknownPropertyValue - } + class KeyOperationAlgorithmNode extends AlgorithmNode, TKeyOperationAlgorithm { + KeyOperationAlgorithmInstanceOrValueConsumer instance; - /** - * Symmetric algorithms - */ - newtype TCipherType = - AES() or - ARIA() or - BLOWFISH() or - CAMELLIA() or - CAST5() or - CHACHA20() or - DES() or - DESX() or - GOST() or - IDEA() or - KUZNYECHIK() or - MAGMA() or - TripleDES() or - DoubleDES() or - RC2() or - RC4() or - RC5() or - RSA() or - SEED() or - SM4() or - OtherCipherType() - - final class CipherAlgorithmNode extends AlgorithmNode, TCipherAlgorithm { - CipherAlgorithmInstanceOrValueConsumer instance; - - CipherAlgorithmNode() { this = TCipherAlgorithm(instance) } + KeyOperationAlgorithmNode() { this = TKeyOperationAlgorithm(instance) } override LocatableElement asElement() { result = instance } - override string getInternalType() { result = "CipherAlgorithm" } + override string getInternalType() { result = "KeyOperationAlgorithm" } - final TCipherStructureType getCipherStructure() { - this.cipherFamilyToNameAndStructure(this.getCipherFamily(), _, result) + final KeyOpAlg::CipherStructureType getSymmetricCipherStructure() { + KeyOpAlg::symmetric_cipher_to_name_and_structure(this.getAlgorithmType() + .(KeyOpAlg::SymmetricCipherAlgorithm) + .getType(), _, result) } final override string getAlgorithmName() { - this.cipherFamilyToNameAndStructure(this.getCipherFamily(), result, _) + KeyOpAlg::type_to_name(this.getAlgorithmType(), result) } - final override string getRawAlgorithmName() { - result = instance.asAlg().getRawCipherAlgorithmName() - } + final override string getRawAlgorithmName() { result = instance.asAlg().getRawAlgorithmName() } /** - * Gets the key size of this cipher, e.g., "128" or "256". + * Gets the key size variant of this algorithm in bits, e.g., 128 for "AES-128". */ - string getKeySize(Location location) { none() } // TODO + string getKeySize() { result = instance.asAlg().getKeySize() } // TODO: key sizes for known algorithms /** - * Gets the type of this cipher, e.g., "AES" or "ChaCha20". + * Gets the type of this key operation algorithm, e.g., "SymmetricEncryption(_)" or "" */ - TCipherType getCipherFamily() { result = instance.asAlg().getCipherFamily() } + KeyOpAlg::Algorithm getAlgorithmType() { result = instance.asAlg().getAlgorithmType() } /** * Gets the mode of operation of this cipher, e.g., "GCM" or "CBC". @@ -1871,55 +2046,6 @@ module CryptographyBase Input> { result.asElement() = instance.asAlg().getPaddingAlgorithm() } - bindingset[type] - final private predicate cipherFamilyToNameAndStructure( - TCipherType type, string name, TCipherStructureType s - ) { - type instanceof AES and name = "AES" and s = Block() - or - type instanceof ARIA and name = "ARIA" and s = Block() - or - type instanceof BLOWFISH and name = "Blowfish" and s = Block() - or - type instanceof CAMELLIA and name = "Camellia" and s = Block() - or - type instanceof CAST5 and name = "CAST5" and s = Block() - or - type instanceof CHACHA20 and name = "ChaCha20" and s = Stream() - or - type instanceof DES and name = "DES" and s = Block() - or - type instanceof DESX and name = "DESX" and s = Block() - or - type instanceof GOST and name = "GOST" and s = Block() - or - type instanceof IDEA and name = "IDEA" and s = Block() - or - type instanceof KUZNYECHIK and name = "Kuznyechik" and s = Block() - or - type instanceof MAGMA and name = "Magma" and s = Block() - or - type instanceof TripleDES and name = "TripleDES" and s = Block() - or - type instanceof DoubleDES and name = "DoubleDES" and s = Block() - or - type instanceof RC2 and name = "RC2" and s = Block() - or - type instanceof RC4 and name = "RC4" and s = Stream() - or - type instanceof RC5 and name = "RC5" and s = Block() - or - type instanceof RSA and name = "RSA" and s = Asymmetric() - or - type instanceof SEED and name = "SEED" and s = Block() - or - type instanceof SM4 and name = "SM4" and s = Block() - or - type instanceof OtherCipherType and - name instanceof UnknownPropertyValue and // TODO: get rid of this hack to bind structure and type - s = UnknownCipherStructureType() - } - override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) or @@ -1939,16 +2065,16 @@ module CryptographyBase Input> { override predicate properties(string key, string value, Location location) { super.properties(key, value, location) or - // [ALWAYS_KNOWN] - unknown case is handled in `getCipherStructureTypeString` + // [ONLY_KNOWN] - only if symmetric, unknown case is handled in `toString` key = "Structure" and - getCipherStructureTypeString(this.getCipherStructure()) = value and - location instanceof UnknownLocation + this.getSymmetricCipherStructure().toString() = value and + location = this.getLocation() or ( // [KNOWN_OR_UNKNOWN] key = "KeySize" and - if exists(this.getKeySize(location)) - then value = this.getKeySize(location) + if exists(this.getKeySize()) + then value = this.getKeySize() else ( value instanceof UnknownPropertyValue and location instanceof UnknownLocation ) @@ -2021,32 +2147,32 @@ module CryptographyBase Input> { override string getRawAlgorithmName() { result = instance.asAlg().getRawHashAlgorithmName() } - final predicate hashTypeToNameMapping(THashType type, string name) { - type instanceof BLAKE2B and name = "BLAKE2B" + final private predicate hashTypeToNameMapping(THashType type, string name) { + type = BLAKE2B() and name = "BLAKE2B" or - type instanceof BLAKE2S and name = "BLAKE2S" + type = BLAKE2S() and name = "BLAKE2S" or - type instanceof RIPEMD160 and name = "RIPEMD160" + type = RIPEMD160() and name = "RIPEMD160" or - type instanceof MD2 and name = "MD2" + type = MD2() and name = "MD2" or - type instanceof MD4 and name = "MD4" + type = MD4() and name = "MD4" or - type instanceof MD5 and name = "MD5" + type = MD5() and name = "MD5" or - type instanceof POLY1305 and name = "POLY1305" + type = POLY1305() and name = "POLY1305" or - type instanceof SHA1 and name = "SHA1" + type = SHA1() and name = "SHA1" or - type instanceof SHA2 and name = "SHA2" + type = SHA2() and name = "SHA2" or - type instanceof SHA3 and name = "SHA3" + type = SHA3() and name = "SHA3" or - type instanceof SHAKE and name = "SHAKE" + type = SHAKE() and name = "SHAKE" or - type instanceof SM3 and name = "SM3" + type = SM3() and name = "SM3" or - type instanceof WHIRLPOOL and name = "WHIRLPOOL" + type = WHIRLPOOL() and name = "WHIRLPOOL" } /** @@ -2129,19 +2255,32 @@ module CryptographyBase Input> { private predicate isNumsCurve(string curveName, int keySize) { // ALL NUMS CURVES keySize in [256, 384, 512] and - exists(string suff | suff in ["T1"] | curveName = "NUMSP" + keySize.toString() + suff) + exists(string suff | suff = "T1" | curveName = "NUMSP" + keySize.toString() + suff) } + /** + * Holds if `name` corresponds to a known elliptic curve. + * + * Note: As an exception, this predicate may be used for library modelling, as curve names are largely standardized. + * + * When modelling, verify that this predicate offers sufficient coverage for the library and handle edge-cases. + */ bindingset[curveName] predicate isEllipticCurveAlgorithmName(string curveName) { - isEllipticCurveAlgorithm(curveName, _, _) + ellipticCurveNameToKeySizeAndFamilyMapping(curveName, _, _) } /** - * Holds if `name` corresponds to a known elliptic curve. + * Relates elliptic curve names to their key size and family. + * + * Note: As an exception, this predicate may be used for library modelling, as curve names are largely standardized. + * + * When modelling, verify that this predicate offers sufficient coverage for the library and handle edge-cases. */ bindingset[rawName] - predicate isEllipticCurveAlgorithm(string rawName, int keySize, TEllipticCurveType curveFamily) { + predicate ellipticCurveNameToKeySizeAndFamilyMapping( + string rawName, int keySize, TEllipticCurveType curveFamily + ) { exists(string curveName | curveName = rawName.toUpperCase() | isSecCurve(curveName, keySize) and curveFamily = SEC() or @@ -2171,19 +2310,30 @@ module CryptographyBase Input> { ) } - final class EllipticCurveNode extends AlgorithmNode, TEllipticCurveAlgorithm { - EllipticCurveAlgorithmInstanceOrValueConsumer instance; + final class EllipticCurveNode extends AlgorithmNode, TEllipticCurve { + EllipticCurveInstanceOrValueConsumer instance; - EllipticCurveNode() { this = TEllipticCurveAlgorithm(instance) } + EllipticCurveNode() { this = TEllipticCurve(instance) } - override string getInternalType() { result = "EllipticCurveAlgorithm" } + override string getInternalType() { result = "EllipticCurve" } + + override LocatableElement asElement() { result = instance } final override string getRawAlgorithmName() { - result = instance.asAlg().getRawEllipticCurveAlgorithmName() + result = instance.asAlg().getRawEllipticCurveName() } - // NICK QUESTION: do I repeat the key size and curve family predicates here as wrappers of the instance? - override LocatableElement asElement() { result = instance } + /* + * Mandating that for Elliptic Curves specifically, users are *only* responsible + * for providing as the 'raw' name within source code. + * + * Rationale: elliptic curve names can have a lot of variation in their components + * (e.g., "secp256r1" vs "P-256"), trying to produce generalized set of properties + * is possible to capture all cases, but such modeling is likely not necessary. + * if all properties need to be captured, we can reassess how names are generated. + */ + + override string getAlgorithmName() { result = this.getRawAlgorithmName() } TEllipticCurveType getEllipticCurveFamily() { result = instance.asAlg().getEllipticCurveFamily() @@ -2197,80 +2347,10 @@ module CryptographyBase Input> { value = instance.asAlg().getKeySize() and location = this.getLocation() or - key = "StdCurveName" and - value = instance.asAlg().getStandardCurveName().toUpperCase() and + // [ONLY_KNOWN] + key = "ParsedName" and + value = instance.asAlg().getParsedEllipticCurveName() and location = this.getLocation() } - - override string getAlgorithmName() { result = this.getRawAlgorithmName().toUpperCase() } - // /** - // * Mandating that for Elliptic Curves specifically, users are responsible - // * for providing as the 'raw' name, the official name of the algorithm. - // * - // * Casing doesn't matter, we will enforce further naming restrictions on - // * `getAlgorithmName` by default. - // * - // * Rationale: elliptic curve names can have a lot of variation in their components - // * (e.g., "secp256r1" vs "P-256"), trying to produce generalized set of properties - // * is possible to capture all cases, but such modeling is likely not necessary. - // * if all properties need to be captured, we can reassess how names are generated. - // */ - // abstract override string getRawAlgorithmName(); - } - - abstract class KEMAlgorithm extends TKeyEncapsulationAlgorithm, AlgorithmNode { - final override string getInternalType() { result = "KeyEncapsulationAlgorithm" } - } - - /** - * Key agreement algorithms - */ - newtype TKeyAgreementType = - DH() or // Diffie-Hellman - EDH() or // Ephemeral Diffie-Hellman - ECDH() or // Elliptic Curve Diffie-Hellman - // Note: x25519 and x448 are applications of ECDH - OtherKeyAgreementType() - - bindingset[name] - predicate isKeyAgreementAlgorithmName(string name) { isKeyAgreementAlgorithm(name, _) } - - bindingset[name] - predicate isKeyAgreementAlgorithm(string name, TKeyAgreementType type) { - exists(string name2 | name2 = name.toUpperCase() | - name2 = "DH" and type = DH() - or - name2 = "EDH" and type = EDH() - or - name2 = "ECDH" and type = ECDH() - or - name2 = "X25519" and type = ECDH() - or - name2 = "X448" and type = ECDH() - ) - } - - abstract class KeyAgreementAlgorithmInstance extends AlgorithmInstance { - // /** - // * If the key agreement uses a curve, (e.g., ECDH) point to the curve instance. - // * none() if the agreement is not curve based (e.g., plain DH). - // * Note that if the curve is inherent to the algorithm (e.g., x25519), this will be - // * the key agreement algorithm instance itself (this). - // */ - // abstract EllipticCurveAlgorithmInstance getEllipticCurveAlgorithm(); - } - - abstract class KeyAgreementSecretGenerationOperationInstance extends OperationInstance { - /** - * The private key used in the key agreement operation. - * This key represents the local party in the key agreement. - */ - abstract ConsumerInputDataFlowNode getServerKeyConsumer(); - - /** - * The public key used in the key agreement operation, coming - * from the peer (the other party in the key agreement). - */ - abstract ConsumerInputDataFlowNode getPeerKeyConsumer(); } } From f1a3293f4c81bb870add0eb4ea083dc34f6e2aa6 Mon Sep 17 00:00:00 2001 From: Napalys Date: Mon, 14 Apr 2025 11:04:56 +0200 Subject: [PATCH 081/336] Added change note --- javascript/ql/lib/change-notes/2025-04-14-fastify-addhook.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 javascript/ql/lib/change-notes/2025-04-14-fastify-addhook.md diff --git a/javascript/ql/lib/change-notes/2025-04-14-fastify-addhook.md b/javascript/ql/lib/change-notes/2025-04-14-fastify-addhook.md new file mode 100644 index 000000000000..a9e754bd56ea --- /dev/null +++ b/javascript/ql/lib/change-notes/2025-04-14-fastify-addhook.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added support for the `fastify` `addHook` method. From c1750816982a41ed13caf1e65ecc7912198220b5 Mon Sep 17 00:00:00 2001 From: Napalys Date: Tue, 15 Apr 2025 09:33:41 +0200 Subject: [PATCH 082/336] Added test cases for `fastify.addHook` --- .../CodeInjection/CodeInjection.expected | 13 +++ .../HeuristicSourceCodeInjection.expected | 9 ++ .../Security/CWE-094/CodeInjection/fastify.js | 103 ++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected index a81b9dbcce0f..5fc5856814c7 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected @@ -27,6 +27,10 @@ | express.js:20:34:20:38 | taint | express.js:19:17:19:35 | req.param("wobble") | express.js:20:34:20:38 | taint | This code execution depends on a $@. | express.js:19:17:19:35 | req.param("wobble") | user-provided value | | express.js:36:15:36:19 | taint | express.js:27:17:27:35 | req.param("wobble") | express.js:36:15:36:19 | taint | This code execution depends on a $@. | express.js:27:17:27:35 | req.param("wobble") | user-provided value | | express.js:43:10:43:12 | msg | express.js:42:30:42:32 | msg | express.js:43:10:43:12 | msg | This code execution depends on a $@. | express.js:42:30:42:32 | msg | user-provided value | +| fastify.js:58:44:58:52 | userInput | fastify.js:57:21:57:33 | request.query | fastify.js:58:44:58:52 | userInput | This code execution depends on a $@. | fastify.js:57:21:57:33 | request.query | user-provided value | +| fastify.js:58:44:58:52 | userInput | fastify.js:57:21:57:39 | request.query.input | fastify.js:58:44:58:52 | userInput | This code execution depends on a $@. | fastify.js:57:21:57:39 | request.query.input | user-provided value | +| fastify.js:59:23:59:31 | userInput | fastify.js:57:21:57:33 | request.query | fastify.js:59:23:59:31 | userInput | This code execution depends on a $@. | fastify.js:57:21:57:33 | request.query | user-provided value | +| fastify.js:59:23:59:31 | userInput | fastify.js:57:21:57:39 | request.query.input | fastify.js:59:23:59:31 | userInput | This code execution depends on a $@. | fastify.js:57:21:57:39 | request.query.input | user-provided value | | module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code | This code execution depends on a $@. | module.js:9:16:9:29 | req.query.code | user-provided value | | module.js:11:17:11:30 | req.query.code | module.js:11:17:11:30 | req.query.code | module.js:11:17:11:30 | req.query.code | This code execution depends on a $@. | module.js:11:17:11:30 | req.query.code | user-provided value | | react-native.js:8:32:8:38 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:8:32:8:38 | tainted | This code execution depends on a $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value | @@ -75,6 +79,10 @@ edges | express.js:27:9:27:35 | taint | express.js:36:15:36:19 | taint | provenance | | | express.js:27:17:27:35 | req.param("wobble") | express.js:27:9:27:35 | taint | provenance | | | express.js:42:30:42:32 | msg | express.js:43:10:43:12 | msg | provenance | | +| fastify.js:57:9:57:39 | userInput | fastify.js:58:44:58:52 | userInput | provenance | | +| fastify.js:57:9:57:39 | userInput | fastify.js:59:23:59:31 | userInput | provenance | | +| fastify.js:57:21:57:33 | request.query | fastify.js:57:9:57:39 | userInput | provenance | | +| fastify.js:57:21:57:39 | request.query.input | fastify.js:57:9:57:39 | userInput | provenance | | | react-native.js:7:7:7:33 | tainted | react-native.js:8:32:8:38 | tainted | provenance | | | react-native.js:7:7:7:33 | tainted | react-native.js:10:23:10:29 | tainted | provenance | | | react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted | provenance | | @@ -144,6 +152,11 @@ nodes | express.js:36:15:36:19 | taint | semmle.label | taint | | express.js:42:30:42:32 | msg | semmle.label | msg | | express.js:43:10:43:12 | msg | semmle.label | msg | +| fastify.js:57:9:57:39 | userInput | semmle.label | userInput | +| fastify.js:57:21:57:33 | request.query | semmle.label | request.query | +| fastify.js:57:21:57:39 | request.query.input | semmle.label | request.query.input | +| fastify.js:58:44:58:52 | userInput | semmle.label | userInput | +| fastify.js:59:23:59:31 | userInput | semmle.label | userInput | | module.js:9:16:9:29 | req.query.code | semmle.label | req.query.code | | module.js:11:17:11:30 | req.query.code | semmle.label | req.query.code | | react-native.js:7:7:7:33 | tainted | semmle.label | tainted | diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected index ba973943e124..b56f28a79171 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected @@ -11,6 +11,10 @@ edges | express.js:27:9:27:35 | taint | express.js:36:15:36:19 | taint | provenance | | | express.js:27:17:27:35 | req.param("wobble") | express.js:27:9:27:35 | taint | provenance | | | express.js:42:30:42:32 | msg | express.js:43:10:43:12 | msg | provenance | | +| fastify.js:57:9:57:39 | userInput | fastify.js:58:44:58:52 | userInput | provenance | | +| fastify.js:57:9:57:39 | userInput | fastify.js:59:23:59:31 | userInput | provenance | | +| fastify.js:57:21:57:33 | request.query | fastify.js:57:9:57:39 | userInput | provenance | | +| fastify.js:57:21:57:39 | request.query.input | fastify.js:57:9:57:39 | userInput | provenance | | | react-native.js:7:7:7:33 | tainted | react-native.js:8:32:8:38 | tainted | provenance | | | react-native.js:7:7:7:33 | tainted | react-native.js:10:23:10:29 | tainted | provenance | | | react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted | provenance | | @@ -82,6 +86,11 @@ nodes | express.js:36:15:36:19 | taint | semmle.label | taint | | express.js:42:30:42:32 | msg | semmle.label | msg | | express.js:43:10:43:12 | msg | semmle.label | msg | +| fastify.js:57:9:57:39 | userInput | semmle.label | userInput | +| fastify.js:57:21:57:33 | request.query | semmle.label | request.query | +| fastify.js:57:21:57:39 | request.query.input | semmle.label | request.query.input | +| fastify.js:58:44:58:52 | userInput | semmle.label | userInput | +| fastify.js:59:23:59:31 | userInput | semmle.label | userInput | | module.js:9:16:9:29 | req.query.code | semmle.label | req.query.code | | module.js:11:17:11:30 | req.query.code | semmle.label | req.query.code | | react-native.js:7:7:7:33 | tainted | semmle.label | tainted | diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js new file mode 100644 index 000000000000..b8878cdab41c --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js @@ -0,0 +1,103 @@ +const fastify = require('fastify')({ logger: true }); + +fastify.addHook('onRequest', async (request, reply) => { + const userInput = request.query.onRequest; // $ MISSING: Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] +}); + +fastify.addHook('onSend', async (request, reply, payload) => { + const userInput = request.query.onSend; // $ MISSING: Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] + return JSON.stringify({ ...JSON.parse(payload), onSend: request.evalResult }); +}); + +fastify.addHook('preParsing', async (request, reply, payload) => { + const userInput = request.query.preParsing; // $ MISSING: Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] + return payload; +}); + +fastify.addHook('preValidation', async (request, reply) => { + const userInput = request.query.preValidation; // $ MISSING: Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] +}); + +fastify.addHook('preHandler', async (request, reply) => { + const userInput = request.query.preHandler; // $ MISSING: Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] +}); + +fastify.addHook('preSerialization', async (request, reply, payload) => { + const userInput = request.query.preSerialization; // $ MISSING: Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] + return payload; +}); + +fastify.addHook('onResponse', async (request, reply) => { + const userInput = request.query.onResponse; // $ MISSING: Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] +}); + +fastify.addHook('onError', async (request, reply, error) => { + const userInput = request.query.onError; // $ MISSING: Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] +}); + +fastify.addHook('onTimeout', async (request, reply) => { + const userInput = request.query.onTimeout; // $ MISSING: Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] +}); + +fastify.addHook('onRequestAbort', (request, done) => { + const userInput = request.query.onRequestAbort; // $ MISSING: Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] +}); + +fastify.get('/dangerous', async (request, reply) => { + const userInput = request.query.input; // $ Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ Alert[js/code-injection] + const result = eval(userInput); // $ Alert[js/code-injection] + return { result }; +}); + + +// Store user input in request object +fastify.addHook('preHandler', async (request, reply) => { + request.storedCode = request.query.storedCode; +}); +fastify.get('/flow-through-request', async (request, reply) => { + // Use the stored code from previous hook + if (request.storedCode) { + const evaluatedResult = eval(request.storedCode); // $ MISSING: Alert[js/code-injection] + return { result: evaluatedResult }; + } + return { result: null }; +}); + +// Store user input in reply object +fastify.addHook('onRequest', async (request, reply) => { + reply.userCode = request.query.replyCode; +}); +fastify.get('/flow-through-reply', async (request, reply) => { + // Use the code stored in reply object + if (reply.userCode) { + const replyResult = eval(reply.userCode); // $ MISSING: Alert[js/code-injection] + return { result: replyResult }; + } + return { result: null }; +}); + + +// Store user input in reply object +fastify.addHook('onRequest', async (request, reply) => { + reply.locals = reply.locals || {}; + reply.locals.nestedCode = request.query.replyCode; +}); +fastify.get('/flow-through-reply', async (request, reply) => { + // Use the code stored in reply object + if (reply.locals && reply.locals.nestedCode) { + const replyResult = eval(reply.locals.nestedCode); // $ MISSING: Alert[js/code-injection] + return { result: replyResult }; + } + return { result: null }; +}); From 9b194ea613c653a7bf6e16ca4633827b8e8d2a41 Mon Sep 17 00:00:00 2001 From: Napalys Date: Tue, 15 Apr 2025 09:37:13 +0200 Subject: [PATCH 083/336] Added `addHook` to `RouteSetup` thus now it is recognized now as rouute handler --- .../semmle/javascript/frameworks/Fastify.qll | 2 +- .../CodeInjection/CodeInjection.expected | 90 +++++++++++++++++++ .../HeuristicSourceCodeInjection.expected | 70 +++++++++++++++ .../Security/CWE-094/CodeInjection/fastify.js | 40 ++++----- 4 files changed, 181 insertions(+), 21 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll index 2b8d6287d78d..5b2485c76794 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll @@ -138,7 +138,7 @@ module Fastify { RouteSetup() { this = server(server).getAMethodCall(methodName) and - methodName = ["route", "get", "head", "post", "put", "delete", "options", "patch"] + methodName = ["route", "get", "head", "post", "put", "delete", "options", "patch", "addHook"] } override DataFlow::SourceNode getARouteHandler() { diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected index 5fc5856814c7..34487a43e630 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected @@ -27,6 +27,26 @@ | express.js:20:34:20:38 | taint | express.js:19:17:19:35 | req.param("wobble") | express.js:20:34:20:38 | taint | This code execution depends on a $@. | express.js:19:17:19:35 | req.param("wobble") | user-provided value | | express.js:36:15:36:19 | taint | express.js:27:17:27:35 | req.param("wobble") | express.js:36:15:36:19 | taint | This code execution depends on a $@. | express.js:27:17:27:35 | req.param("wobble") | user-provided value | | express.js:43:10:43:12 | msg | express.js:42:30:42:32 | msg | express.js:43:10:43:12 | msg | This code execution depends on a $@. | express.js:42:30:42:32 | msg | user-provided value | +| fastify.js:5:44:5:52 | userInput | fastify.js:4:21:4:33 | request.query | fastify.js:5:44:5:52 | userInput | This code execution depends on a $@. | fastify.js:4:21:4:33 | request.query | user-provided value | +| fastify.js:5:44:5:52 | userInput | fastify.js:4:21:4:43 | request ... Request | fastify.js:5:44:5:52 | userInput | This code execution depends on a $@. | fastify.js:4:21:4:43 | request ... Request | user-provided value | +| fastify.js:10:44:10:52 | userInput | fastify.js:9:21:9:33 | request.query | fastify.js:10:44:10:52 | userInput | This code execution depends on a $@. | fastify.js:9:21:9:33 | request.query | user-provided value | +| fastify.js:10:44:10:52 | userInput | fastify.js:9:21:9:40 | request.query.onSend | fastify.js:10:44:10:52 | userInput | This code execution depends on a $@. | fastify.js:9:21:9:40 | request.query.onSend | user-provided value | +| fastify.js:16:44:16:52 | userInput | fastify.js:15:21:15:33 | request.query | fastify.js:16:44:16:52 | userInput | This code execution depends on a $@. | fastify.js:15:21:15:33 | request.query | user-provided value | +| fastify.js:16:44:16:52 | userInput | fastify.js:15:21:15:44 | request ... Parsing | fastify.js:16:44:16:52 | userInput | This code execution depends on a $@. | fastify.js:15:21:15:44 | request ... Parsing | user-provided value | +| fastify.js:22:44:22:52 | userInput | fastify.js:21:21:21:33 | request.query | fastify.js:22:44:22:52 | userInput | This code execution depends on a $@. | fastify.js:21:21:21:33 | request.query | user-provided value | +| fastify.js:22:44:22:52 | userInput | fastify.js:21:21:21:47 | request ... idation | fastify.js:22:44:22:52 | userInput | This code execution depends on a $@. | fastify.js:21:21:21:47 | request ... idation | user-provided value | +| fastify.js:27:44:27:52 | userInput | fastify.js:26:21:26:33 | request.query | fastify.js:27:44:27:52 | userInput | This code execution depends on a $@. | fastify.js:26:21:26:33 | request.query | user-provided value | +| fastify.js:27:44:27:52 | userInput | fastify.js:26:21:26:44 | request ... Handler | fastify.js:27:44:27:52 | userInput | This code execution depends on a $@. | fastify.js:26:21:26:44 | request ... Handler | user-provided value | +| fastify.js:32:44:32:52 | userInput | fastify.js:31:21:31:33 | request.query | fastify.js:32:44:32:52 | userInput | This code execution depends on a $@. | fastify.js:31:21:31:33 | request.query | user-provided value | +| fastify.js:32:44:32:52 | userInput | fastify.js:31:21:31:50 | request ... ization | fastify.js:32:44:32:52 | userInput | This code execution depends on a $@. | fastify.js:31:21:31:50 | request ... ization | user-provided value | +| fastify.js:38:44:38:52 | userInput | fastify.js:37:21:37:33 | request.query | fastify.js:38:44:38:52 | userInput | This code execution depends on a $@. | fastify.js:37:21:37:33 | request.query | user-provided value | +| fastify.js:38:44:38:52 | userInput | fastify.js:37:21:37:44 | request ... esponse | fastify.js:38:44:38:52 | userInput | This code execution depends on a $@. | fastify.js:37:21:37:44 | request ... esponse | user-provided value | +| fastify.js:43:44:43:52 | userInput | fastify.js:42:21:42:33 | request.query | fastify.js:43:44:43:52 | userInput | This code execution depends on a $@. | fastify.js:42:21:42:33 | request.query | user-provided value | +| fastify.js:43:44:43:52 | userInput | fastify.js:42:21:42:41 | request ... onError | fastify.js:43:44:43:52 | userInput | This code execution depends on a $@. | fastify.js:42:21:42:41 | request ... onError | user-provided value | +| fastify.js:48:44:48:52 | userInput | fastify.js:47:21:47:33 | request.query | fastify.js:48:44:48:52 | userInput | This code execution depends on a $@. | fastify.js:47:21:47:33 | request.query | user-provided value | +| fastify.js:48:44:48:52 | userInput | fastify.js:47:21:47:43 | request ... Timeout | fastify.js:48:44:48:52 | userInput | This code execution depends on a $@. | fastify.js:47:21:47:43 | request ... Timeout | user-provided value | +| fastify.js:53:46:53:54 | userInput | fastify.js:52:23:52:35 | request.query | fastify.js:53:46:53:54 | userInput | This code execution depends on a $@. | fastify.js:52:23:52:35 | request.query | user-provided value | +| fastify.js:53:46:53:54 | userInput | fastify.js:52:23:52:50 | request ... stAbort | fastify.js:53:46:53:54 | userInput | This code execution depends on a $@. | fastify.js:52:23:52:50 | request ... stAbort | user-provided value | | fastify.js:58:44:58:52 | userInput | fastify.js:57:21:57:33 | request.query | fastify.js:58:44:58:52 | userInput | This code execution depends on a $@. | fastify.js:57:21:57:33 | request.query | user-provided value | | fastify.js:58:44:58:52 | userInput | fastify.js:57:21:57:39 | request.query.input | fastify.js:58:44:58:52 | userInput | This code execution depends on a $@. | fastify.js:57:21:57:39 | request.query.input | user-provided value | | fastify.js:59:23:59:31 | userInput | fastify.js:57:21:57:33 | request.query | fastify.js:59:23:59:31 | userInput | This code execution depends on a $@. | fastify.js:57:21:57:33 | request.query | user-provided value | @@ -79,6 +99,36 @@ edges | express.js:27:9:27:35 | taint | express.js:36:15:36:19 | taint | provenance | | | express.js:27:17:27:35 | req.param("wobble") | express.js:27:9:27:35 | taint | provenance | | | express.js:42:30:42:32 | msg | express.js:43:10:43:12 | msg | provenance | | +| fastify.js:4:9:4:43 | userInput | fastify.js:5:44:5:52 | userInput | provenance | | +| fastify.js:4:21:4:33 | request.query | fastify.js:4:9:4:43 | userInput | provenance | | +| fastify.js:4:21:4:43 | request ... Request | fastify.js:4:9:4:43 | userInput | provenance | | +| fastify.js:9:9:9:40 | userInput | fastify.js:10:44:10:52 | userInput | provenance | | +| fastify.js:9:21:9:33 | request.query | fastify.js:9:9:9:40 | userInput | provenance | | +| fastify.js:9:21:9:40 | request.query.onSend | fastify.js:9:9:9:40 | userInput | provenance | | +| fastify.js:15:9:15:44 | userInput | fastify.js:16:44:16:52 | userInput | provenance | | +| fastify.js:15:21:15:33 | request.query | fastify.js:15:9:15:44 | userInput | provenance | | +| fastify.js:15:21:15:44 | request ... Parsing | fastify.js:15:9:15:44 | userInput | provenance | | +| fastify.js:21:9:21:47 | userInput | fastify.js:22:44:22:52 | userInput | provenance | | +| fastify.js:21:21:21:33 | request.query | fastify.js:21:9:21:47 | userInput | provenance | | +| fastify.js:21:21:21:47 | request ... idation | fastify.js:21:9:21:47 | userInput | provenance | | +| fastify.js:26:9:26:44 | userInput | fastify.js:27:44:27:52 | userInput | provenance | | +| fastify.js:26:21:26:33 | request.query | fastify.js:26:9:26:44 | userInput | provenance | | +| fastify.js:26:21:26:44 | request ... Handler | fastify.js:26:9:26:44 | userInput | provenance | | +| fastify.js:31:9:31:50 | userInput | fastify.js:32:44:32:52 | userInput | provenance | | +| fastify.js:31:21:31:33 | request.query | fastify.js:31:9:31:50 | userInput | provenance | | +| fastify.js:31:21:31:50 | request ... ization | fastify.js:31:9:31:50 | userInput | provenance | | +| fastify.js:37:9:37:44 | userInput | fastify.js:38:44:38:52 | userInput | provenance | | +| fastify.js:37:21:37:33 | request.query | fastify.js:37:9:37:44 | userInput | provenance | | +| fastify.js:37:21:37:44 | request ... esponse | fastify.js:37:9:37:44 | userInput | provenance | | +| fastify.js:42:9:42:41 | userInput | fastify.js:43:44:43:52 | userInput | provenance | | +| fastify.js:42:21:42:33 | request.query | fastify.js:42:9:42:41 | userInput | provenance | | +| fastify.js:42:21:42:41 | request ... onError | fastify.js:42:9:42:41 | userInput | provenance | | +| fastify.js:47:9:47:43 | userInput | fastify.js:48:44:48:52 | userInput | provenance | | +| fastify.js:47:21:47:33 | request.query | fastify.js:47:9:47:43 | userInput | provenance | | +| fastify.js:47:21:47:43 | request ... Timeout | fastify.js:47:9:47:43 | userInput | provenance | | +| fastify.js:52:11:52:50 | userInput | fastify.js:53:46:53:54 | userInput | provenance | | +| fastify.js:52:23:52:35 | request.query | fastify.js:52:11:52:50 | userInput | provenance | | +| fastify.js:52:23:52:50 | request ... stAbort | fastify.js:52:11:52:50 | userInput | provenance | | | fastify.js:57:9:57:39 | userInput | fastify.js:58:44:58:52 | userInput | provenance | | | fastify.js:57:9:57:39 | userInput | fastify.js:59:23:59:31 | userInput | provenance | | | fastify.js:57:21:57:33 | request.query | fastify.js:57:9:57:39 | userInput | provenance | | @@ -152,6 +202,46 @@ nodes | express.js:36:15:36:19 | taint | semmle.label | taint | | express.js:42:30:42:32 | msg | semmle.label | msg | | express.js:43:10:43:12 | msg | semmle.label | msg | +| fastify.js:4:9:4:43 | userInput | semmle.label | userInput | +| fastify.js:4:21:4:33 | request.query | semmle.label | request.query | +| fastify.js:4:21:4:43 | request ... Request | semmle.label | request ... Request | +| fastify.js:5:44:5:52 | userInput | semmle.label | userInput | +| fastify.js:9:9:9:40 | userInput | semmle.label | userInput | +| fastify.js:9:21:9:33 | request.query | semmle.label | request.query | +| fastify.js:9:21:9:40 | request.query.onSend | semmle.label | request.query.onSend | +| fastify.js:10:44:10:52 | userInput | semmle.label | userInput | +| fastify.js:15:9:15:44 | userInput | semmle.label | userInput | +| fastify.js:15:21:15:33 | request.query | semmle.label | request.query | +| fastify.js:15:21:15:44 | request ... Parsing | semmle.label | request ... Parsing | +| fastify.js:16:44:16:52 | userInput | semmle.label | userInput | +| fastify.js:21:9:21:47 | userInput | semmle.label | userInput | +| fastify.js:21:21:21:33 | request.query | semmle.label | request.query | +| fastify.js:21:21:21:47 | request ... idation | semmle.label | request ... idation | +| fastify.js:22:44:22:52 | userInput | semmle.label | userInput | +| fastify.js:26:9:26:44 | userInput | semmle.label | userInput | +| fastify.js:26:21:26:33 | request.query | semmle.label | request.query | +| fastify.js:26:21:26:44 | request ... Handler | semmle.label | request ... Handler | +| fastify.js:27:44:27:52 | userInput | semmle.label | userInput | +| fastify.js:31:9:31:50 | userInput | semmle.label | userInput | +| fastify.js:31:21:31:33 | request.query | semmle.label | request.query | +| fastify.js:31:21:31:50 | request ... ization | semmle.label | request ... ization | +| fastify.js:32:44:32:52 | userInput | semmle.label | userInput | +| fastify.js:37:9:37:44 | userInput | semmle.label | userInput | +| fastify.js:37:21:37:33 | request.query | semmle.label | request.query | +| fastify.js:37:21:37:44 | request ... esponse | semmle.label | request ... esponse | +| fastify.js:38:44:38:52 | userInput | semmle.label | userInput | +| fastify.js:42:9:42:41 | userInput | semmle.label | userInput | +| fastify.js:42:21:42:33 | request.query | semmle.label | request.query | +| fastify.js:42:21:42:41 | request ... onError | semmle.label | request ... onError | +| fastify.js:43:44:43:52 | userInput | semmle.label | userInput | +| fastify.js:47:9:47:43 | userInput | semmle.label | userInput | +| fastify.js:47:21:47:33 | request.query | semmle.label | request.query | +| fastify.js:47:21:47:43 | request ... Timeout | semmle.label | request ... Timeout | +| fastify.js:48:44:48:52 | userInput | semmle.label | userInput | +| fastify.js:52:11:52:50 | userInput | semmle.label | userInput | +| fastify.js:52:23:52:35 | request.query | semmle.label | request.query | +| fastify.js:52:23:52:50 | request ... stAbort | semmle.label | request ... stAbort | +| fastify.js:53:46:53:54 | userInput | semmle.label | userInput | | fastify.js:57:9:57:39 | userInput | semmle.label | userInput | | fastify.js:57:21:57:33 | request.query | semmle.label | request.query | | fastify.js:57:21:57:39 | request.query.input | semmle.label | request.query.input | diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected index b56f28a79171..41550a22c9f7 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected @@ -11,6 +11,36 @@ edges | express.js:27:9:27:35 | taint | express.js:36:15:36:19 | taint | provenance | | | express.js:27:17:27:35 | req.param("wobble") | express.js:27:9:27:35 | taint | provenance | | | express.js:42:30:42:32 | msg | express.js:43:10:43:12 | msg | provenance | | +| fastify.js:4:9:4:43 | userInput | fastify.js:5:44:5:52 | userInput | provenance | | +| fastify.js:4:21:4:33 | request.query | fastify.js:4:9:4:43 | userInput | provenance | | +| fastify.js:4:21:4:43 | request ... Request | fastify.js:4:9:4:43 | userInput | provenance | | +| fastify.js:9:9:9:40 | userInput | fastify.js:10:44:10:52 | userInput | provenance | | +| fastify.js:9:21:9:33 | request.query | fastify.js:9:9:9:40 | userInput | provenance | | +| fastify.js:9:21:9:40 | request.query.onSend | fastify.js:9:9:9:40 | userInput | provenance | | +| fastify.js:15:9:15:44 | userInput | fastify.js:16:44:16:52 | userInput | provenance | | +| fastify.js:15:21:15:33 | request.query | fastify.js:15:9:15:44 | userInput | provenance | | +| fastify.js:15:21:15:44 | request ... Parsing | fastify.js:15:9:15:44 | userInput | provenance | | +| fastify.js:21:9:21:47 | userInput | fastify.js:22:44:22:52 | userInput | provenance | | +| fastify.js:21:21:21:33 | request.query | fastify.js:21:9:21:47 | userInput | provenance | | +| fastify.js:21:21:21:47 | request ... idation | fastify.js:21:9:21:47 | userInput | provenance | | +| fastify.js:26:9:26:44 | userInput | fastify.js:27:44:27:52 | userInput | provenance | | +| fastify.js:26:21:26:33 | request.query | fastify.js:26:9:26:44 | userInput | provenance | | +| fastify.js:26:21:26:44 | request ... Handler | fastify.js:26:9:26:44 | userInput | provenance | | +| fastify.js:31:9:31:50 | userInput | fastify.js:32:44:32:52 | userInput | provenance | | +| fastify.js:31:21:31:33 | request.query | fastify.js:31:9:31:50 | userInput | provenance | | +| fastify.js:31:21:31:50 | request ... ization | fastify.js:31:9:31:50 | userInput | provenance | | +| fastify.js:37:9:37:44 | userInput | fastify.js:38:44:38:52 | userInput | provenance | | +| fastify.js:37:21:37:33 | request.query | fastify.js:37:9:37:44 | userInput | provenance | | +| fastify.js:37:21:37:44 | request ... esponse | fastify.js:37:9:37:44 | userInput | provenance | | +| fastify.js:42:9:42:41 | userInput | fastify.js:43:44:43:52 | userInput | provenance | | +| fastify.js:42:21:42:33 | request.query | fastify.js:42:9:42:41 | userInput | provenance | | +| fastify.js:42:21:42:41 | request ... onError | fastify.js:42:9:42:41 | userInput | provenance | | +| fastify.js:47:9:47:43 | userInput | fastify.js:48:44:48:52 | userInput | provenance | | +| fastify.js:47:21:47:33 | request.query | fastify.js:47:9:47:43 | userInput | provenance | | +| fastify.js:47:21:47:43 | request ... Timeout | fastify.js:47:9:47:43 | userInput | provenance | | +| fastify.js:52:11:52:50 | userInput | fastify.js:53:46:53:54 | userInput | provenance | | +| fastify.js:52:23:52:35 | request.query | fastify.js:52:11:52:50 | userInput | provenance | | +| fastify.js:52:23:52:50 | request ... stAbort | fastify.js:52:11:52:50 | userInput | provenance | | | fastify.js:57:9:57:39 | userInput | fastify.js:58:44:58:52 | userInput | provenance | | | fastify.js:57:9:57:39 | userInput | fastify.js:59:23:59:31 | userInput | provenance | | | fastify.js:57:21:57:33 | request.query | fastify.js:57:9:57:39 | userInput | provenance | | @@ -86,6 +116,46 @@ nodes | express.js:36:15:36:19 | taint | semmle.label | taint | | express.js:42:30:42:32 | msg | semmle.label | msg | | express.js:43:10:43:12 | msg | semmle.label | msg | +| fastify.js:4:9:4:43 | userInput | semmle.label | userInput | +| fastify.js:4:21:4:33 | request.query | semmle.label | request.query | +| fastify.js:4:21:4:43 | request ... Request | semmle.label | request ... Request | +| fastify.js:5:44:5:52 | userInput | semmle.label | userInput | +| fastify.js:9:9:9:40 | userInput | semmle.label | userInput | +| fastify.js:9:21:9:33 | request.query | semmle.label | request.query | +| fastify.js:9:21:9:40 | request.query.onSend | semmle.label | request.query.onSend | +| fastify.js:10:44:10:52 | userInput | semmle.label | userInput | +| fastify.js:15:9:15:44 | userInput | semmle.label | userInput | +| fastify.js:15:21:15:33 | request.query | semmle.label | request.query | +| fastify.js:15:21:15:44 | request ... Parsing | semmle.label | request ... Parsing | +| fastify.js:16:44:16:52 | userInput | semmle.label | userInput | +| fastify.js:21:9:21:47 | userInput | semmle.label | userInput | +| fastify.js:21:21:21:33 | request.query | semmle.label | request.query | +| fastify.js:21:21:21:47 | request ... idation | semmle.label | request ... idation | +| fastify.js:22:44:22:52 | userInput | semmle.label | userInput | +| fastify.js:26:9:26:44 | userInput | semmle.label | userInput | +| fastify.js:26:21:26:33 | request.query | semmle.label | request.query | +| fastify.js:26:21:26:44 | request ... Handler | semmle.label | request ... Handler | +| fastify.js:27:44:27:52 | userInput | semmle.label | userInput | +| fastify.js:31:9:31:50 | userInput | semmle.label | userInput | +| fastify.js:31:21:31:33 | request.query | semmle.label | request.query | +| fastify.js:31:21:31:50 | request ... ization | semmle.label | request ... ization | +| fastify.js:32:44:32:52 | userInput | semmle.label | userInput | +| fastify.js:37:9:37:44 | userInput | semmle.label | userInput | +| fastify.js:37:21:37:33 | request.query | semmle.label | request.query | +| fastify.js:37:21:37:44 | request ... esponse | semmle.label | request ... esponse | +| fastify.js:38:44:38:52 | userInput | semmle.label | userInput | +| fastify.js:42:9:42:41 | userInput | semmle.label | userInput | +| fastify.js:42:21:42:33 | request.query | semmle.label | request.query | +| fastify.js:42:21:42:41 | request ... onError | semmle.label | request ... onError | +| fastify.js:43:44:43:52 | userInput | semmle.label | userInput | +| fastify.js:47:9:47:43 | userInput | semmle.label | userInput | +| fastify.js:47:21:47:33 | request.query | semmle.label | request.query | +| fastify.js:47:21:47:43 | request ... Timeout | semmle.label | request ... Timeout | +| fastify.js:48:44:48:52 | userInput | semmle.label | userInput | +| fastify.js:52:11:52:50 | userInput | semmle.label | userInput | +| fastify.js:52:23:52:35 | request.query | semmle.label | request.query | +| fastify.js:52:23:52:50 | request ... stAbort | semmle.label | request ... stAbort | +| fastify.js:53:46:53:54 | userInput | semmle.label | userInput | | fastify.js:57:9:57:39 | userInput | semmle.label | userInput | | fastify.js:57:21:57:33 | request.query | semmle.label | request.query | | fastify.js:57:21:57:39 | request.query.input | semmle.label | request.query.input | diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js index b8878cdab41c..082061bba3f8 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js @@ -1,56 +1,56 @@ const fastify = require('fastify')({ logger: true }); fastify.addHook('onRequest', async (request, reply) => { - const userInput = request.query.onRequest; // $ MISSING: Source[js/code-injection] - if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] + const userInput = request.query.onRequest; // $ Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ Alert[js/code-injection] }); fastify.addHook('onSend', async (request, reply, payload) => { - const userInput = request.query.onSend; // $ MISSING: Source[js/code-injection] - if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] + const userInput = request.query.onSend; // $ Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ Alert[js/code-injection] return JSON.stringify({ ...JSON.parse(payload), onSend: request.evalResult }); }); fastify.addHook('preParsing', async (request, reply, payload) => { - const userInput = request.query.preParsing; // $ MISSING: Source[js/code-injection] - if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] + const userInput = request.query.preParsing; // $ Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ Alert[js/code-injection] return payload; }); fastify.addHook('preValidation', async (request, reply) => { - const userInput = request.query.preValidation; // $ MISSING: Source[js/code-injection] - if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] + const userInput = request.query.preValidation; // $ Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ Alert[js/code-injection] }); fastify.addHook('preHandler', async (request, reply) => { - const userInput = request.query.preHandler; // $ MISSING: Source[js/code-injection] - if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] + const userInput = request.query.preHandler; // $ Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ Alert[js/code-injection] }); fastify.addHook('preSerialization', async (request, reply, payload) => { - const userInput = request.query.preSerialization; // $ MISSING: Source[js/code-injection] - if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] + const userInput = request.query.preSerialization; // $ Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ Alert[js/code-injection] return payload; }); fastify.addHook('onResponse', async (request, reply) => { - const userInput = request.query.onResponse; // $ MISSING: Source[js/code-injection] - if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] + const userInput = request.query.onResponse; // $ Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ Alert[js/code-injection] }); fastify.addHook('onError', async (request, reply, error) => { - const userInput = request.query.onError; // $ MISSING: Source[js/code-injection] - if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] + const userInput = request.query.onError; // $ Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ Alert[js/code-injection] }); fastify.addHook('onTimeout', async (request, reply) => { - const userInput = request.query.onTimeout; // $ MISSING: Source[js/code-injection] - if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] + const userInput = request.query.onTimeout; // $ Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ Alert[js/code-injection] }); fastify.addHook('onRequestAbort', (request, done) => { - const userInput = request.query.onRequestAbort; // $ MISSING: Source[js/code-injection] - if (userInput) request.evalResult = eval(userInput); // $ MISSING: Alert[js/code-injection] + const userInput = request.query.onRequestAbort; // $ Source[js/code-injection] + if (userInput) request.evalResult = eval(userInput); // $ Alert[js/code-injection] }); fastify.get('/dangerous', async (request, reply) => { From 5c3556da66d7d28d287ec475d51b51dd043aa9b7 Mon Sep 17 00:00:00 2001 From: Napalys Date: Tue, 15 Apr 2025 09:41:52 +0200 Subject: [PATCH 084/336] Add user-controlled property tracking and update code injection alerts in Fastify hooks --- .../semmle/javascript/frameworks/Fastify.qll | 28 +++++++++++++++++++ .../CodeInjection/CodeInjection.expected | 6 ++++ .../HeuristicSourceCodeInjection.expected | 3 ++ .../Security/CWE-094/CodeInjection/fastify.js | 6 ++-- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll index 5b2485c76794..53c92e7f7b33 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll @@ -238,6 +238,20 @@ module Fastify { } } + /** + * Gets the property name where user-controlled input is written to a request or response object + * in a route handler. This is used to track taint flow through request and response object properties. + */ + private string getUserControlledPropertyName() { + exists(DataFlow::PropWrite write, DataFlow::Node source, RouteHandler rh | + write.getBase*() = + [rh.getARequestSource().ref().getALocalUse(), rh.getAResponseSource().ref().getALocalUse()] and + write.getPropertyName() = result and + write.getRhs() = source and + source = any(Http::RequestInputAccess ria).getASuccessor*() + ) + } + /** * An access to a user-controlled Fastify request input. */ @@ -252,6 +266,20 @@ module Fastify { or kind = "body" and name = "body" + or + kind = "stored" and + name = getUserControlledPropertyName() + ) + or + // Handle reading from reply object with user input stored on it + exists(string name | + ( + this = rh.getAResponseSource().ref().getAPropertyRead(name) + or + this = rh.getAResponseSource().ref().getAPropertyRead+().getAPropertyRead(name) + ) and + kind = "stored" and + name = getUserControlledPropertyName() ) } diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected index 34487a43e630..9a81aa80a2c0 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected @@ -51,6 +51,9 @@ | fastify.js:58:44:58:52 | userInput | fastify.js:57:21:57:39 | request.query.input | fastify.js:58:44:58:52 | userInput | This code execution depends on a $@. | fastify.js:57:21:57:39 | request.query.input | user-provided value | | fastify.js:59:23:59:31 | userInput | fastify.js:57:21:57:33 | request.query | fastify.js:59:23:59:31 | userInput | This code execution depends on a $@. | fastify.js:57:21:57:33 | request.query | user-provided value | | fastify.js:59:23:59:31 | userInput | fastify.js:57:21:57:39 | request.query.input | fastify.js:59:23:59:31 | userInput | This code execution depends on a $@. | fastify.js:57:21:57:39 | request.query.input | user-provided value | +| fastify.js:71:34:71:51 | request.storedCode | fastify.js:71:34:71:51 | request.storedCode | fastify.js:71:34:71:51 | request.storedCode | This code execution depends on a $@. | fastify.js:71:34:71:51 | request.storedCode | user-provided value | +| fastify.js:84:30:84:43 | reply.userCode | fastify.js:84:30:84:43 | reply.userCode | fastify.js:84:30:84:43 | reply.userCode | This code execution depends on a $@. | fastify.js:84:30:84:43 | reply.userCode | user-provided value | +| fastify.js:99:30:99:52 | reply.l ... tedCode | fastify.js:99:30:99:52 | reply.l ... tedCode | fastify.js:99:30:99:52 | reply.l ... tedCode | This code execution depends on a $@. | fastify.js:99:30:99:52 | reply.l ... tedCode | user-provided value | | module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code | This code execution depends on a $@. | module.js:9:16:9:29 | req.query.code | user-provided value | | module.js:11:17:11:30 | req.query.code | module.js:11:17:11:30 | req.query.code | module.js:11:17:11:30 | req.query.code | This code execution depends on a $@. | module.js:11:17:11:30 | req.query.code | user-provided value | | react-native.js:8:32:8:38 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:8:32:8:38 | tainted | This code execution depends on a $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value | @@ -247,6 +250,9 @@ nodes | fastify.js:57:21:57:39 | request.query.input | semmle.label | request.query.input | | fastify.js:58:44:58:52 | userInput | semmle.label | userInput | | fastify.js:59:23:59:31 | userInput | semmle.label | userInput | +| fastify.js:71:34:71:51 | request.storedCode | semmle.label | request.storedCode | +| fastify.js:84:30:84:43 | reply.userCode | semmle.label | reply.userCode | +| fastify.js:99:30:99:52 | reply.l ... tedCode | semmle.label | reply.l ... tedCode | | module.js:9:16:9:29 | req.query.code | semmle.label | req.query.code | | module.js:11:17:11:30 | req.query.code | semmle.label | req.query.code | | react-native.js:7:7:7:33 | tainted | semmle.label | tainted | diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected index 41550a22c9f7..0f52acfa6cde 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected @@ -161,6 +161,9 @@ nodes | fastify.js:57:21:57:39 | request.query.input | semmle.label | request.query.input | | fastify.js:58:44:58:52 | userInput | semmle.label | userInput | | fastify.js:59:23:59:31 | userInput | semmle.label | userInput | +| fastify.js:71:34:71:51 | request.storedCode | semmle.label | request.storedCode | +| fastify.js:84:30:84:43 | reply.userCode | semmle.label | reply.userCode | +| fastify.js:99:30:99:52 | reply.l ... tedCode | semmle.label | reply.l ... tedCode | | module.js:9:16:9:29 | req.query.code | semmle.label | req.query.code | | module.js:11:17:11:30 | req.query.code | semmle.label | req.query.code | | react-native.js:7:7:7:33 | tainted | semmle.label | tainted | diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js index 082061bba3f8..bb5577c7acc1 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js @@ -68,7 +68,7 @@ fastify.addHook('preHandler', async (request, reply) => { fastify.get('/flow-through-request', async (request, reply) => { // Use the stored code from previous hook if (request.storedCode) { - const evaluatedResult = eval(request.storedCode); // $ MISSING: Alert[js/code-injection] + const evaluatedResult = eval(request.storedCode); // $ Alert[js/code-injection] return { result: evaluatedResult }; } return { result: null }; @@ -81,7 +81,7 @@ fastify.addHook('onRequest', async (request, reply) => { fastify.get('/flow-through-reply', async (request, reply) => { // Use the code stored in reply object if (reply.userCode) { - const replyResult = eval(reply.userCode); // $ MISSING: Alert[js/code-injection] + const replyResult = eval(reply.userCode); // $ Alert[js/code-injection] return { result: replyResult }; } return { result: null }; @@ -96,7 +96,7 @@ fastify.addHook('onRequest', async (request, reply) => { fastify.get('/flow-through-reply', async (request, reply) => { // Use the code stored in reply object if (reply.locals && reply.locals.nestedCode) { - const replyResult = eval(reply.locals.nestedCode); // $ MISSING: Alert[js/code-injection] + const replyResult = eval(reply.locals.nestedCode); // $ Alert[js/code-injection] return { result: replyResult }; } return { result: null }; From 1958c192ecdc1ed7cbb88038d1eaf72daaf22e2d Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Tue, 15 Apr 2025 23:00:12 -0400 Subject: [PATCH 085/336] Reimplement EC, MAC, key creation logic + consumer --- java/ql/lib/experimental/Quantum/JCA.qll | 992 +++++++++++------- java/ql/lib/experimental/Quantum/Language.qll | 8 +- .../ql/src/experimental/Quantum/TestCipher.ql | 4 +- .../codeql/cryptography/Model.qll | 125 ++- 4 files changed, 746 insertions(+), 383 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index b75c00c35498..7507c9edbd50 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -2,11 +2,20 @@ import java import semmle.code.java.dataflow.DataFlow import semmle.code.java.dataflow.TaintTracking import semmle.code.java.controlflow.Dominance +import codeql.util.Option module JCAModel { import Language import Crypto::KeyOpAlg as KeyOpAlg + abstract class CipherAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { } + + abstract class EllipticCurveAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { } + + abstract class HashAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { } + + abstract class KeyAgreementAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { } + // TODO: Verify that the PBEWith% case works correctly bindingset[algo] predicate cipher_names(string algo) { @@ -103,10 +112,11 @@ module JCAModel { name.matches("PBEWith%") and result instanceof Crypto::PBES and withSubstring = name.regexpCapture("PBEWith(.*)", 1) + // TODO: add additional } bindingset[name] - Crypto::THashType hash_name_to_hash_type(string name, int digestLength) { + Crypto::THashType hash_name_to_type_known(string name, int digestLength) { name = "SHA-1" and result instanceof Crypto::SHA1 and digestLength = 160 or name = ["SHA-256", "SHA-384", "SHA-512"] and @@ -226,7 +236,7 @@ module JCAModel { string getPadding() { result = this.getValue().splitAt("/", 2) } } - class CipherGetInstanceCall extends Call { + class CipherGetInstanceCall extends MethodCall { CipherGetInstanceCall() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "getInstance") } @@ -236,17 +246,21 @@ module JCAModel { Expr getProviderArg() { result = this.getArgument(1) } } + // TODO: handle key artifact produced by unwrap private class CipherOperationCall extends MethodCall { CipherOperationCall() { - exists(string s | s in ["doFinal", "wrap", "unwrap"] | - this.getMethod().hasQualifiedName("javax.crypto", "Cipher", s) - ) + this.getMethod() + .hasQualifiedName("javax.crypto", "Cipher", ["update", "doFinal", "wrap", "unwrap"]) } + predicate isIntermediate() { this.getMethod().getName() = "update" } + Expr getInput() { result = this.getArgument(0) } Expr getOutput() { - result = this.getArgument(3) + exists(int outputIndex | this.getMethod().getParameter(outputIndex).getName() = "output" | + result = this.getArgument(outputIndex) + ) or this.getMethod().getReturnType().hasName("byte[]") and result = this } @@ -255,17 +269,18 @@ module JCAModel { } /** - * Data-flow configuration modelling flow from a cipher string literal to a `CipherGetInstanceCall` argument. + * Data-flow configuration modelling flow from a cipher string literal to a cipher algorithm consumer. */ - private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { + private module CipherAlgorithmStringToCipherConsumerConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof CipherStringLiteral } predicate isSink(DataFlow::Node sink) { - exists(Crypto::AlgorithmValueConsumer consumer | sink = consumer.getInputNode()) + sink = any(CipherAlgorithmValueConsumer call).getInputNode() } } - module AlgorithmStringToFetchFlow = TaintTracking::Global; + module CipherAlgorithmStringToFetchFlow = + TaintTracking::Global; /** * Note: padding and a mode of operation will only exist when the padding / mode (*and its type*) are determinable. @@ -315,13 +330,13 @@ module JCAModel { class CipherStringLiteralAlgorithmInstance extends Crypto::KeyOperationAlgorithmInstance instanceof CipherStringLiteral { - Crypto::AlgorithmValueConsumer consumer; + CipherAlgorithmValueConsumer consumer; CipherStringLiteralAlgorithmInstance() { - AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) + CipherAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) } - Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } + CipherAlgorithmValueConsumer getConsumer() { result = consumer } override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { result = this // TODO: provider defaults @@ -368,9 +383,9 @@ module JCAModel { override string getRawHashAlgorithmName() { result = super.getPadding() } - override Crypto::THashType getHashFamily() { result = hash_name_to_hash_type(hashName, _) } + override Crypto::THashType getHashFamily() { result = hash_name_to_type_known(hashName, _) } - override int getDigestLength() { exists(hash_name_to_hash_type(hashName, result)) } + override int getDigestLength() { exists(hash_name_to_type_known(hashName, result)) } } class OAEPPaddingAlgorithmInstance extends Crypto::OAEPPaddingAlgorithmInstance, @@ -388,19 +403,13 @@ module JCAModel { * * For example, in `Cipher.getInstance(algorithm)`, this class represents `algorithm`. */ - class CipherGetInstanceAlgorithmArg extends Crypto::AlgorithmValueConsumer instanceof Expr { + class CipherGetInstanceAlgorithmArg extends CipherAlgorithmValueConsumer instanceof Expr { CipherGetInstanceCall call; CipherGetInstanceAlgorithmArg() { this = call.getAlgorithmArg() } override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } - CipherStringLiteral getOrigin(string value) { - AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(result), - DataFlow::exprNode(this.(Expr).getAChildExpr*())) and - value = result.getValue() - } - override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { result.(CipherStringLiteralAlgorithmInstance).getConsumer() = this } @@ -426,133 +435,208 @@ module JCAModel { } } - private newtype TCipherModeFlowState = - TUninitializedCipherModeFlowState() or - TInitializedCipherModeFlowState(CipherInitCall call) or - TUsedCipherModeFlowState(CipherInitCall init) + signature class GetInstanceCallSig instanceof MethodCall; - abstract private class CipherModeFlowState extends TCipherModeFlowState { - string toString() { - this = TUninitializedCipherModeFlowState() and result = "uninitialized" - or - this = TInitializedCipherModeFlowState(_) and result = "initialized" - } + signature class InitCallSig instanceof MethodCall; - abstract Crypto::KeyOperationSubtype getKeyOperationMode(); + signature class UseCallSig instanceof MethodCall { + /** + * Holds if the use is not a final use, such as an `update()` call before `doFinal()` + */ + predicate isIntermediate(); } - private class UninitializedCipherModeFlowState extends CipherModeFlowState, - TUninitializedCipherModeFlowState + module MethodCallOption = Option; + + /** + * An generic analysis module for analyzing the `getInstance` to `initialize` to `doOperation` pattern in the JCA. + * + * For example: + * ``` + * kpg = KeyPairGenerator.getInstance(); + * kpg.initialize(...); + * kpg.generate(...); + * ``` + */ + module GetInstanceInitUseFlowAnalysis< + GetInstanceCallSig GetInstance, InitCallSig Init, UseCallSig Use> { - override Crypto::KeyOperationSubtype getKeyOperationMode() { - result instanceof Crypto::TUnknownKeyOperationMode + newtype TFlowState = + TUninitialized() or + TInitialized(Init call) or + TIntermediateUse(Use call) + + abstract class InitFlowState extends TFlowState { + string toString() { + this = TUninitialized() and result = "Uninitialized" + or + this = TInitialized(_) and result = "Initialized" + // TODO: add intermediate use + } } - } - private class InitializedCipherModeFlowState extends CipherModeFlowState, - TInitializedCipherModeFlowState - { - CipherInitCall call; - DataFlow::Node node1; - DataFlow::Node node2; - Crypto::KeyOperationSubtype mode; + class UninitializedFlowState extends InitFlowState, TUninitialized { } - InitializedCipherModeFlowState() { - this = TInitializedCipherModeFlowState(call) and - DataFlow::localFlowStep(node1, node2) and - node2.asExpr() = call.getQualifier() and - // TODO: does this make this predicate inefficient as it binds with anything? - not node1.asExpr() = call.getQualifier() and - mode = call.getCipherOperationModeType() - } + class InitializedFlowState extends InitFlowState, TInitialized { + Init call; + DataFlow::Node node1; + DataFlow::Node node2; - CipherInitCall getInitCall() { result = call } + InitializedFlowState() { + this = TInitialized(call) and + node2.asExpr() = call.(MethodCall).getQualifier() and + DataFlow::localFlowStep(node1, node2) and + node1 != node2 + } - DataFlow::Node getFstNode() { result = node1 } + Init getInitCall() { result = call } - /** - * Returns the node *to* which the state-changing step occurs - */ - DataFlow::Node getSndNode() { result = node2 } + DataFlow::Node getFstNode() { result = node1 } - override Crypto::KeyOperationSubtype getKeyOperationMode() { result = mode } - } + DataFlow::Node getSndNode() { result = node2 } + } - /** - * Trace from cipher initialization to a cryptographic operation, - * specifically `Cipher.doFinal()`, `Cipher.wrap()`, or `Cipher.unwrap()`. - * - * TODO: handle `Cipher.update()` - */ - private module CipherGetInstanceToCipherOperationConfig implements DataFlow::StateConfigSig { - class FlowState = TCipherModeFlowState; + class IntermediateUseState extends InitFlowState, TIntermediateUse { + Use call; + DataFlow::Node node1; + DataFlow::Node node2; + + IntermediateUseState() { + this = TIntermediateUse(call) and + call.isIntermediate() and + node1.asExpr() = call.(MethodCall).getQualifier() and + node2 = node1 + } - predicate isSource(DataFlow::Node src, FlowState state) { - state instanceof UninitializedCipherModeFlowState and - src.asExpr() instanceof CipherGetInstanceCall + Use getUseCall() { result = call } + + DataFlow::Node getFstNode() { result = node1 } + + DataFlow::Node getSndNode() { result = node2 } } - predicate isSink(DataFlow::Node sink, FlowState state) { none() } // TODO: document this, but this is intentional (avoid cross products?) + module GetInstanceToInitToUseConfig implements DataFlow::StateConfigSig { + class FlowState = InitFlowState; - predicate isSink(DataFlow::Node sink) { - exists(CipherOperationCall c | c.getQualifier() = sink.asExpr()) + predicate isSource(DataFlow::Node src, FlowState state) { + state instanceof UninitializedFlowState and + src.asExpr() instanceof GetInstance + or + src = state.(InitializedFlowState).getSndNode() + or + src = state.(IntermediateUseState).getSndNode() + } + + // TODO: document this, but this is intentional (avoid cross products?) + predicate isSink(DataFlow::Node sink, FlowState state) { none() } + + predicate isSink(DataFlow::Node sink) { + exists(Init c | c.(MethodCall).getQualifier() = sink.asExpr()) + or + exists(Use c | not c.isIntermediate() and c.(MethodCall).getQualifier() = sink.asExpr()) + } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 + ) { + state1 = state1 and + ( + node1 = state2.(InitializedFlowState).getFstNode() and + node2 = state2.(InitializedFlowState).getSndNode() + or + node1 = state2.(IntermediateUseState).getFstNode() and + node2 = state2.(IntermediateUseState).getSndNode() + ) + } + + predicate isBarrier(DataFlow::Node node, FlowState state) { + exists(CipherInitCall call | node.asExpr() = call.getQualifier() | + state instanceof UninitializedFlowState + or + state.(InitializedFlowState).getInitCall() != call + ) + } + } + + module GetInstanceToInitToUseFlow = DataFlow::GlobalWithState; + + GetInstance getInstantiationFromUse( + Use use, GetInstanceToInitToUseFlow::PathNode src, GetInstanceToInitToUseFlow::PathNode sink + ) { + src.getNode().asExpr() = result and + sink.getNode().asExpr() = use.(MethodCall).getQualifier() and + GetInstanceToInitToUseFlow::flowPath(src, sink) } - predicate isAdditionalFlowStep( - DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 + Init getInitFromUse( + Use use, GetInstanceToInitToUseFlow::PathNode src, GetInstanceToInitToUseFlow::PathNode sink ) { - state1 = state1 and - node1 = state2.(InitializedCipherModeFlowState).getFstNode() and - node2 = state2.(InitializedCipherModeFlowState).getSndNode() + src.getNode().asExpr() = result.(MethodCall).getQualifier() and + sink.getNode().asExpr() = use.(MethodCall).getQualifier() and + GetInstanceToInitToUseFlow::flowPath(src, sink) } - predicate isBarrier(DataFlow::Node node, FlowState state) { - exists(CipherInitCall call | node.asExpr() = call.getQualifier() | - state instanceof UninitializedCipherModeFlowState - or - state.(InitializedCipherModeFlowState).getInitCall() != call - ) + predicate hasInit(Use use) { exists(getInitFromUse(use, _, _)) } + + Use getAnIntermediateUseFromFinalUse( + Use final, GetInstanceToInitToUseFlow::PathNode src, GetInstanceToInitToUseFlow::PathNode sink + ) { + not final.isIntermediate() and + result.isIntermediate() and + src.getNode().asExpr() = result.(MethodCall).getQualifier() and + sink.getNode().asExpr() = final.(MethodCall).getQualifier() and + GetInstanceToInitToUseFlow::flowPath(src, sink) } } - module CipherGetInstanceToCipherOperationFlow = - DataFlow::GlobalWithState; + module CipherFlowAnalysisImpl = + GetInstanceInitUseFlowAnalysis; - class CipherOperationInstance extends Crypto::KeyOperationInstance instanceof Call { - Crypto::KeyOperationSubtype mode; - CipherGetInstanceToCipherOperationFlow::PathNode sink; - CipherOperationCall doFinalize; - CipherGetInstanceAlgorithmArg consumer; + module CipherFlow = CipherFlowAnalysisImpl::GetInstanceToInitToUseFlow; - CipherOperationInstance() { - exists(CipherGetInstanceToCipherOperationFlow::PathNode src, CipherGetInstanceCall getCipher | - CipherGetInstanceToCipherOperationFlow::flowPath(src, sink) and - src.getNode().asExpr() = getCipher and - sink.getNode().asExpr() = doFinalize.getQualifier() and - sink.getState().(CipherModeFlowState).getKeyOperationMode() = mode and - this = doFinalize and - consumer = getCipher.getAlgorithmArg() - ) + Crypto::KeyOperationSubtype getKeyOperationSubtypeFromState( + CipherFlowAnalysisImpl::InitFlowState state + ) { + state instanceof CipherFlowAnalysisImpl::UninitializedFlowState and + result = Crypto::TUnknownKeyOperationMode() + or + exists(CipherInitCall call | state = CipherFlowAnalysisImpl::TInitialized(call) | + result = call.getCipherOperationModeType() + ) + } + + class CipherOperationInstance extends Crypto::KeyOperationInstance instanceof CipherOperationCall { + override Crypto::KeyOperationSubtype getKeyOperationSubtype() { + if CipherFlowAnalysisImpl::hasInit(this) + then result = CipherFlowAnalysisImpl::getInitFromUse(this, _, _).getCipherOperationModeType() + else result = Crypto::TUnknownKeyOperationMode() + } + + CipherGetInstanceCall getInstantiationCall() { + result = CipherFlowAnalysisImpl::getInstantiationFromUse(this, _, _) } - override Crypto::KeyOperationSubtype getKeyOperationSubtype() { result = mode } + CipherInitCall getInitCall() { result = CipherFlowAnalysisImpl::getInitFromUse(this, _, _) } override Crypto::ConsumerInputDataFlowNode getNonceConsumer() { - result.asExpr() = sink.getState().(InitializedCipherModeFlowState).getInitCall().getNonceArg() + result.asExpr() = this.getInitCall().getNonceArg() } override Crypto::ConsumerInputDataFlowNode getInputConsumer() { - result = doFinalize.getMessageArg() + result = super.getMessageArg() or + result = CipherFlowAnalysisImpl::getAnIntermediateUseFromFinalUse(this, _, _).getMessageArg() } override Crypto::ConsumerInputDataFlowNode getKeyConsumer() { - result.asExpr() = sink.getState().(InitializedCipherModeFlowState).getInitCall().getKeyArg() + result.asExpr() = this.getInitCall().getKeyArg() } - override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { result = consumer } + override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { + result = this.getInstantiationCall().getAlgorithmArg() + } override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { - result.asExpr() = doFinalize.getOutput() + result.asExpr() = super.getOutput() } } @@ -596,7 +680,6 @@ module JCAModel { } } - // e.g., getPublic or getPrivate class KeyAdditionalFlowSteps extends MethodCall { KeyAdditionalFlowSteps() { this.getCallee().hasQualifiedName("java.security", "KeyPair", "getPublic") @@ -706,12 +789,18 @@ module JCAModel { override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } } - // flow config from a known hash algorithm literal to MessageDigest.getInstance + /* + * Hash Functions + */ + + /** + * Flow from a known hash algorithm name to a `MessageDigest.getInstance(sink)` call. + */ module KnownHashAlgorithmLiteralToMessageDigestConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { hash_names(src.asExpr().(StringLiteral).getValue()) } predicate isSink(DataFlow::Node sink) { - exists(MessageDigestGetInstanceCall call | sink.asExpr() = call.getAlgorithmArg()) + exists(HashAlgorithmValueConsumer consumer | sink = consumer.getInputNode()) } } @@ -719,7 +808,7 @@ module JCAModel { DataFlow::Global; class KnownHashAlgorithm extends Crypto::HashAlgorithmInstance instanceof StringLiteral { - MessageDigestAlgorithmValueConsumer consumer; + HashAlgorithmValueConsumer consumer; KnownHashAlgorithm() { hash_names(this.getValue()) and @@ -727,23 +816,25 @@ module JCAModel { consumer.getInputNode()) } - MessageDigestAlgorithmValueConsumer getConsumer() { result = consumer } + HashAlgorithmValueConsumer getConsumer() { result = consumer } override string getRawHashAlgorithmName() { result = this.(StringLiteral).getValue() } override Crypto::THashType getHashFamily() { - result = hash_name_to_hash_type(this.getRawHashAlgorithmName(), _) + result = hash_name_to_type_known(this.getRawHashAlgorithmName(), _) } override int getDigestLength() { - exists(hash_name_to_hash_type(this.getRawHashAlgorithmName(), result)) + exists(hash_name_to_type_known(this.getRawHashAlgorithmName(), result)) } } - class MessageDigestAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { + class MessageDigestGetInstanceAlgorithmValueConsumer extends HashAlgorithmValueConsumer { MessageDigestGetInstanceCall call; - MessageDigestAlgorithmValueConsumer() { this = call.getAlgorithmArg() } + MessageDigestGetInstanceAlgorithmValueConsumer() { this = call.getAlgorithmArg() } + + MessageDigestGetInstanceCall getInstantiationCall() { result = call } override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } @@ -794,228 +885,244 @@ module JCAModel { } override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { - exists(MessageDigestGetInstanceCall call | - call.getDigestCall() = this and result = call.getAlgorithmArg() + exists(MessageDigestGetInstanceCall getInstanceCall | + getInstanceCall.getDigestCall() = this and + getInstanceCall = + result.(MessageDigestGetInstanceAlgorithmValueConsumer).getInstantiationCall() ) } } - class KeyGeneratorCallAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { - KeyGeneratorGetInstanceCall call; + /* + * Key Generation + */ - KeyGeneratorCallAlgorithmValueConsumer() { this = call.getAlgorithmArg() } + module KeyGeneratorFlowAnalysisImpl = + GetInstanceInitUseFlowAnalysis; - override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } + module KeyGeneratorFlow = KeyGeneratorFlowAnalysisImpl::GetInstanceToInitToUseFlow; - override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { - result.(CipherStringLiteralAlgorithmInstance).getConsumer() = this + abstract class KeyGeneratorParameterSpecClassInstanceExpr extends ClassInstanceExpr { + KeyGeneratorInitCall getAnInitCallUse() { + exists(DataFlow::Node sink | + KeyGeneratorParameterSpecToInitializeFlow::flow(DataFlow::exprNode(this), sink) and + result.getAlgorithmParameterSpecArg() = sink.asExpr() + ) } } - // flow from instance created by getInstance to generateKey - module KeyGeneratorGetInstanceToGenerateConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { - exists(KeyGeneratorGetInstanceCall call | src.asExpr() = call) + class DHGenParameterSpecInstance extends KeyGeneratorParameterSpecClassInstanceExpr { + DHGenParameterSpecInstance() { + this.(ClassInstanceExpr) + .getConstructedType() + .hasQualifiedName("javax.crypto.spec", "DHGenParameterSpec") } - predicate isSink(DataFlow::Node sink) { - exists(KeyGeneratorGenerateCall call | sink.asExpr() = call.(MethodCall).getQualifier()) - } - } + Expr getPrimeSizeArg() { result = this.getArgument(0) } - module KeyGeneratorGetInstanceToGenerateFlow = - DataFlow::Global; + Expr getExponentSizeArg() { result = this.getArgument(1) } + } - class KeyGeneratorGetInstanceCall extends MethodCall { - KeyGeneratorGetInstanceCall() { - this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "getInstance") - or - this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "getInstance") + class DSAParameterSpecInstance extends KeyGeneratorParameterSpecClassInstanceExpr { + DSAParameterSpecInstance() { + this.(ClassInstanceExpr) + .getConstructedType() + .hasQualifiedName("java.security.spec", "DSAParameterSpec") } - Expr getAlgorithmArg() { result = super.getArgument(0) } + Expr getPArg() { result = this.getArgument(0) } - predicate flowsToKeyGenerateCallQualifier(KeyGeneratorGenerateCall sink) { - KeyGeneratorGetInstanceToGenerateFlow::flow(DataFlow::exprNode(this), - DataFlow::exprNode(sink.(MethodCall).getQualifier())) - } - } + Expr getQArg() { result = this.getArgument(1) } - class KeyGeneratorGenerateCall extends Crypto::KeyGenerationOperationInstance instanceof MethodCall - { - Crypto::KeyArtifactType type; + Expr getSeedLenArg() { result = this.getArgument(2) } + } - KeyGeneratorGenerateCall() { - this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "generateKey") and - type instanceof Crypto::TSymmetricKeyType - or - this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "generateKeyPair") and - type instanceof Crypto::TAsymmetricKeyType + class ECGenParameterSpecInstance extends KeyGeneratorParameterSpecClassInstanceExpr { + ECGenParameterSpecInstance() { + this.(ClassInstanceExpr) + .getConstructedType() + .hasQualifiedName("java.security.spec", "ECGenParameterSpec") } - override Crypto::ArtifactOutputDataFlowNode getOutputKeyArtifact() { result.asExpr() = this } - - override Crypto::KeyArtifactType getOutputKeyType() { result = type } + Expr getCurveNameArg() { result = this.getArgument(0) } - override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { - exists(KeyGeneratorGetInstanceCall getInstance | - getInstance.flowsToKeyGenerateCallQualifier(this) and result = getInstance.getAlgorithmArg() - ) - } + Expr getRandomNumberGeneratorArg() { result = this.getArgument(1) } + } - Crypto::AlgorithmInstance getAKnownAlgorithm() { - result = this.getAnAlgorithmValueConsumer().getAKnownAlgorithmSource() + class RSAGenParameterSpecInstance extends KeyGeneratorParameterSpecClassInstanceExpr { + RSAGenParameterSpecInstance() { + this.(ClassInstanceExpr) + .getConstructedType() + .hasQualifiedName("java.security.spec", "RSAGenParameterSpec") } - override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { none() } - - override string getKeySizeFixed() { none() } + Expr getKeySizeArg() { result = this.getArgument(0) } } - module MACKnownAlgorithmToConsumerConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { mac_names(src.asExpr().(StringLiteral).getValue()) } + private module KeyGeneratorParameterSpecToInitializeConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + src.asExpr() instanceof KeyGeneratorParameterSpecClassInstanceExpr + } predicate isSink(DataFlow::Node sink) { - exists(MACGetInstanceCall call | sink.asExpr() = call.getAlgorithmArg()) + exists(KeyGeneratorInitCall c | + c.getKeyType() = Crypto::TAsymmetricKeyType() and + c.getArgument(0) = sink.asExpr() + ) } } - module MACKnownAlgorithmToConsumerFlow = DataFlow::Global; - - module MACGetInstanceToMACOperationFlowConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { src.asExpr() instanceof MACGetInstanceCall } + module KeyGeneratorParameterSpecToInitializeFlow = + DataFlow::Global; - predicate isSink(DataFlow::Node sink) { - exists(MACOperationCall call | sink.asExpr() = call.(MethodCall).getQualifier()) or - exists(MACInitCall call | sink.asExpr() = call.(MethodCall).getQualifier()) + class ECGenParameterSpecClassInstanceExpr extends KeyGeneratorParameterSpecClassInstanceExpr { + ECGenParameterSpecClassInstanceExpr() { + this.(ClassInstanceExpr) + .getConstructedType() + .hasQualifiedName("java.security.spec", "ECGenParameterSpec") } + + Expr getAlgorithmArg() { result = this.getArgument(0) } } - module MACGetInstanceToMACOperationFlow = - DataFlow::Global; + class KeyGenerationAlgorithmValueConsumer extends CipherAlgorithmValueConsumer, + KeyAgreementAlgorithmValueConsumer, EllipticCurveAlgorithmValueConsumer instanceof Expr + { + KeyGeneratorGetInstanceCall instantiationCall; - module MACInitCallToMACOperationFlowConfig implements DataFlow::ConfigSig { - // TODO: use flow state with one config - predicate isSource(DataFlow::Node src) { - exists(MACInitCall init | src.asExpr() = init.getQualifier()) + KeyGenerationAlgorithmValueConsumer() { + // This is only an algorithm value consumer if it accepts a spec rather than a key size (integral) + this = instantiationCall.getAlgorithmArg() and not super.getType() instanceof IntegralType + or + // However, for general elliptic curves, getInstance("EC") is used + // and java.security.spec.ECGenParameterSpec("") is what sets the specific curve. + // The result of ECGenParameterSpec is passed to KeyPairGenerator.initialize + // If the curve is not specified, the default is used. + // We would trace the use of this inside a KeyPairGenerator.initialize + exists(KeyGeneratorInitCall initCall, ECGenParameterSpecClassInstanceExpr spec | + KeyGeneratorFlow::flow(DataFlow::exprNode(instantiationCall), + DataFlow::exprNode(initCall.getQualifier())) and + spec.getAnInitCallUse() = initCall and + spec.getAlgorithmArg() = this + ) } - predicate isSink(DataFlow::Node sink) { - exists(MACOperationCall call | sink.asExpr() = call.(MethodCall).getQualifier()) - } - } + override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } - module MACInitCallToMACOperationFlow = DataFlow::Global; + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + result.(CipherStringLiteralAlgorithmInstance).getConsumer() = this or + result.(KeyAgreementStringLiteralAlgorithmInstance).getConsumer() = this or + result.(EllipticCurveStringLiteralInstance).getConsumer() = this + } - class KnownMACAlgorithm extends Crypto::MACAlgorithmInstance instanceof StringLiteral { - MACGetInstanceAlgorithmValueConsumer consumer; + KeyGeneratorGetInstanceCall getInstantiationCall() { result = instantiationCall } + } - KnownMACAlgorithm() { - mac_names(this.getValue()) and - MACKnownAlgorithmToConsumerFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) + // TODO: Link getAlgorithm from KeyPairGenerator to algorithm instances or AVCs? High priority. + class KeyGeneratorGetInstanceCall extends MethodCall { + KeyGeneratorGetInstanceCall() { + this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "getInstance") + or + this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "getInstance") } - MACGetInstanceAlgorithmValueConsumer getConsumer() { result = consumer } + Expr getAlgorithmArg() { result = super.getArgument(0) } + } - override string getRawMACAlgorithmName() { result = super.getValue() } + class KeyGeneratorInitCall extends MethodCall { + Crypto::TKeyArtifactType keyType; - override Crypto::TMACType getMACType() { - if mac_name_to_mac_type_known(_, super.getValue()) - then mac_name_to_mac_type_known(result, super.getValue()) - else result instanceof Crypto::TOtherMACType + KeyGeneratorInitCall() { + this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "initialize") and + keyType = Crypto::TAsymmetricKeyType() + or + this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", ["init", "initialize"]) and + keyType = Crypto::TSymmetricKeyType() } - } - class MACGetInstanceCall extends MethodCall { - MACGetInstanceCall() { this.getCallee().hasQualifiedName("javax.crypto", "Mac", "getInstance") } + Crypto::TKeyArtifactType getKeyType() { result = keyType } - Expr getAlgorithmArg() { result = this.getArgument(0) } + Expr getAlgorithmParameterSpecArg() { + result = this.getArgument(0) and + this.getMethod().getParameterType(0).hasName("AlgorithmParameterSpec") + } - MACOperationCall getOperation() { - MACGetInstanceToMACOperationFlow::flow(DataFlow::exprNode(this), - DataFlow::exprNode(result.(MethodCall).getQualifier())) + Expr getKeySizeArg() { + result = this.getArgument(0) and + this.getMethod().getParameterType(0) instanceof IntegralType } - MACInitCall getInitCall() { - MACGetInstanceToMACOperationFlow::flow(DataFlow::exprNode(this), - DataFlow::exprNode(result.getQualifier())) + Expr getRandomnessSourceArg() { + exists(int index | + this.getMethod().getParameterType(index).hasName("SecureRandom") and + result = this.getArgument(index) + ) } } - class MACInitCall extends MethodCall { - MACInitCall() { this.getCallee().hasQualifiedName("javax.crypto", "Mac", "init") } - - Expr getKeyArg() { - result = this.getArgument(0) and this.getMethod().getParameterType(0).hasName("Key") - } + class KeyGeneratorGenerateCall extends Crypto::KeyGenerationOperationInstance instanceof MethodCall + { + Crypto::KeyArtifactType type; - MACOperationCall getOperation() { - MACInitCallToMACOperationFlow::flow(DataFlow::exprNode(this.getQualifier()), - DataFlow::exprNode(result.(MethodCall).getQualifier())) + KeyGeneratorGenerateCall() { + this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "generateKey") and + type instanceof Crypto::TSymmetricKeyType + or + this.getCallee() + .hasQualifiedName("java.security", "KeyPairGenerator", ["generateKeyPair", "genKeyPair"]) and + type instanceof Crypto::TAsymmetricKeyType } - } - class MACGetInstanceAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { - MACGetInstanceCall call; + predicate isIntermediate() { none() } - MACGetInstanceAlgorithmValueConsumer() { this = call.getAlgorithmArg() } + override Crypto::ArtifactOutputDataFlowNode getOutputKeyArtifact() { result.asExpr() = this } - override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } + override Crypto::KeyArtifactType getOutputKeyType() { result = type } - override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { - exists(KnownMACAlgorithm l | l.getConsumer() = this and result = l) + override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { + KeyGeneratorFlowAnalysisImpl::getInstantiationFromUse(this, _, _) = + result.(KeyGenerationAlgorithmValueConsumer).getInstantiationCall() } - } - class MACOperationCall extends Crypto::MACOperationInstance instanceof MethodCall { - Expr output; - - MACOperationCall() { - super.getMethod().getDeclaringType().hasQualifiedName("javax.crypto", "Mac") and - ( - super.getMethod().hasStringSignature(["doFinal()", "doFinal(byte[])"]) and this = output - or - super.getMethod().hasStringSignature("doFinal(byte[], int)") and - this.getArgument(0) = output - ) + Crypto::AlgorithmInstance getAKnownAlgorithm() { + result = this.getAnAlgorithmValueConsumer().getAKnownAlgorithmSource() } - override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { - exists(MACGetInstanceCall instantiation | - instantiation.getOperation() = this and result = instantiation.getAlgorithmArg() - ) + override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { + KeyGeneratorFlowAnalysisImpl::getInitFromUse(this, _, _).getKeySizeArg() = result.asExpr() } - override Crypto::ConsumerInputDataFlowNode getKeyConsumer() { - exists(MACGetInstanceCall instantiation, MACInitCall initCall | - instantiation.getOperation() = this and - initCall.getOperation() = this and - instantiation.getInitCall() = initCall and - result.asExpr() = initCall.getKeyArg() - ) - } + override string getKeySizeFixed() { none() } + } - override Crypto::ConsumerInputDataFlowNode getMessageConsumer() { - result.asExpr() = super.getArgument(0) and - super.getMethod().getParameterType(0).hasName("byte[]") + /* + * Key Derivation Functions (KDFs) + */ + + class KeySpecInstantiation extends ClassInstanceExpr { + KeySpecInstantiation() { + this.getConstructedType() + .hasQualifiedName("javax.crypto.spec", + ["PBEKeySpec", "SecretKeySpec", "PBEKeySpec", "DESedeKeySpec"]) } + + Expr getPasswordArg() { result = this.getArgument(0) } } - module SecretKeyFactoryGetInstanceToGenerateSecretFlowConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { - exists(SecretKeyFactoryGetInstanceCall call | src.asExpr() = call) - } + class PBEKeySpecInstantiation extends KeySpecInstantiation { + PBEKeySpecInstantiation() { this.getConstructedType().hasName("PBEKeySpec") } - predicate isSink(DataFlow::Node sink) { - exists(SecretKeyFactoryGenerateSecretCall call | - sink.asExpr() = call.(MethodCall).getQualifier() - ) - } + Expr getSaltArg() { result = this.getArgument(1) } + + Expr getIterationCountArg() { result = this.getArgument(2) } + + Expr getKeyLengthArg() { result = this.getArgument(3) } } - module PBEKeySpecInstantiationToGenerateSecretFlowConfig implements DataFlow::ConfigSig { + module KeySpecInstantiationToGenerateSecretFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { - exists(PBEKeySpecInstantiation call | src.asExpr() = call) + exists(KeySpecInstantiation call | src.asExpr() = call) } predicate isSink(DataFlow::Node sink) { @@ -1031,28 +1138,21 @@ module JCAModel { } } - module SecretKeyFactoryGetInstanceToGenerateSecretFlow = - DataFlow::Global; - - module PBEKeySpecInstantiationToGenerateSecretFlow = - DataFlow::Global; + module KeySpecInstantiationToGenerateSecretFlow = + DataFlow::Global; module KDFAlgorithmStringToGetInstanceFlow = DataFlow::Global; - class PBEKeySpecInstantiation extends ClassInstanceExpr { - PBEKeySpecInstantiation() { - this.getConstructedType().hasQualifiedName("javax.crypto.spec", "PBEKeySpec") - } - - Expr getPasswordArg() { result = this.getArgument(0) } + class DUMMY_UNUSED_METHODCALL extends MethodCall { + DUMMY_UNUSED_METHODCALL() { none() } + } - Expr getSaltArg() { result = this.getArgument(1) } + module SecretKeyFactoryFlowAnalysisImpl = + GetInstanceInitUseFlowAnalysis; - Expr getIterationCountArg() { result = this.getArgument(2) } - - Expr getKeyLengthArg() { result = this.getArgument(3) } - } + module SecretKeyFactoryFlow = SecretKeyFactoryFlowAnalysisImpl::GetInstanceToInitToUseFlow; class SecretKeyFactoryGetInstanceCall extends MethodCall { SecretKeyFactoryGetInstanceCall() { @@ -1060,11 +1160,16 @@ module JCAModel { } Expr getAlgorithmArg() { result = this.getArgument(0) } + } - SecretKeyFactoryGenerateSecretCall getOperation() { - SecretKeyFactoryGetInstanceToGenerateSecretFlow::flow(DataFlow::exprNode(this), - DataFlow::exprNode(result.(MethodCall).getQualifier())) + class SecretKeyFactoryGenerateSecretCall extends MethodCall { + SecretKeyFactoryGenerateSecretCall() { + this.getCallee().hasQualifiedName("javax.crypto", "SecretKeyFactory", "generateSecret") } + + Expr getKeySpecArg() { result = this.getArgument(0) } + + predicate isIntermediate() { none() } } class KDFAlgorithmStringLiteral extends Crypto::KeyDerivationAlgorithmInstance instanceof StringLiteral @@ -1096,11 +1201,11 @@ module JCAModel { override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { result = this } override Crypto::THashType getHashFamily() { - result = hash_name_to_hash_type(this.getRawHashAlgorithmName(), _) + result = hash_name_to_type_known(this.getRawHashAlgorithmName(), _) } override int getDigestLength() { - exists(hash_name_to_hash_type(this.getRawHashAlgorithmName(), result)) + exists(hash_name_to_type_known(this.getRawHashAlgorithmName(), result)) } override string getRawMACAlgorithmName() { @@ -1133,51 +1238,41 @@ module JCAModel { SecretKeyFactoryGetInstanceCall getInstantiation() { result = call } } - class SecretKeyFactoryGenerateSecretCall extends Crypto::KeyDerivationOperationInstance instanceof MethodCall + class KeyDerivationOperationCall extends Crypto::KeyDerivationOperationInstance instanceof SecretKeyFactoryGenerateSecretCall { - SecretKeyFactoryGenerateSecretCall() { - super.getCallee().hasQualifiedName("javax.crypto", "SecretKeyFactory", "generateSecret") - } - - Expr getKeySpecArg() { - result = super.getArgument(0) and - super.getMethod().getParameterType(0).hasName("KeySpec") - } + KeyDerivationOperationCall() { not super.isIntermediate() } - PBEKeySpecInstantiation getInstantiation() { - PBEKeySpecInstantiationToGenerateSecretFlow::flow(DataFlow::exprNode(result), - DataFlow::exprNode(this.getKeySpecArg())) + KeySpecInstantiation getKeySpecInstantiation() { + KeySpecInstantiationToGenerateSecretFlow::flow(DataFlow::exprNode(result), + DataFlow::exprNode(super.getKeySpecArg())) } override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { - exists(SecretKeyFactoryGetInstanceCall instantiation | - instantiation.getOperation() = this and result = instantiation.getAlgorithmArg() - ) + result.(SecretKeyFactoryKDFAlgorithmValueConsumer).getInstantiation() = + SecretKeyFactoryFlowAnalysisImpl::getInstantiationFromUse(this, _, _) } override Crypto::ConsumerInputDataFlowNode getSaltConsumer() { - result.asExpr() = this.getInstantiation().getSaltArg() + result.asExpr() = this.getKeySpecInstantiation().(PBEKeySpecInstantiation).getSaltArg() } override Crypto::ConsumerInputDataFlowNode getInputConsumer() { - result.asExpr() = this.getInstantiation().getPasswordArg() + result.asExpr() = this.getKeySpecInstantiation().getPasswordArg() } override Crypto::ConsumerInputDataFlowNode getIterationCountConsumer() { - result.asExpr() = this.getInstantiation().getIterationCountArg() + result.asExpr() = + this.getKeySpecInstantiation().(PBEKeySpecInstantiation).getIterationCountArg() } - override Crypto::ArtifactOutputDataFlowNode getOutputKeyArtifact() { - result.asExpr() = this and - super.getMethod().getReturnType().hasName("SecretKey") - } + override Crypto::ArtifactOutputDataFlowNode getOutputKeyArtifact() { result.asExpr() = this } override Crypto::ConsumerInputDataFlowNode getOutputKeySizeConsumer() { - result.asExpr() = this.getInstantiation().getKeyLengthArg() + result.asExpr() = this.getKeySpecInstantiation().(PBEKeySpecInstantiation).getKeyLengthArg() } override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { - result.asExpr() = this.getInstantiation().getKeyLengthArg() + result.asExpr() = this.getKeySpecInstantiation().(PBEKeySpecInstantiation).getKeyLengthArg() } override string getKeySizeFixed() { none() } @@ -1187,23 +1282,31 @@ module JCAModel { override string getIterationCountFixed() { none() } } + /* + * Key agreement + */ + + module KeyAgreementFlowAnalysisImpl = + GetInstanceInitUseFlowAnalysis; + class KeyAgreementStringLiteral extends StringLiteral { KeyAgreementStringLiteral() { key_agreement_names(this.getValue()) } } /** - * Data-flow configuration modelling flow from a key agreement literal to a value consumer argument. + * Data-flow configuration modelling flow from a key agreement string literal to a key agreement algorithm consumer. */ - private module KeyAgreementAlgorithmStringToFetchConfig implements DataFlow::ConfigSig { + private module KeyAgreementAlgorithmStringToConsumerConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof KeyAgreementStringLiteral } predicate isSink(DataFlow::Node sink) { - exists(Crypto::AlgorithmValueConsumer consumer | sink = consumer.getInputNode()) + sink = any(KeyAgreementAlgorithmValueConsumer consumer).getInputNode() } } - module KeyAgreementAlgorithmStringToFetchFlow = - TaintTracking::Global; + module KeyAgreementAlgorithmStringToConsumerFlow = + TaintTracking::Global; class KeyAgreementInitCall extends MethodCall { KeyAgreementInitCall() { @@ -1213,24 +1316,6 @@ module JCAModel { Expr getServerKeyArg() { result = this.getArgument(0) } } - private module KeyAgreementInitQualifierToSecretGenQualifierConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { - exists(KeyAgreementInitCall init | src.asExpr() = init.getQualifier()) - } - - predicate isSink(DataFlow::Node sink) { - exists(KeyAgreementGenerateSecretCall c | sink.asExpr() = c.getQualifier()) - } - - /** - * Barrier if we go into another init, assume the second init overwrites the first - */ - predicate isBarrierIn(DataFlow::Node node) { isSource(node) } - } - - module KeyAgreementInitQualifierToSecretGenQualifierFlow = - DataFlow::Global; - class KeyAgreementGetInstanceCall extends MethodCall { KeyAgreementGetInstanceCall() { this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "getInstance") @@ -1239,30 +1324,30 @@ module JCAModel { Expr getAlgorithmArg() { result = super.getArgument(0) } } - class KeyAgreementAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { + private class KeyAgreementGetInstanceAlgorithmArgValueConsumer extends KeyAgreementAlgorithmValueConsumer + { KeyAgreementGetInstanceCall call; - KeyAgreementAlgorithmValueConsumer() { this = call.getAlgorithmArg() } - - DataFlow::Node getResultNode() { result.asExpr() = call } + KeyAgreementGetInstanceAlgorithmArgValueConsumer() { this = call.getAlgorithmArg() } override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { result.(KeyAgreementStringLiteralAlgorithmInstance).getConsumer() = this } + + KeyAgreementGetInstanceCall getInstantiationCall() { result = call } } class KeyAgreementStringLiteralAlgorithmInstance extends Crypto::KeyAgreementAlgorithmInstance instanceof KeyAgreementStringLiteral { - Crypto::AlgorithmValueConsumer consumer; + KeyAgreementAlgorithmValueConsumer consumer; KeyAgreementStringLiteralAlgorithmInstance() { - KeyAgreementAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) + KeyAgreementAlgorithmStringToConsumerFlow::flow(DataFlow::exprNode(this), + consumer.getInputNode()) } - Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } - override string getRawKeyAgreementAlgorithmName() { result = super.getValue() } override Crypto::TKeyAgreementType getKeyAgreementType() { @@ -1270,48 +1355,231 @@ module JCAModel { then key_agreement_name_to_type_known(result, super.getValue()) else result = Crypto::UnknownKeyAgreementType() } + + KeyAgreementAlgorithmValueConsumer getConsumer() { result = consumer } + } + + class KeyAgreementCall extends MethodCall { + KeyAgreementCall() { + this.getCallee() + .hasQualifiedName("javax.crypto", "KeyAgreement", ["generateSecret", "doPhase"]) + } + + predicate isIntermediate() { this.getCallee().getName() = "doPhase" } + + DataFlow::Node getOutputNode() { + result.asExpr() = this and + not this.isIntermediate() + } + + Expr getPeerKeyArg() { + this.isIntermediate() and + result = this.getArgument(0) and + this.getCallee().getName() = "doPhase" + } + } + + class KeyAgreementSecretGenerationOperationInstance extends Crypto::KeyAgreementSecretGenerationOperationInstance instanceof KeyAgreementCall + { + KeyAgreementSecretGenerationOperationInstance() { + // exclude doPhase (only include generateSecret) + not super.isIntermediate() + } + + override Crypto::ConsumerInputDataFlowNode getServerKeyConsumer() { + result.asExpr() = KeyAgreementFlowAnalysisImpl::getInitFromUse(this, _, _).getServerKeyArg() + } + + override Crypto::ConsumerInputDataFlowNode getPeerKeyConsumer() { + result.asExpr() = + KeyAgreementFlowAnalysisImpl::getAnIntermediateUseFromFinalUse(this, _, _).getPeerKeyArg() + } + + override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { + result.(KeyAgreementGetInstanceAlgorithmArgValueConsumer).getInstantiationCall() = + KeyAgreementFlowAnalysisImpl::getInstantiationFromUse(this, _, _) + } + + override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { result.asExpr() = this } } - class KeyAgreementGenerateSecretCall extends MethodCall { - KeyAgreementGenerateSecretCall() { - this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "generateSecret") + /* + * MACs + */ + + module MACKnownAlgorithmToConsumerConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { mac_names(src.asExpr().(StringLiteral).getValue()) } + + predicate isSink(DataFlow::Node sink) { + exists(MACGetInstanceCall call | sink.asExpr() = call.getAlgorithmArg()) } + } + + module MACKnownAlgorithmToConsumerFlow = DataFlow::Global; - KeyAgreementInitCall getKeyAgreementInitCall() { - KeyAgreementInitQualifierToSecretGenQualifierFlow::flow(DataFlow::exprNode(result - .getQualifier()), DataFlow::exprNode(this.getQualifier())) + module MACGetInstanceToMACOperationFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof MACGetInstanceCall } + + predicate isSink(DataFlow::Node sink) { + exists(MACOperationCall call | sink.asExpr() = call.(MethodCall).getQualifier()) or + exists(MACInitCall call | sink.asExpr() = call.(MethodCall).getQualifier()) } } - private module KeyAgreementAVCToInitQualifierConfig implements DataFlow::ConfigSig { + module MACGetInstanceToMACOperationFlow = + DataFlow::Global; + + module MACInitCallToMACOperationFlowConfig implements DataFlow::ConfigSig { + // TODO: use flow state with one config predicate isSource(DataFlow::Node src) { - exists(KeyAgreementAlgorithmValueConsumer consumer | consumer.getResultNode() = src) + exists(MACInitCall init | src.asExpr() = init.getQualifier()) + } + + predicate isSink(DataFlow::Node sink) { + exists(MACOperationCall call | sink.asExpr() = call.(MethodCall).getQualifier()) } + } + + module MACInitCallToMACOperationFlow = DataFlow::Global; + + class KnownMACAlgorithm extends Crypto::MACAlgorithmInstance instanceof StringLiteral { + MACGetInstanceAlgorithmValueConsumer consumer; + + KnownMACAlgorithm() { + mac_names(this.getValue()) and + MACKnownAlgorithmToConsumerFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) + } + + MACGetInstanceAlgorithmValueConsumer getConsumer() { result = consumer } + + override string getRawMACAlgorithmName() { result = super.getValue() } + + override Crypto::TMACType getMACType() { + if mac_name_to_mac_type_known(_, super.getValue()) + then mac_name_to_mac_type_known(result, super.getValue()) + else result instanceof Crypto::TOtherMACType + } + } + + class MACGetInstanceCall extends MethodCall { + MACGetInstanceCall() { this.getCallee().hasQualifiedName("javax.crypto", "Mac", "getInstance") } + + Expr getAlgorithmArg() { result = this.getArgument(0) } + + MACOperationCall getOperation() { + MACGetInstanceToMACOperationFlow::flow(DataFlow::exprNode(this), + DataFlow::exprNode(result.(MethodCall).getQualifier())) + } + + MACInitCall getInitCall() { + MACGetInstanceToMACOperationFlow::flow(DataFlow::exprNode(this), + DataFlow::exprNode(result.getQualifier())) + } + } + + class MACInitCall extends MethodCall { + MACInitCall() { this.getCallee().hasQualifiedName("javax.crypto", "Mac", "init") } + + Expr getKeyArg() { + result = this.getArgument(0) and this.getMethod().getParameterType(0).hasName("Key") + } + + MACOperationCall getOperation() { + MACInitCallToMACOperationFlow::flow(DataFlow::exprNode(this.getQualifier()), + DataFlow::exprNode(result.(MethodCall).getQualifier())) + } + } + + class MACGetInstanceAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { + MACGetInstanceCall call; + + MACGetInstanceAlgorithmValueConsumer() { this = call.getAlgorithmArg() } + + override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } + + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + exists(KnownMACAlgorithm l | l.getConsumer() = this and result = l) + } + } + + class MACOperationCall extends Crypto::MACOperationInstance instanceof MethodCall { + Expr output; + + MACOperationCall() { + super.getMethod().getDeclaringType().hasQualifiedName("javax.crypto", "Mac") and + ( + super.getMethod().hasStringSignature(["doFinal()", "doFinal(byte[])"]) and this = output + or + super.getMethod().hasStringSignature("doFinal(byte[], int)") and + this.getArgument(0) = output + ) + } + + override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { + exists(MACGetInstanceCall instantiation | + instantiation.getOperation() = this and result = instantiation.getAlgorithmArg() + ) + } + + override Crypto::ConsumerInputDataFlowNode getKeyConsumer() { + exists(MACGetInstanceCall instantiation, MACInitCall initCall | + instantiation.getOperation() = this and + initCall.getOperation() = this and + instantiation.getInitCall() = initCall and + result.asExpr() = initCall.getKeyArg() + ) + } + + override Crypto::ConsumerInputDataFlowNode getMessageConsumer() { + result.asExpr() = super.getArgument(0) and + super.getMethod().getParameterType(0).hasName("byte[]") + } + } + + /* + * Elliptic Curves (EC) + */ + + module EllipticCurveStringToConsumerConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof EllipticCurveStringLiteral } predicate isSink(DataFlow::Node sink) { - exists(KeyAgreementInitCall init | sink.asExpr() = init.getQualifier()) + exists(EllipticCurveAlgorithmValueConsumer consumer | sink = consumer.getInputNode()) } } - module KeyAgreementAVCToInitQualifierFlow = - DataFlow::Global; + module EllipticCurveStringToConsumerFlow = DataFlow::Global; - class KeyAgreementSecretGenerationOperationInstance extends Crypto::KeyAgreementSecretGenerationOperationInstance instanceof KeyAgreementGenerateSecretCall + class EllipticCurveStringLiteral extends StringLiteral { + EllipticCurveStringLiteral() { elliptic_curve_names(this.getValue()) } + } + + class EllipticCurveStringLiteralInstance extends Crypto::EllipticCurveInstance instanceof EllipticCurveStringLiteral { - override Crypto::ConsumerInputDataFlowNode getServerKeyConsumer() { - this.(KeyAgreementGenerateSecretCall).getKeyAgreementInitCall().getServerKeyArg() = - result.asExpr() + EllipticCurveAlgorithmValueConsumer consumer; + + EllipticCurveStringLiteralInstance() { + EllipticCurveStringToConsumerFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) } - override Crypto::ConsumerInputDataFlowNode getPeerKeyConsumer() { - none() //TODO + override string getRawEllipticCurveName() { result = super.getValue() } + + override Crypto::TEllipticCurveType getEllipticCurveType() { + if Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getRawEllipticCurveName(), _, _) + then + Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getRawEllipticCurveName(), _, result) + else result = Crypto::OtherEllipticCurveType() } - override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { - none() // TODO: key agreeement has its own algorithm consumer, separate from the key - // TODO: the char pred must trace from the consumer to here, - // in theory, along that path we would get the init and doPhase, but can I just get those - // separately avoiding a complicated config state for dataflow? + override string getKeySize() { + exists(int keySize | + Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getRawEllipticCurveName(), keySize, + _) + | + result = keySize.toString() + ) } + + EllipticCurveAlgorithmValueConsumer getConsumer() { result = consumer } } } diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 8027ef33df7b..1e12f6f1ac8e 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -100,7 +100,7 @@ class ConstantDataSource extends Crypto::GenericConstantSourceInstance instanceo // where typical algorithms are specified, but EC specifically means set up a // default curve container, that will later be specified explicitly (or if not a default) // curve is used. - this = any(Literal l | l.getValue() != "EC") + this.getValue() != "EC" } override DataFlow::Node getOutputNode() { result.asExpr() = this } @@ -194,6 +194,12 @@ module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { node1.(AdditionalFlowInputStep).getOutput() = node2 + or + exists(MethodCall m | + m.getMethod().hasQualifiedName("java.lang", "String", "getBytes") and + node1.asExpr() = m.getQualifier() and + node2.asExpr() = m + ) } } diff --git a/java/ql/src/experimental/Quantum/TestCipher.ql b/java/ql/src/experimental/Quantum/TestCipher.ql index d56e16804408..6779a64f608e 100644 --- a/java/ql/src/experimental/Quantum/TestCipher.ql +++ b/java/ql/src/experimental/Quantum/TestCipher.ql @@ -5,7 +5,7 @@ import experimental.Quantum.Language from - Crypto::CipherOperationNode op, Crypto::KeyOperationAlgorithmNode a, + Crypto::KeyOperationNode op, Crypto::KeyOperationAlgorithmNode a, Crypto::ModeOfOperationAlgorithmNode m, Crypto::PaddingAlgorithmNode p, Crypto::NonceArtifactNode nonce, Crypto::KeyArtifactNode k where @@ -15,4 +15,4 @@ where nonce = op.getANonce() and k = op.getAKey() select op, op.getKeyOperationSubtype(), a, a.getRawAlgorithmName(), m, m.getRawAlgorithmName(), p, - p.getRawAlgorithmName(), nonce, k, k.getSourceElement() + p.getRawAlgorithmName(), nonce, k diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 782c53e1043f..510f334bc626 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -438,6 +438,19 @@ module CryptographyBase Input> { override DataFlowNode getOutputNode() { result = creator.getOutputArtifact() } } + /** + * An artifact representing the shared secret generated by key agreement operations. + */ + final class KeyAgreementSharedSecretOutputArtifactInstance extends OutputArtifactInstance { + KeyAgreementSecretGenerationOperationInstance creator; + + KeyAgreementSharedSecretOutputArtifactInstance() { + Input::dfn_to_element(creator.getOutputArtifact()) = this + } + + override DataFlowNode getOutputNode() { result = creator.getOutputArtifact() } + } + // Artifacts that may be outputs or inputs newtype TKeyArtifactType = TSymmetricKeyType() or @@ -871,7 +884,7 @@ module CryptographyBase Input> { */ abstract string getRawEllipticCurveName(); - abstract TEllipticCurveType getEllipticCurveFamily(); + abstract TEllipticCurveType getEllipticCurveType(); abstract string getKeySize(); @@ -1043,6 +1056,13 @@ module CryptographyBase Input> { * from the peer (the other party in the key agreement). */ abstract ConsumerInputDataFlowNode getPeerKeyConsumer(); + + /** + * The output artifact produced by the key agreement operation. + * This artifact represents the shared secret generated during + * the key agreement process. + */ + abstract ArtifactOutputDataFlowNode getOutputArtifact(); } private signature class AlgorithmInstanceType instanceof AlgorithmInstance; @@ -1066,14 +1086,17 @@ module CryptographyBase Input> { this instanceof Alg or // Or an AlgorithmValueConsumer with unknown sources and no known sources + not this instanceof Alg and isCandidateAVC(this) and not exists(this.(AlgorithmValueConsumer).getAKnownAlgorithmSource()) and - exists(this.(AlgorithmValueConsumer).getAGenericSource()) + exists(GenericSourceInstance src | + src = this.(AlgorithmValueConsumer).getAGenericSource() and src != this + ) } Alg asAlg() { result = this } - AlgorithmValueConsumer asAVC() { result = this } + AlgorithmValueConsumer asAVC() { result = this and not this instanceof Alg } } } @@ -1098,6 +1121,13 @@ module CryptographyBase Input> { private predicate isEllipticCurveAVC(AlgorithmValueConsumer avc) { exists(ECDHKeyAgreementAlgorithmInstance alg | avc = alg.getEllipticCurveAlgorithmValueConsumer() + ) or + exists(KeyGenerationOperationInstance op | op.getAnAlgorithmValueConsumer() = avc) + } + + private predicate isKeyAgreementAVC(AlgorithmValueConsumer avc) { + exists(KeyAgreementSecretGenerationOperationInstance op | + op.getAnAlgorithmValueConsumer() = avc ) } @@ -1116,10 +1146,14 @@ module CryptographyBase Input> { final private class EllipticCurveInstanceOrValueConsumer = AlgorithmInstanceOrValueConsumer::Union; + final private class KeyAgreementAlgorithmInstanceOrValueConsumer = + AlgorithmInstanceOrValueConsumer::Union; + private newtype TNode = // Output artifacts (data that is not an operation or algorithm, e.g., a key) TDigest(DigestArtifactInstance e) or TKey(KeyArtifactInstance e) or + TSharedSecret(KeyAgreementSharedSecretOutputArtifactInstance e) or // Input artifacts (synthetic nodes, used to differentiate input as entities) TNonceInput(NonceArtifactConsumer e) or TMessageInput(MessageArtifactConsumer e) or @@ -1140,12 +1174,13 @@ module CryptographyBase Input> { // All other operations THashOperation(HashOperationInstance e) or TMACOperation(MACOperationInstance e) or + TKeyAgreementOperation(KeyAgreementSecretGenerationOperationInstance e) or // All other algorithms TEllipticCurve(EllipticCurveInstanceOrValueConsumer e) or THashAlgorithm(HashAlgorithmInstanceOrValueConsumer e) or TKeyDerivationAlgorithm(KeyDerivationAlgorithmInstanceOrValueConsumer e) or TMACAlgorithm(MACAlgorithmInstanceOrValueConsumer e) or - TKeyAgreementAlgorithm(KeyAgreementAlgorithmInstance e) or + TKeyAgreementAlgorithm(KeyAgreementAlgorithmInstanceOrValueConsumer e) or // Generic source nodes, i.e., sources of data that are not resolvable to a specific known asset. TGenericSourceNode(GenericSourceInstance e) { // An element modelled as a `GenericSourceInstance` can also be modelled as a `KnownElement` @@ -1492,6 +1527,19 @@ module CryptographyBase Input> { override LocatableElement asElement() { result = instance } } + /** + * A shared secret artifact produced by a key agreement operation. + */ + final class SharedSecretArtifactNode extends ArtifactNode, TSharedSecret { + KeyAgreementSharedSecretOutputArtifactInstance instance; + + SharedSecretArtifactNode() { this = TSharedSecret(instance) } + + final override string getInternalType() { result = "SharedSecret" } + + override LocatableElement asElement() { result = instance } + } + abstract class KeyCreationOperationNode extends OperationNode, TKeyCreationOperation { KeyCreationOperationInstance instance; @@ -1599,6 +1647,48 @@ module CryptographyBase Input> { } } + class KeyAgreementOperationNode extends OperationNode, TKeyAgreementOperation { + KeyAgreementSecretGenerationOperationInstance instance; + + KeyAgreementOperationNode() { this = TKeyAgreementOperation(instance) } + + final override string getInternalType() { result = "KeyAgreementOperation" } + + override LocatableElement asElement() { result = instance } + + override predicate isCandidateAlgorithmNode(AlgorithmNode node) { + node instanceof KeyAgreementAlgorithmNode + } + + SharedSecretArtifactNode getOutput() { + result.asElement() = instance.getOutputArtifact().getArtifact() + } + + override NodeBase getChild(string key) { + result = super.getChild(key) + or + // [ALWAYS_KNOWN] + key = "Output" and + result = this.getOutput() + } + } + + class KeyAgreementAlgorithmNode extends AlgorithmNode, TKeyAgreementAlgorithm { + KeyAgreementAlgorithmInstanceOrValueConsumer instance; + + KeyAgreementAlgorithmNode() { this = TKeyAgreementAlgorithm(instance) } + + final override string getInternalType() { result = "KeyAgreementAlgorithm" } + + override LocatableElement asElement() { result = instance } + + final override string getRawAlgorithmName() { + result = instance.asAlg().getRawKeyAgreementAlgorithmName() + } + + override string getAlgorithmName() { result = this.getRawAlgorithmName() } // TODO: standardize? + } + class KeyGenerationOperationNode extends KeyCreationOperationNode { KeyGenerationOperationInstance keyGenInstance; @@ -2296,16 +2386,17 @@ module CryptographyBase Input> { or curveName = "CURVE25519" and keySize = 255 and curveFamily = CURVE25519() or - curveName = "X25519" and keySize = 255 and curveFamily = CURVE25519() - or - curveName = "ED25519" and keySize = 255 and curveFamily = CURVE25519() - or - curveName = "CURVE448" and keySize = 448 and curveFamily = CURVE448() - or - curveName = "ED448" and keySize = 448 and curveFamily = CURVE448() - or - curveName = "X448" and keySize = 448 and curveFamily = CURVE448() - or + // TODO: separate these into key agreement logic or sign/verify (ECDSA / ECDH) + // or + // curveName = "X25519" and keySize = 255 and curveFamily = CURVE25519() + // or + // curveName = "ED25519" and keySize = 255 and curveFamily = CURVE25519() + // or + // curveName = "ED448" and keySize = 448 and curveFamily = CURVE448() + // curveName = "CURVE448" and keySize = 448 and curveFamily = CURVE448() + // or + // or + // curveName = "X448" and keySize = 448 and curveFamily = CURVE448() curveName = "SM2" and keySize in [256, 512] and curveFamily = SM2() ) } @@ -2335,9 +2426,7 @@ module CryptographyBase Input> { override string getAlgorithmName() { result = this.getRawAlgorithmName() } - TEllipticCurveType getEllipticCurveFamily() { - result = instance.asAlg().getEllipticCurveFamily() - } + TEllipticCurveType getEllipticCurveType() { result = instance.asAlg().getEllipticCurveType() } override predicate properties(string key, string value, Location location) { super.properties(key, value, location) @@ -2347,7 +2436,7 @@ module CryptographyBase Input> { value = instance.asAlg().getKeySize() and location = this.getLocation() or - // [ONLY_KNOWN] + // [KNOWN_OR_UNKNOWN] key = "ParsedName" and value = instance.asAlg().getParsedEllipticCurveName() and location = this.getLocation() From 6431228d37663f35c208510ccb1f570eedf0a1ea Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Wed, 16 Apr 2025 09:40:01 +0100 Subject: [PATCH 086/336] Limit size of allowImplicitRead for performance --- .../Variables/LoopVariableCapture/LoopVariableCaptureQuery.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/Variables/LoopVariableCapture/LoopVariableCaptureQuery.qll b/python/ql/src/Variables/LoopVariableCapture/LoopVariableCaptureQuery.qll index ed0c64961413..7f25701cac8e 100644 --- a/python/ql/src/Variables/LoopVariableCapture/LoopVariableCaptureQuery.qll +++ b/python/ql/src/Variables/LoopVariableCapture/LoopVariableCaptureQuery.qll @@ -59,7 +59,7 @@ module EscapingCaptureFlowConfig implements DataFlow::ConfigSig { predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet cs) { isSink(node) and ( - cs instanceof DataFlow::TupleElementContent or + cs.(DataFlow::TupleElementContent).getIndex() in [0 .. 10] or cs instanceof DataFlow::ListElementContent or cs instanceof DataFlow::SetElementContent or cs instanceof DataFlow::DictionaryElementAnyContent From 00661b62dc489e08716e6c713ce2ca7dac66a07c Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 22 Apr 2025 12:00:02 +0200 Subject: [PATCH 087/336] JS: Add isMiddlewareSetup() hook to Routing model --- .../ql/lib/semmle/javascript/Routing.qll | 39 ++++++++++++++++++- .../semmle/javascript/frameworks/Fastify.qll | 8 +++- .../CodeInjection/CodeInjection.expected | 18 +++++++++ .../HeuristicSourceCodeInjection.expected | 12 ++++++ .../Security/CWE-094/CodeInjection/fastify.js | 6 +-- 5 files changed, 77 insertions(+), 6 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/Routing.qll b/javascript/ql/lib/semmle/javascript/Routing.qll index 29700a255d61..530322a2d2c4 100644 --- a/javascript/ql/lib/semmle/javascript/Routing.qll +++ b/javascript/ql/lib/semmle/javascript/Routing.qll @@ -139,6 +139,8 @@ module Routing { predicate mayResumeDispatch() { this.getLastChild().mayResumeDispatch() or + isInMiddlewareSetup(this) + or exists(this.(RouteHandler).getAContinuationInvocation()) or // Leaf nodes that aren't functions are assumed to invoke their continuation @@ -155,6 +157,8 @@ module Routing { predicate definitelyResumesDispatch() { this.getLastChild().definitelyResumesDispatch() or + isInMiddlewareSetup(this) + or exists(this.(RouteHandler).getAContinuationInvocation()) or this instanceof MkRouter @@ -325,6 +329,19 @@ module Routing { DataFlow::Node getValueImplicitlyStoredInAccessPath(int n, string path) { none() } } + /** + * Holds if `node` is installed at a route handler that is declared to be a middleware setup, + * and is therefore assume to resume dispatch. + */ + private predicate isInMiddlewareSetup(Node node) { + exists(RouteSetup::Range range | + node = getRouteSetupNode(range) and + range.isMiddlewareSetup() + ) + or + isInMiddlewareSetup(node.getParent()) + } + /** Holds if `pred` and `succ` are adjacent siblings and `succ` is installed after `pred`. */ private predicate areSiblings(Node pred, Node succ) { exists(ValueNode::Range base, int n | @@ -612,6 +629,20 @@ module Routing { * Holds if this route setup targets `router` and occurs at the given `cfgNode`. */ abstract predicate isInstalledAt(Router::Range router, ControlFlowNode cfgNode); + + /** + * Holds if this is a middleware setup, meaning dispatch will resume after the + * route handlers in this route setup have completed (usually meaning that they have returned a promise, which has resolved). + * + * This should only be overridden when the route setup itself determines whether subsequent + * route handlers are invoked afterwards. + * - For Express-like libraries, the route _handler_ determines whether to resume dispatch, + * based on whether the `next` callback is invoked. For such libraries, do not override `isMiddlewareSetup`. + * - For Fastify-like libraries, the route _setup_ determines whether to resume dispatch. + * For example, `.addHook()` will resume dispatch whereas `.get()` will not. `isMiddlewareSetup()` should thus + * hold for `.addHook()` but not for `.get()` calls. + */ + predicate isMiddlewareSetup() { none() } } /** @@ -892,10 +923,14 @@ module Routing { * based on `Node::Range::getValueAtAccessPath`. */ private DataFlow::Node getAnAccessPathRhs(Node base, int n, string path) { - // Assigned in the body of a route handler function, whi + // Assigned in the body of a route handler function, which is a middleware exists(RouteHandler handler | base = handler | result = AccessPath::getAnAssignmentTo(handler.getParameter(n).ref(), path) and - exists(handler.getAContinuationInvocation()) + ( + exists(handler.getAContinuationInvocation()) + or + isInMiddlewareSetup(handler) + ) ) or // Implicit assignment contributed by framework model diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll index 53c92e7f7b33..2c2f0f6fc114 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll @@ -164,13 +164,19 @@ module Fastify { private class ShorthandRoutingTreeSetup extends Routing::RouteSetup::MethodCall instanceof RouteSetup { - ShorthandRoutingTreeSetup() { not this.getMethodName() = "route" } + ShorthandRoutingTreeSetup() { not this.getMethodName() = ["route", "addHook"] } override string getRelativePath() { result = this.getArgument(0).getStringValue() } override Http::RequestMethodName getHttpMethod() { result = this.getMethodName().toUpperCase() } } + private class AddHookRouteSetup extends Routing::RouteSetup::MethodCall instanceof RouteSetup { + AddHookRouteSetup() { this.getMethodName() = "addHook" } + + override predicate isMiddlewareSetup() { any() } + } + /** Gets the name of the `n`th handler function that can be installed a route setup, in order of execution. */ private string getNthHandlerName(int n) { result = diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected index 9a81aa80a2c0..a63cc195ecbd 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected @@ -51,8 +51,14 @@ | fastify.js:58:44:58:52 | userInput | fastify.js:57:21:57:39 | request.query.input | fastify.js:58:44:58:52 | userInput | This code execution depends on a $@. | fastify.js:57:21:57:39 | request.query.input | user-provided value | | fastify.js:59:23:59:31 | userInput | fastify.js:57:21:57:33 | request.query | fastify.js:59:23:59:31 | userInput | This code execution depends on a $@. | fastify.js:57:21:57:33 | request.query | user-provided value | | fastify.js:59:23:59:31 | userInput | fastify.js:57:21:57:39 | request.query.input | fastify.js:59:23:59:31 | userInput | This code execution depends on a $@. | fastify.js:57:21:57:39 | request.query.input | user-provided value | +| fastify.js:71:34:71:51 | request.storedCode | fastify.js:66:24:66:36 | request.query | fastify.js:71:34:71:51 | request.storedCode | This code execution depends on a $@. | fastify.js:66:24:66:36 | request.query | user-provided value | +| fastify.js:71:34:71:51 | request.storedCode | fastify.js:66:24:66:47 | request ... redCode | fastify.js:71:34:71:51 | request.storedCode | This code execution depends on a $@. | fastify.js:66:24:66:47 | request ... redCode | user-provided value | | fastify.js:71:34:71:51 | request.storedCode | fastify.js:71:34:71:51 | request.storedCode | fastify.js:71:34:71:51 | request.storedCode | This code execution depends on a $@. | fastify.js:71:34:71:51 | request.storedCode | user-provided value | +| fastify.js:84:30:84:43 | reply.userCode | fastify.js:79:20:79:32 | request.query | fastify.js:84:30:84:43 | reply.userCode | This code execution depends on a $@. | fastify.js:79:20:79:32 | request.query | user-provided value | +| fastify.js:84:30:84:43 | reply.userCode | fastify.js:79:20:79:42 | request ... plyCode | fastify.js:84:30:84:43 | reply.userCode | This code execution depends on a $@. | fastify.js:79:20:79:42 | request ... plyCode | user-provided value | | fastify.js:84:30:84:43 | reply.userCode | fastify.js:84:30:84:43 | reply.userCode | fastify.js:84:30:84:43 | reply.userCode | This code execution depends on a $@. | fastify.js:84:30:84:43 | reply.userCode | user-provided value | +| fastify.js:99:30:99:52 | reply.l ... tedCode | fastify.js:94:29:94:41 | request.query | fastify.js:99:30:99:52 | reply.l ... tedCode | This code execution depends on a $@. | fastify.js:94:29:94:41 | request.query | user-provided value | +| fastify.js:99:30:99:52 | reply.l ... tedCode | fastify.js:94:29:94:51 | request ... plyCode | fastify.js:99:30:99:52 | reply.l ... tedCode | This code execution depends on a $@. | fastify.js:94:29:94:51 | request ... plyCode | user-provided value | | fastify.js:99:30:99:52 | reply.l ... tedCode | fastify.js:99:30:99:52 | reply.l ... tedCode | fastify.js:99:30:99:52 | reply.l ... tedCode | This code execution depends on a $@. | fastify.js:99:30:99:52 | reply.l ... tedCode | user-provided value | | module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code | This code execution depends on a $@. | module.js:9:16:9:29 | req.query.code | user-provided value | | module.js:11:17:11:30 | req.query.code | module.js:11:17:11:30 | req.query.code | module.js:11:17:11:30 | req.query.code | This code execution depends on a $@. | module.js:11:17:11:30 | req.query.code | user-provided value | @@ -136,6 +142,12 @@ edges | fastify.js:57:9:57:39 | userInput | fastify.js:59:23:59:31 | userInput | provenance | | | fastify.js:57:21:57:33 | request.query | fastify.js:57:9:57:39 | userInput | provenance | | | fastify.js:57:21:57:39 | request.query.input | fastify.js:57:9:57:39 | userInput | provenance | | +| fastify.js:66:24:66:36 | request.query | fastify.js:66:24:66:47 | request ... redCode | provenance | | +| fastify.js:66:24:66:47 | request ... redCode | fastify.js:71:34:71:51 | request.storedCode | provenance | | +| fastify.js:79:20:79:32 | request.query | fastify.js:79:20:79:42 | request ... plyCode | provenance | | +| fastify.js:79:20:79:42 | request ... plyCode | fastify.js:84:30:84:43 | reply.userCode | provenance | | +| fastify.js:94:29:94:41 | request.query | fastify.js:94:29:94:51 | request ... plyCode | provenance | | +| fastify.js:94:29:94:51 | request ... plyCode | fastify.js:99:30:99:52 | reply.l ... tedCode | provenance | | | react-native.js:7:7:7:33 | tainted | react-native.js:8:32:8:38 | tainted | provenance | | | react-native.js:7:7:7:33 | tainted | react-native.js:10:23:10:29 | tainted | provenance | | | react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted | provenance | | @@ -250,8 +262,14 @@ nodes | fastify.js:57:21:57:39 | request.query.input | semmle.label | request.query.input | | fastify.js:58:44:58:52 | userInput | semmle.label | userInput | | fastify.js:59:23:59:31 | userInput | semmle.label | userInput | +| fastify.js:66:24:66:36 | request.query | semmle.label | request.query | +| fastify.js:66:24:66:47 | request ... redCode | semmle.label | request ... redCode | | fastify.js:71:34:71:51 | request.storedCode | semmle.label | request.storedCode | +| fastify.js:79:20:79:32 | request.query | semmle.label | request.query | +| fastify.js:79:20:79:42 | request ... plyCode | semmle.label | request ... plyCode | | fastify.js:84:30:84:43 | reply.userCode | semmle.label | reply.userCode | +| fastify.js:94:29:94:41 | request.query | semmle.label | request.query | +| fastify.js:94:29:94:51 | request ... plyCode | semmle.label | request ... plyCode | | fastify.js:99:30:99:52 | reply.l ... tedCode | semmle.label | reply.l ... tedCode | | module.js:9:16:9:29 | req.query.code | semmle.label | req.query.code | | module.js:11:17:11:30 | req.query.code | semmle.label | req.query.code | diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected index 0f52acfa6cde..aa23d7a6d5a1 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected @@ -45,6 +45,12 @@ edges | fastify.js:57:9:57:39 | userInput | fastify.js:59:23:59:31 | userInput | provenance | | | fastify.js:57:21:57:33 | request.query | fastify.js:57:9:57:39 | userInput | provenance | | | fastify.js:57:21:57:39 | request.query.input | fastify.js:57:9:57:39 | userInput | provenance | | +| fastify.js:66:24:66:36 | request.query | fastify.js:66:24:66:47 | request ... redCode | provenance | | +| fastify.js:66:24:66:47 | request ... redCode | fastify.js:71:34:71:51 | request.storedCode | provenance | | +| fastify.js:79:20:79:32 | request.query | fastify.js:79:20:79:42 | request ... plyCode | provenance | | +| fastify.js:79:20:79:42 | request ... plyCode | fastify.js:84:30:84:43 | reply.userCode | provenance | | +| fastify.js:94:29:94:41 | request.query | fastify.js:94:29:94:51 | request ... plyCode | provenance | | +| fastify.js:94:29:94:51 | request ... plyCode | fastify.js:99:30:99:52 | reply.l ... tedCode | provenance | | | react-native.js:7:7:7:33 | tainted | react-native.js:8:32:8:38 | tainted | provenance | | | react-native.js:7:7:7:33 | tainted | react-native.js:10:23:10:29 | tainted | provenance | | | react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted | provenance | | @@ -161,8 +167,14 @@ nodes | fastify.js:57:21:57:39 | request.query.input | semmle.label | request.query.input | | fastify.js:58:44:58:52 | userInput | semmle.label | userInput | | fastify.js:59:23:59:31 | userInput | semmle.label | userInput | +| fastify.js:66:24:66:36 | request.query | semmle.label | request.query | +| fastify.js:66:24:66:47 | request ... redCode | semmle.label | request ... redCode | | fastify.js:71:34:71:51 | request.storedCode | semmle.label | request.storedCode | +| fastify.js:79:20:79:32 | request.query | semmle.label | request.query | +| fastify.js:79:20:79:42 | request ... plyCode | semmle.label | request ... plyCode | | fastify.js:84:30:84:43 | reply.userCode | semmle.label | reply.userCode | +| fastify.js:94:29:94:41 | request.query | semmle.label | request.query | +| fastify.js:94:29:94:51 | request ... plyCode | semmle.label | request ... plyCode | | fastify.js:99:30:99:52 | reply.l ... tedCode | semmle.label | reply.l ... tedCode | | module.js:9:16:9:29 | req.query.code | semmle.label | req.query.code | | module.js:11:17:11:30 | req.query.code | semmle.label | req.query.code | diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js index bb5577c7acc1..e1cba0d277ca 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js @@ -63,7 +63,7 @@ fastify.get('/dangerous', async (request, reply) => { // Store user input in request object fastify.addHook('preHandler', async (request, reply) => { - request.storedCode = request.query.storedCode; + request.storedCode = request.query.storedCode; // $ Source[js/code-injection] }); fastify.get('/flow-through-request', async (request, reply) => { // Use the stored code from previous hook @@ -76,7 +76,7 @@ fastify.get('/flow-through-request', async (request, reply) => { // Store user input in reply object fastify.addHook('onRequest', async (request, reply) => { - reply.userCode = request.query.replyCode; + reply.userCode = request.query.replyCode; // $ Source[js/code-injection] }); fastify.get('/flow-through-reply', async (request, reply) => { // Use the code stored in reply object @@ -91,7 +91,7 @@ fastify.get('/flow-through-reply', async (request, reply) => { // Store user input in reply object fastify.addHook('onRequest', async (request, reply) => { reply.locals = reply.locals || {}; - reply.locals.nestedCode = request.query.replyCode; + reply.locals.nestedCode = request.query.replyCode; // $ Source[js/code-injection] }); fastify.get('/flow-through-reply', async (request, reply) => { // Use the code stored in reply object From fdfdcc0d9302ef2fe500aa125f3fc3d43aa9f3d6 Mon Sep 17 00:00:00 2001 From: Napalys Date: Tue, 22 Apr 2025 14:16:45 +0200 Subject: [PATCH 088/336] Undo unnecessary name tracking for request, response objects --- .../semmle/javascript/frameworks/Fastify.qll | 28 ------------------- .../CodeInjection/CodeInjection.expected | 3 -- 2 files changed, 31 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll index 2c2f0f6fc114..aaf1dbfdd770 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll @@ -244,20 +244,6 @@ module Fastify { } } - /** - * Gets the property name where user-controlled input is written to a request or response object - * in a route handler. This is used to track taint flow through request and response object properties. - */ - private string getUserControlledPropertyName() { - exists(DataFlow::PropWrite write, DataFlow::Node source, RouteHandler rh | - write.getBase*() = - [rh.getARequestSource().ref().getALocalUse(), rh.getAResponseSource().ref().getALocalUse()] and - write.getPropertyName() = result and - write.getRhs() = source and - source = any(Http::RequestInputAccess ria).getASuccessor*() - ) - } - /** * An access to a user-controlled Fastify request input. */ @@ -272,20 +258,6 @@ module Fastify { or kind = "body" and name = "body" - or - kind = "stored" and - name = getUserControlledPropertyName() - ) - or - // Handle reading from reply object with user input stored on it - exists(string name | - ( - this = rh.getAResponseSource().ref().getAPropertyRead(name) - or - this = rh.getAResponseSource().ref().getAPropertyRead+().getAPropertyRead(name) - ) and - kind = "stored" and - name = getUserControlledPropertyName() ) } diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected index a63cc195ecbd..9ad04af3a2c5 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected @@ -53,13 +53,10 @@ | fastify.js:59:23:59:31 | userInput | fastify.js:57:21:57:39 | request.query.input | fastify.js:59:23:59:31 | userInput | This code execution depends on a $@. | fastify.js:57:21:57:39 | request.query.input | user-provided value | | fastify.js:71:34:71:51 | request.storedCode | fastify.js:66:24:66:36 | request.query | fastify.js:71:34:71:51 | request.storedCode | This code execution depends on a $@. | fastify.js:66:24:66:36 | request.query | user-provided value | | fastify.js:71:34:71:51 | request.storedCode | fastify.js:66:24:66:47 | request ... redCode | fastify.js:71:34:71:51 | request.storedCode | This code execution depends on a $@. | fastify.js:66:24:66:47 | request ... redCode | user-provided value | -| fastify.js:71:34:71:51 | request.storedCode | fastify.js:71:34:71:51 | request.storedCode | fastify.js:71:34:71:51 | request.storedCode | This code execution depends on a $@. | fastify.js:71:34:71:51 | request.storedCode | user-provided value | | fastify.js:84:30:84:43 | reply.userCode | fastify.js:79:20:79:32 | request.query | fastify.js:84:30:84:43 | reply.userCode | This code execution depends on a $@. | fastify.js:79:20:79:32 | request.query | user-provided value | | fastify.js:84:30:84:43 | reply.userCode | fastify.js:79:20:79:42 | request ... plyCode | fastify.js:84:30:84:43 | reply.userCode | This code execution depends on a $@. | fastify.js:79:20:79:42 | request ... plyCode | user-provided value | -| fastify.js:84:30:84:43 | reply.userCode | fastify.js:84:30:84:43 | reply.userCode | fastify.js:84:30:84:43 | reply.userCode | This code execution depends on a $@. | fastify.js:84:30:84:43 | reply.userCode | user-provided value | | fastify.js:99:30:99:52 | reply.l ... tedCode | fastify.js:94:29:94:41 | request.query | fastify.js:99:30:99:52 | reply.l ... tedCode | This code execution depends on a $@. | fastify.js:94:29:94:41 | request.query | user-provided value | | fastify.js:99:30:99:52 | reply.l ... tedCode | fastify.js:94:29:94:51 | request ... plyCode | fastify.js:99:30:99:52 | reply.l ... tedCode | This code execution depends on a $@. | fastify.js:94:29:94:51 | request ... plyCode | user-provided value | -| fastify.js:99:30:99:52 | reply.l ... tedCode | fastify.js:99:30:99:52 | reply.l ... tedCode | fastify.js:99:30:99:52 | reply.l ... tedCode | This code execution depends on a $@. | fastify.js:99:30:99:52 | reply.l ... tedCode | user-provided value | | module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code | This code execution depends on a $@. | module.js:9:16:9:29 | req.query.code | user-provided value | | module.js:11:17:11:30 | req.query.code | module.js:11:17:11:30 | req.query.code | module.js:11:17:11:30 | req.query.code | This code execution depends on a $@. | module.js:11:17:11:30 | req.query.code | user-provided value | | react-native.js:8:32:8:38 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:8:32:8:38 | tainted | This code execution depends on a $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value | From 6df5a1ef8036b7d50ebafc03569d243ba9194231 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 24 Apr 2025 14:14:21 +0200 Subject: [PATCH 089/336] Rust: Extract `SelfParam`s from crate graph --- rust/extractor/src/crate_graph.rs | 45 +++++++++++++++---- .../dataflow/modeled/inline-flow.expected | 18 ++++++++ .../type-inference/type-inference.ql | 3 +- .../PathResolutionConsistency.expected | 13 ++++++ 4 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 rust/ql/test/query-tests/security/CWE-089/CONSISTENCY/PathResolutionConsistency.expected diff --git a/rust/extractor/src/crate_graph.rs b/rust/extractor/src/crate_graph.rs index 0203e8adc47d..8122248aba3c 100644 --- a/rust/extractor/src/crate_graph.rs +++ b/rust/extractor/src/crate_graph.rs @@ -383,25 +383,54 @@ fn emit_function( assert_eq!(sig.binders.len(Interner), parameters.len()); let sig = sig.skip_binders(); let ty_vars = &[parameters]; + let function_data = db.function_data(function); + let mut self_param = None; let params = sig .params() .iter() - .map(|p| { + .enumerate() + .filter_map(|(idx, p)| { let type_repr = emit_hir_ty(trap, db, ty_vars, p); - trap.emit(generated::Param { - id: trap::TrapId::Star, - attrs: vec![], - type_repr, - pat: None, - }) + + if idx == 0 && function_data.has_self_param() { + // Check if the self parameter is a reference + let (is_ref, is_mut) = match p.kind(Interner) { + chalk_ir::TyKind::Ref(mutability, _, _) => { + (true, matches!(mutability, chalk_ir::Mutability::Mut)) + } + chalk_ir::TyKind::Raw(mutability, _) => { + (false, matches!(mutability, chalk_ir::Mutability::Mut)) + } + _ => (false, false), + }; + + self_param = Some(trap.emit(generated::SelfParam { + id: trap::TrapId::Star, + attrs: vec![], + type_repr, + is_ref, + is_mut, + lifetime: None, + name: None, + })); + None + } else { + Some(trap.emit(generated::Param { + id: trap::TrapId::Star, + attrs: vec![], + type_repr, + pat: None, + })) + } }) .collect(); let ret_type = emit_hir_ty(trap, db, ty_vars, sig.ret()); + let param_list = trap.emit(generated::ParamList { id: trap::TrapId::Star, params, - self_param: None, + self_param, }); let ret_type = ret_type.map(|ret_type| { trap.emit(generated::RetTypeRepr { diff --git a/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected b/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected index a7d350ee5acd..ff86fd568dd3 100644 --- a/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected @@ -8,19 +8,29 @@ models | 7 | Summary: lang:core; crate::ptr::write; Argument[1]; Argument[0].Reference; value | edges | main.rs:12:9:12:9 | a [Some] | main.rs:13:10:13:19 | a.unwrap() | provenance | MaD:2 | +| main.rs:12:9:12:9 | a [Some] | main.rs:14:13:14:13 | a [Some] | provenance | | | main.rs:12:9:12:9 | a [Some] | main.rs:14:13:14:21 | a.clone() [Some] | provenance | MaD:1 | | main.rs:12:9:12:9 | a [Some] | main.rs:14:13:14:21 | a.clone() [Some] | provenance | generated | | main.rs:12:13:12:28 | Some(...) [Some] | main.rs:12:9:12:9 | a [Some] | provenance | | | main.rs:12:18:12:27 | source(...) | main.rs:12:13:12:28 | Some(...) [Some] | provenance | | +| main.rs:14:9:14:9 | b [&ref, Some] | main.rs:15:10:15:10 | b [&ref, Some] | provenance | | | main.rs:14:9:14:9 | b [Some] | main.rs:15:10:15:19 | b.unwrap() | provenance | MaD:2 | +| main.rs:14:13:14:13 | a [Some] | main.rs:14:13:14:21 | a.clone() [&ref, Some] | provenance | generated | +| main.rs:14:13:14:21 | a.clone() [&ref, Some] | main.rs:14:9:14:9 | b [&ref, Some] | provenance | | | main.rs:14:13:14:21 | a.clone() [Some] | main.rs:14:9:14:9 | b [Some] | provenance | | +| main.rs:15:10:15:10 | b [&ref, Some] | main.rs:15:10:15:19 | b.unwrap() | provenance | MaD:2 | | main.rs:19:9:19:9 | a [Ok] | main.rs:20:10:20:19 | a.unwrap() | provenance | MaD:5 | +| main.rs:19:9:19:9 | a [Ok] | main.rs:21:13:21:13 | a [Ok] | provenance | | | main.rs:19:9:19:9 | a [Ok] | main.rs:21:13:21:21 | a.clone() [Ok] | provenance | MaD:4 | | main.rs:19:9:19:9 | a [Ok] | main.rs:21:13:21:21 | a.clone() [Ok] | provenance | generated | | main.rs:19:31:19:44 | Ok(...) [Ok] | main.rs:19:9:19:9 | a [Ok] | provenance | | | main.rs:19:34:19:43 | source(...) | main.rs:19:31:19:44 | Ok(...) [Ok] | provenance | | +| main.rs:21:9:21:9 | b [&ref, Ok] | main.rs:22:10:22:10 | b [&ref, Ok] | provenance | | | main.rs:21:9:21:9 | b [Ok] | main.rs:22:10:22:19 | b.unwrap() | provenance | MaD:5 | +| main.rs:21:13:21:13 | a [Ok] | main.rs:21:13:21:21 | a.clone() [&ref, Ok] | provenance | generated | +| main.rs:21:13:21:21 | a.clone() [&ref, Ok] | main.rs:21:9:21:9 | b [&ref, Ok] | provenance | | | main.rs:21:13:21:21 | a.clone() [Ok] | main.rs:21:9:21:9 | b [Ok] | provenance | | +| main.rs:22:10:22:10 | b [&ref, Ok] | main.rs:22:10:22:19 | b.unwrap() | provenance | MaD:5 | | main.rs:26:9:26:9 | a | main.rs:27:10:27:10 | a | provenance | | | main.rs:26:9:26:9 | a | main.rs:28:13:28:21 | a.clone() | provenance | generated | | main.rs:26:13:26:22 | source(...) | main.rs:26:9:26:9 | a | provenance | | @@ -56,15 +66,23 @@ nodes | main.rs:12:13:12:28 | Some(...) [Some] | semmle.label | Some(...) [Some] | | main.rs:12:18:12:27 | source(...) | semmle.label | source(...) | | main.rs:13:10:13:19 | a.unwrap() | semmle.label | a.unwrap() | +| main.rs:14:9:14:9 | b [&ref, Some] | semmle.label | b [&ref, Some] | | main.rs:14:9:14:9 | b [Some] | semmle.label | b [Some] | +| main.rs:14:13:14:13 | a [Some] | semmle.label | a [Some] | +| main.rs:14:13:14:21 | a.clone() [&ref, Some] | semmle.label | a.clone() [&ref, Some] | | main.rs:14:13:14:21 | a.clone() [Some] | semmle.label | a.clone() [Some] | +| main.rs:15:10:15:10 | b [&ref, Some] | semmle.label | b [&ref, Some] | | main.rs:15:10:15:19 | b.unwrap() | semmle.label | b.unwrap() | | main.rs:19:9:19:9 | a [Ok] | semmle.label | a [Ok] | | main.rs:19:31:19:44 | Ok(...) [Ok] | semmle.label | Ok(...) [Ok] | | main.rs:19:34:19:43 | source(...) | semmle.label | source(...) | | main.rs:20:10:20:19 | a.unwrap() | semmle.label | a.unwrap() | +| main.rs:21:9:21:9 | b [&ref, Ok] | semmle.label | b [&ref, Ok] | | main.rs:21:9:21:9 | b [Ok] | semmle.label | b [Ok] | +| main.rs:21:13:21:13 | a [Ok] | semmle.label | a [Ok] | +| main.rs:21:13:21:21 | a.clone() [&ref, Ok] | semmle.label | a.clone() [&ref, Ok] | | main.rs:21:13:21:21 | a.clone() [Ok] | semmle.label | a.clone() [Ok] | +| main.rs:22:10:22:10 | b [&ref, Ok] | semmle.label | b [&ref, Ok] | | main.rs:22:10:22:19 | b.unwrap() | semmle.label | b.unwrap() | | main.rs:26:9:26:9 | a | semmle.label | a | | main.rs:26:13:26:22 | source(...) | semmle.label | source(...) | diff --git a/rust/ql/test/library-tests/type-inference/type-inference.ql b/rust/ql/test/library-tests/type-inference/type-inference.ql index d83900e58402..2652699558ff 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.ql +++ b/rust/ql/test/library-tests/type-inference/type-inference.ql @@ -4,7 +4,8 @@ import codeql.rust.internal.TypeInference as TypeInference import TypeInference query predicate inferType(AstNode n, TypePath path, Type t) { - t = TypeInference::inferType(n, path) + t = TypeInference::inferType(n, path) and + n.fromSource() } module ResolveTest implements TestSig { diff --git a/rust/ql/test/query-tests/security/CWE-089/CONSISTENCY/PathResolutionConsistency.expected b/rust/ql/test/query-tests/security/CWE-089/CONSISTENCY/PathResolutionConsistency.expected new file mode 100644 index 000000000000..9567c4ea5177 --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-089/CONSISTENCY/PathResolutionConsistency.expected @@ -0,0 +1,13 @@ +multipleMethodCallTargets +| sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | From 7e205366ab370d3d7bf532483dafb23278f924f1 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 25 Apr 2025 08:49:02 +0200 Subject: [PATCH 090/336] Rust: Adjust `clone` modeling --- .../lib/codeql/rust/frameworks/stdlib/Clone.qll | 4 +++- .../dataflow/modeled/inline-flow.expected | 16 ++-------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/Clone.qll b/rust/ql/lib/codeql/rust/frameworks/stdlib/Clone.qll index 0798343837e0..514c3781355e 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/Clone.qll +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/Clone.qll @@ -18,7 +18,9 @@ final class CloneCallable extends SummarizedCallable::Range { final override predicate propagatesFlow( string input, string output, boolean preservesValue, string model ) { - input = "Argument[self]" and + // The `clone` method takes a `&self` parameter and dereferences it; + // make sure to not clone the reference itself + input = ["Argument[self].Reference", "Argument[self].WithoutReference"] and output = "ReturnValue" and preservesValue = true and model = "generated" diff --git a/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected b/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected index ff86fd568dd3..b5e19855cfa5 100644 --- a/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected @@ -13,24 +13,18 @@ edges | main.rs:12:9:12:9 | a [Some] | main.rs:14:13:14:21 | a.clone() [Some] | provenance | generated | | main.rs:12:13:12:28 | Some(...) [Some] | main.rs:12:9:12:9 | a [Some] | provenance | | | main.rs:12:18:12:27 | source(...) | main.rs:12:13:12:28 | Some(...) [Some] | provenance | | -| main.rs:14:9:14:9 | b [&ref, Some] | main.rs:15:10:15:10 | b [&ref, Some] | provenance | | | main.rs:14:9:14:9 | b [Some] | main.rs:15:10:15:19 | b.unwrap() | provenance | MaD:2 | -| main.rs:14:13:14:13 | a [Some] | main.rs:14:13:14:21 | a.clone() [&ref, Some] | provenance | generated | -| main.rs:14:13:14:21 | a.clone() [&ref, Some] | main.rs:14:9:14:9 | b [&ref, Some] | provenance | | +| main.rs:14:13:14:13 | a [Some] | main.rs:14:13:14:21 | a.clone() [Some] | provenance | generated | | main.rs:14:13:14:21 | a.clone() [Some] | main.rs:14:9:14:9 | b [Some] | provenance | | -| main.rs:15:10:15:10 | b [&ref, Some] | main.rs:15:10:15:19 | b.unwrap() | provenance | MaD:2 | | main.rs:19:9:19:9 | a [Ok] | main.rs:20:10:20:19 | a.unwrap() | provenance | MaD:5 | | main.rs:19:9:19:9 | a [Ok] | main.rs:21:13:21:13 | a [Ok] | provenance | | | main.rs:19:9:19:9 | a [Ok] | main.rs:21:13:21:21 | a.clone() [Ok] | provenance | MaD:4 | | main.rs:19:9:19:9 | a [Ok] | main.rs:21:13:21:21 | a.clone() [Ok] | provenance | generated | | main.rs:19:31:19:44 | Ok(...) [Ok] | main.rs:19:9:19:9 | a [Ok] | provenance | | | main.rs:19:34:19:43 | source(...) | main.rs:19:31:19:44 | Ok(...) [Ok] | provenance | | -| main.rs:21:9:21:9 | b [&ref, Ok] | main.rs:22:10:22:10 | b [&ref, Ok] | provenance | | | main.rs:21:9:21:9 | b [Ok] | main.rs:22:10:22:19 | b.unwrap() | provenance | MaD:5 | -| main.rs:21:13:21:13 | a [Ok] | main.rs:21:13:21:21 | a.clone() [&ref, Ok] | provenance | generated | -| main.rs:21:13:21:21 | a.clone() [&ref, Ok] | main.rs:21:9:21:9 | b [&ref, Ok] | provenance | | +| main.rs:21:13:21:13 | a [Ok] | main.rs:21:13:21:21 | a.clone() [Ok] | provenance | generated | | main.rs:21:13:21:21 | a.clone() [Ok] | main.rs:21:9:21:9 | b [Ok] | provenance | | -| main.rs:22:10:22:10 | b [&ref, Ok] | main.rs:22:10:22:19 | b.unwrap() | provenance | MaD:5 | | main.rs:26:9:26:9 | a | main.rs:27:10:27:10 | a | provenance | | | main.rs:26:9:26:9 | a | main.rs:28:13:28:21 | a.clone() | provenance | generated | | main.rs:26:13:26:22 | source(...) | main.rs:26:9:26:9 | a | provenance | | @@ -66,23 +60,17 @@ nodes | main.rs:12:13:12:28 | Some(...) [Some] | semmle.label | Some(...) [Some] | | main.rs:12:18:12:27 | source(...) | semmle.label | source(...) | | main.rs:13:10:13:19 | a.unwrap() | semmle.label | a.unwrap() | -| main.rs:14:9:14:9 | b [&ref, Some] | semmle.label | b [&ref, Some] | | main.rs:14:9:14:9 | b [Some] | semmle.label | b [Some] | | main.rs:14:13:14:13 | a [Some] | semmle.label | a [Some] | -| main.rs:14:13:14:21 | a.clone() [&ref, Some] | semmle.label | a.clone() [&ref, Some] | | main.rs:14:13:14:21 | a.clone() [Some] | semmle.label | a.clone() [Some] | -| main.rs:15:10:15:10 | b [&ref, Some] | semmle.label | b [&ref, Some] | | main.rs:15:10:15:19 | b.unwrap() | semmle.label | b.unwrap() | | main.rs:19:9:19:9 | a [Ok] | semmle.label | a [Ok] | | main.rs:19:31:19:44 | Ok(...) [Ok] | semmle.label | Ok(...) [Ok] | | main.rs:19:34:19:43 | source(...) | semmle.label | source(...) | | main.rs:20:10:20:19 | a.unwrap() | semmle.label | a.unwrap() | -| main.rs:21:9:21:9 | b [&ref, Ok] | semmle.label | b [&ref, Ok] | | main.rs:21:9:21:9 | b [Ok] | semmle.label | b [Ok] | | main.rs:21:13:21:13 | a [Ok] | semmle.label | a [Ok] | -| main.rs:21:13:21:21 | a.clone() [&ref, Ok] | semmle.label | a.clone() [&ref, Ok] | | main.rs:21:13:21:21 | a.clone() [Ok] | semmle.label | a.clone() [Ok] | -| main.rs:22:10:22:10 | b [&ref, Ok] | semmle.label | b [&ref, Ok] | | main.rs:22:10:22:19 | b.unwrap() | semmle.label | b.unwrap() | | main.rs:26:9:26:9 | a | semmle.label | a | | main.rs:26:13:26:22 | source(...) | semmle.label | source(...) | From ac3c3ae13a11b2a3a1db1e2ddd758b46401e1399 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 10 Apr 2025 11:45:34 +0200 Subject: [PATCH 091/336] C++: Do not limit second level scopes to the top-level --- .../code/cpp/ir/dataflow/internal/DataFlowPrivate.qll | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index c5024d07dcb4..39975d8883c4 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -1652,8 +1652,6 @@ predicate validParameterAliasStep(Node node1, Node node2) { ) } -private predicate isTopLevel(Cpp::Stmt s) { any(Function f).getBlock().getAStmt() = s } - private Cpp::Stmt getAChainedBranch(Cpp::IfStmt s) { result = s.getThen() or @@ -1684,11 +1682,9 @@ private Instruction getAnInstruction(Node n) { } private newtype TDataFlowSecondLevelScope = - TTopLevelIfBranch(Cpp::Stmt s) { - exists(Cpp::IfStmt ifstmt | s = getAChainedBranch(ifstmt) and isTopLevel(ifstmt)) - } or + TTopLevelIfBranch(Cpp::Stmt s) { s = getAChainedBranch(_) } or TTopLevelSwitchCase(Cpp::SwitchCase s) { - exists(Cpp::SwitchStmt switchstmt | s = switchstmt.getASwitchCase() and isTopLevel(switchstmt)) + exists(Cpp::SwitchStmt switchstmt | s = switchstmt.getASwitchCase()) } /** From 9396f0ee5599abe047211dc7381bda0642a2fa74 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 24 Apr 2025 20:19:29 +0200 Subject: [PATCH 092/336] C++: Set `defaultFieldFlowBranchLimit` to 3 --- .../code/cpp/ir/dataflow/internal/DataFlowImplSpecific.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplSpecific.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplSpecific.qll index dfd207ed7e5b..1b23cf0b9ae2 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplSpecific.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplSpecific.qll @@ -31,4 +31,6 @@ module CppDataFlow implements InputSig { predicate viableImplInCallContext = Private::viableImplInCallContext/2; predicate neverSkipInPathGraph = Private::neverSkipInPathGraph/1; + + int defaultFieldFlowBranchLimit() { result = 3 } } From 63b0dd68c9913be57febbc3b7e7e9d5fa0709d48 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 25 Apr 2025 12:18:42 +0100 Subject: [PATCH 093/336] C++: Add a test with missing summaries. --- .../dataflow/modelgenerator/dataflow/summaries.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/summaries.cpp b/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/summaries.cpp index 8b6da3e8ac57..f3c045fb339d 100644 --- a/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/summaries.cpp +++ b/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/summaries.cpp @@ -198,4 +198,14 @@ int get_x_from_union(U* u) { //contentbased-summary=;;true;set_x_in_union;(U *,int);;Argument[1];Argument[*0].Union[*U];value;dfc-generated void set_x_in_union(U* u, int x) { u->x = x; +} + +struct HasInt { + int x; +}; + + +int copy_struct(HasInt *out, const HasInt *in) { + *out = *in; + return 1; } \ No newline at end of file From 2f265395af0d8994081037f2e783e4266bdad196 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 25 Apr 2025 12:19:25 +0100 Subject: [PATCH 094/336] C++: Add missing predicate to grab the parameter position of a return kind. --- .../src/utils/modelgenerator/internal/CaptureModels.qll | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll index e6bbfe1e5c9a..58acfa011186 100644 --- a/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -295,6 +295,14 @@ module ModelGeneratorInput implements ModelGeneratorInputSig Date: Fri, 25 Apr 2025 12:29:38 +0100 Subject: [PATCH 095/336] C++: Accept test changes. --- .../dataflow/modelgenerator/dataflow/summaries.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/summaries.cpp b/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/summaries.cpp index f3c045fb339d..ffd4956215ae 100644 --- a/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/summaries.cpp +++ b/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/summaries.cpp @@ -131,6 +131,8 @@ namespace Models { //summary=;;true;toplevel_function;(int *);;Argument[0];ReturnValue;taint;df-generated //summary=;;true;toplevel_function;(int *);;Argument[*0];ReturnValue;taint;df-generated +//summary=;;true;toplevel_function;(int *);;Argument[0];Argument[*0];taint;df-generated +//contentbased-summary=;;true;toplevel_function;(int *);;Argument[0];Argument[*0];taint;dfc-generated //contentbased-summary=;;true;toplevel_function;(int *);;Argument[0];ReturnValue;taint;dfc-generated //contentbased-summary=;;true;toplevel_function;(int *);;Argument[*0];ReturnValue;value;dfc-generated int toplevel_function(int* p) { @@ -204,7 +206,12 @@ struct HasInt { int x; }; - +//contentbased-summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[1];Argument[*0];taint;dfc-generated +//contentbased-summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[1];Argument[*1];taint;dfc-generated +//contentbased-summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[*1];Argument[*0];value;dfc-generated +//summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[1];Argument[*0];taint;df-generated +//summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[1];Argument[*1];taint;df-generated +//summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[*1];Argument[*0];taint;df-generated int copy_struct(HasInt *out, const HasInt *in) { *out = *in; return 1; From 89a9ae8bf4eb18198a3cfd31ec43c289b3846397 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Fri, 25 Apr 2025 17:18:09 +0200 Subject: [PATCH 096/336] Bazel: update `rules_kotlin` to 2.1.3 --- MODULE.bazel | 2 +- .../rules_kotlin/2.1.3-codeql.1/MODULE.bazel | 35 +++++++++++++++++++ .../codeql_add_language_version_option.patch | 32 +++++++++++++++++ .../patches/codeql_do_not_emit_jdeps.patch | 16 +++++++++ .../rules_kotlin/2.1.3-codeql.1/source.json | 9 +++++ .../modules/rules_kotlin/metadata.json | 1 + 6 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/MODULE.bazel create mode 100644 misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_add_language_version_option.patch create mode 100644 misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_do_not_emit_jdeps.patch create mode 100644 misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/source.json diff --git a/MODULE.bazel b/MODULE.bazel index ae00bca4390d..7e8e36b53092 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -24,7 +24,7 @@ bazel_dep(name = "bazel_skylib", version = "1.7.1") bazel_dep(name = "abseil-cpp", version = "20240116.1", repo_name = "absl") bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json") bazel_dep(name = "fmt", version = "10.0.0") -bazel_dep(name = "rules_kotlin", version = "2.0.0-codeql.1") +bazel_dep(name = "rules_kotlin", version = "2.1.3-codeql.1") bazel_dep(name = "gazelle", version = "0.40.0") bazel_dep(name = "rules_dotnet", version = "0.17.4") bazel_dep(name = "googletest", version = "1.14.0.bcr.1") diff --git a/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/MODULE.bazel b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/MODULE.bazel new file mode 100644 index 000000000000..41bef52cf9f6 --- /dev/null +++ b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/MODULE.bazel @@ -0,0 +1,35 @@ +module( + name = "rules_kotlin", + version = "2.1.3-codeql.1", + compatibility_level = 1, + repo_name = "rules_kotlin", +) + +bazel_dep(name = "platforms", version = "0.0.11") +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "rules_java", version = "7.2.0") +bazel_dep(name = "rules_python", version = "0.23.1") +bazel_dep(name = "rules_cc", version = "0.0.8") +bazel_dep(name = "rules_android", version = "0.1.1") + +rules_kotlin_extensions = use_extension( + "//src/main/starlark/core/repositories:bzlmod_setup.bzl", + "rules_kotlin_extensions", +) +use_repo( + rules_kotlin_extensions, + "com_github_google_ksp", + "com_github_jetbrains_kotlin", + "com_github_pinterest_ktlint", + "kotlinx_serialization_core_jvm", + "kotlinx_serialization_json", + "kotlinx_serialization_json_jvm", +) + +register_toolchains("//kotlin/internal:default_toolchain") + +# TODO(bencodes) We should be able to remove this once rules_android has rolled out official Bzlmod support +remote_android_extensions = use_extension("@bazel_tools//tools/android:android_extensions.bzl", "remote_android_tools_extensions") +use_repo(remote_android_extensions, "android_gmaven_r8", "android_tools") + +bazel_dep(name = "rules_proto", version = "5.3.0-21.7") diff --git a/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_add_language_version_option.patch b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_add_language_version_option.patch new file mode 100644 index 000000000000..b0bf85d4faef --- /dev/null +++ b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_add_language_version_option.patch @@ -0,0 +1,32 @@ +diff --git a/src/main/starlark/core/options/opts.kotlinc.bzl b/src/main/starlark/core/options/opts.kotlinc.bzl +index 76df826..ef2d6ca 100644 +--- a/src/main/starlark/core/options/opts.kotlinc.bzl ++++ b/src/main/starlark/core/options/opts.kotlinc.bzl +@@ -33,6 +33,11 @@ def _map_jdk_release_to_flag(version): + return None + return ["-Xjdk-release=%s" % version] + ++def _map_language_version_to_flag(version): ++ if not version: ++ return None ++ return ["-language-version=%s" % version, "-api-version=%s" % version] ++ + _KOPTS_ALL = { + "warn": struct( + args = dict( +@@ -429,6 +434,15 @@ _KOPTS_ALL = { + value_to_flag = None, + map_value_to_flag = _map_jdk_release_to_flag, + ), ++ "language_version": struct( ++ args = dict( ++ default = "1.9", ++ doc = "-language-version", ++ ), ++ type = attr.string, ++ value_to_flag = None, ++ map_value_to_flag = _map_language_version_to_flag, ++ ), + } + + def _merge(key, rule_defined): diff --git a/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_do_not_emit_jdeps.patch b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_do_not_emit_jdeps.patch new file mode 100644 index 000000000000..380c837d06a4 --- /dev/null +++ b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_do_not_emit_jdeps.patch @@ -0,0 +1,16 @@ +Emitting jdeps is broken for the 2.0.0 kotlin extractor, and we don't need those files. +Patching it here rather than passing `--@rules_kotlin//kotlin/settings:jvm_emit_jdeps=false` +allows us to not have to specify that option (and therefore pull in `rules_kotlin`) in `semmle-code`. +diff --git a/kotlin/settings/BUILD.bazel b/kotlin/settings/BUILD.bazel +index 2c93c11..f352b80 100644 +--- a/kotlin/settings/BUILD.bazel ++++ b/kotlin/settings/BUILD.bazel +@@ -25,7 +25,7 @@ release_archive( + # Flag that controls the emission of jdeps files during kotlin jvm compilation. + bool_flag( + name = "jvm_emit_jdeps", +- build_setting_default = True, # Upstream default behavior ++ build_setting_default = False, + visibility = ["//visibility:public"], + ) + diff --git a/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/source.json b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/source.json new file mode 100644 index 000000000000..8abac8eb4bd1 --- /dev/null +++ b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/source.json @@ -0,0 +1,9 @@ +{ + "integrity": "sha256-4USKVrJGJAeyaI3qht9cN1s2oJkb1HjC3dlMlxaBJeI=", + "url": "https://github.com/bazelbuild/rules_kotlin/releases/download/v2.1.3/rules_kotlin-v2.1.3.tar.gz", + "patches": { + "codeql_do_not_emit_jdeps.patch": "sha256-1ir4Aio1SICxnj1wafQ0GefT/m7bwn2n+SQwq19V3A8=", + "codeql_add_language_version_option.patch": "sha256-F7RthnrO6kJlCNcQ76L1Utqll2OwyeFZ/HmT82NwgB4=" + }, + "patch_strip": 1 +} diff --git a/misc/bazel/registry/modules/rules_kotlin/metadata.json b/misc/bazel/registry/modules/rules_kotlin/metadata.json index ac259b2e729a..3e11b7df8202 100644 --- a/misc/bazel/registry/modules/rules_kotlin/metadata.json +++ b/misc/bazel/registry/modules/rules_kotlin/metadata.json @@ -21,6 +21,7 @@ "github:bazelbuild/rules_kotlin" ], "versions": [ + "2.1.3-codeql.1", "2.0.0-codeql.1" ], "yanked_versions": {} From 4ac104060ec07b47dc7a752cc22d73432c9b1f17 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Mon, 28 Apr 2025 10:22:11 +0200 Subject: [PATCH 097/336] Bazel: remove `2.0.0` `rules_kotlin` patching --- .../rules_kotlin/2.0.0-codeql.1/MODULE.bazel | 35 ------------------- .../codeql_add_language_version_option.patch | 34 ------------------ .../patches/codeql_do_not_emit_jdeps.patch | 16 --------- .../rules_kotlin/2.0.0-codeql.1/source.json | 9 ----- .../modules/rules_kotlin/metadata.json | 3 +- 5 files changed, 1 insertion(+), 96 deletions(-) delete mode 100644 misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/MODULE.bazel delete mode 100644 misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_add_language_version_option.patch delete mode 100644 misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_do_not_emit_jdeps.patch delete mode 100644 misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/source.json diff --git a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/MODULE.bazel b/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/MODULE.bazel deleted file mode 100644 index 6c11301e2340..000000000000 --- a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/MODULE.bazel +++ /dev/null @@ -1,35 +0,0 @@ -module( - name = "rules_kotlin", - version = "2.0.0-codeql.1", - compatibility_level = 1, - repo_name = "rules_kotlin", -) - -bazel_dep(name = "platforms", version = "0.0.10") -bazel_dep(name = "bazel_skylib", version = "1.7.1") -bazel_dep(name = "rules_java", version = "7.2.0") -bazel_dep(name = "rules_python", version = "0.23.1") -bazel_dep(name = "rules_cc", version = "0.0.8") -bazel_dep(name = "rules_android", version = "0.1.1") - -rules_kotlin_extensions = use_extension( - "//src/main/starlark/core/repositories:bzlmod_setup.bzl", - "rules_kotlin_extensions", -) -use_repo( - rules_kotlin_extensions, - "com_github_google_ksp", - "com_github_jetbrains_kotlin", - "com_github_pinterest_ktlint", - "kotlinx_serialization_core_jvm", - "kotlinx_serialization_json", - "kotlinx_serialization_json_jvm", -) - -register_toolchains("//kotlin/internal:default_toolchain") - -# TODO(bencodes) We should be able to remove this once rules_android has rolled out official Bzlmod support -remote_android_extensions = use_extension("@bazel_tools//tools/android:android_extensions.bzl", "remote_android_tools_extensions") -use_repo(remote_android_extensions, "android_gmaven_r8", "android_tools") - -bazel_dep(name = "rules_proto", version = "5.3.0-21.7") diff --git a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_add_language_version_option.patch b/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_add_language_version_option.patch deleted file mode 100644 index d5716daba07b..000000000000 --- a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_add_language_version_option.patch +++ /dev/null @@ -1,34 +0,0 @@ -We need to build different extractor variants with different -language-version options, which is not allowed -in current kotlin_rules -diff --git a/src/main/starlark/core/options/opts.kotlinc.bzl b/src/main/starlark/core/options/opts.kotlinc.bzl -index 5e1461b..b93e6aa 100644 ---- a/src/main/starlark/core/options/opts.kotlinc.bzl -+++ b/src/main/starlark/core/options/opts.kotlinc.bzl -@@ -33,6 +33,11 @@ def _map_jdk_release_to_flag(version): - return None - return ["-Xjdk-release=%s" % version] - -+def _map_language_version_to_flag(version): -+ if not version: -+ return None -+ return ["-language-version=%s" % version, "-api-version=%s" % version] -+ - _KOPTS_ALL = { - "warn": struct( - args = dict( -@@ -417,6 +422,15 @@ _KOPTS_ALL = { - value_to_flag = None, - map_value_to_flag = _map_jdk_release_to_flag, - ), -+ "language_version": struct( -+ args = dict( -+ default = "1.9", -+ doc = "-language-version", -+ ), -+ type = attr.string, -+ value_to_flag = None, -+ map_value_to_flag = _map_language_version_to_flag, -+ ), - } - - # Filters out options that are not available in current compiler release \ No newline at end of file diff --git a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_do_not_emit_jdeps.patch b/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_do_not_emit_jdeps.patch deleted file mode 100644 index 380c837d06a4..000000000000 --- a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_do_not_emit_jdeps.patch +++ /dev/null @@ -1,16 +0,0 @@ -Emitting jdeps is broken for the 2.0.0 kotlin extractor, and we don't need those files. -Patching it here rather than passing `--@rules_kotlin//kotlin/settings:jvm_emit_jdeps=false` -allows us to not have to specify that option (and therefore pull in `rules_kotlin`) in `semmle-code`. -diff --git a/kotlin/settings/BUILD.bazel b/kotlin/settings/BUILD.bazel -index 2c93c11..f352b80 100644 ---- a/kotlin/settings/BUILD.bazel -+++ b/kotlin/settings/BUILD.bazel -@@ -25,7 +25,7 @@ release_archive( - # Flag that controls the emission of jdeps files during kotlin jvm compilation. - bool_flag( - name = "jvm_emit_jdeps", -- build_setting_default = True, # Upstream default behavior -+ build_setting_default = False, - visibility = ["//visibility:public"], - ) - diff --git a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/source.json b/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/source.json deleted file mode 100644 index 96d828e3455a..000000000000 --- a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/source.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "integrity": "sha256-2JcjzJ67t72y66yhr30jg+B0YVZDz5ejZrdYp2t9xEM=", - "url": "https://github.com/bazelbuild/rules_kotlin/releases/download/v2.0.0/rules_kotlin-v2.0.0.tar.gz", - "patches": { - "codeql_do_not_emit_jdeps.patch": "sha256-1ir4Aio1SICxnj1wafQ0GefT/m7bwn2n+SQwq19V3A8=", - "codeql_add_language_version_option.patch": "sha256-t8Fm0bYZ4Q4vTqcoXZjyK4WPEoAafjE4whJLNnrnRbg=" - }, - "patch_strip": 1 -} diff --git a/misc/bazel/registry/modules/rules_kotlin/metadata.json b/misc/bazel/registry/modules/rules_kotlin/metadata.json index 3e11b7df8202..dace87c72d1c 100644 --- a/misc/bazel/registry/modules/rules_kotlin/metadata.json +++ b/misc/bazel/registry/modules/rules_kotlin/metadata.json @@ -21,8 +21,7 @@ "github:bazelbuild/rules_kotlin" ], "versions": [ - "2.1.3-codeql.1", - "2.0.0-codeql.1" + "2.1.3-codeql.1" ], "yanked_versions": {} } From 6dd8114f0061eba162e399138118717bb3369e7d Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 28 Apr 2025 10:53:17 +0200 Subject: [PATCH 098/336] JS: Add test with trailing comma in JSON object --- .../tests/json/input/object-trailing-comma.json | 6 ++++++ .../output/trap/object-trailing-comma.json.trap | 15 +++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 javascript/extractor/tests/json/input/object-trailing-comma.json create mode 100644 javascript/extractor/tests/json/output/trap/object-trailing-comma.json.trap diff --git a/javascript/extractor/tests/json/input/object-trailing-comma.json b/javascript/extractor/tests/json/input/object-trailing-comma.json new file mode 100644 index 000000000000..79dfec63fbde --- /dev/null +++ b/javascript/extractor/tests/json/input/object-trailing-comma.json @@ -0,0 +1,6 @@ +{ + "object": { + "foo": 1, + "bar": 2, + } +} diff --git a/javascript/extractor/tests/json/output/trap/object-trailing-comma.json.trap b/javascript/extractor/tests/json/output/trap/object-trailing-comma.json.trap new file mode 100644 index 000000000000..428bbc2cd6a9 --- /dev/null +++ b/javascript/extractor/tests/json/output/trap/object-trailing-comma.json.trap @@ -0,0 +1,15 @@ +#10000=@"/object-trailing-comma.json;sourcefile" +files(#10000,"/object-trailing-comma.json") +#10001=@"/;folder" +folders(#10001,"/") +containerparent(#10001,#10000) +#10002=@"loc,{#10000},0,0,0,0" +locations_default(#10002,#10000,0,0,0,0) +hasLocation(#10000,#10002) +#20000=* +json_errors(#20000,"Error: Trailing commas are not allowed in JSON.") +#20001=@"loc,{#10000},5,5,5,5" +locations_default(#20001,#10000,5,5,5,5) +hasLocation(#20000,#20001) +numlines(#10000,6,0,0) +filetype(#10000,"json") From 152d6f3c29db495fcd035e911ed16ba99b315f26 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 28 Apr 2025 10:43:46 +0200 Subject: [PATCH 099/336] JS: Tolerate trailing comma in JSON objects --- .../src/com/semmle/js/parser/JSONParser.java | 3 -- .../trap/object-trailing-comma.json.trap | 28 ++++++++++++++++--- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/parser/JSONParser.java b/javascript/extractor/src/com/semmle/js/parser/JSONParser.java index be55eb8397e0..fba97e3ba9d2 100644 --- a/javascript/extractor/src/com/semmle/js/parser/JSONParser.java +++ b/javascript/extractor/src/com/semmle/js/parser/JSONParser.java @@ -152,9 +152,6 @@ private JSONObject readObject(int startoff, Position start) throws ParseError { char c = next(); switch (c) { case '}': - if (!needsComma) { - raise("Trailing commas are not allowed in JSON."); - } break out; case ',': if (!needsComma) { diff --git a/javascript/extractor/tests/json/output/trap/object-trailing-comma.json.trap b/javascript/extractor/tests/json/output/trap/object-trailing-comma.json.trap index 428bbc2cd6a9..5f36ecaca528 100644 --- a/javascript/extractor/tests/json/output/trap/object-trailing-comma.json.trap +++ b/javascript/extractor/tests/json/output/trap/object-trailing-comma.json.trap @@ -7,9 +7,29 @@ containerparent(#10001,#10000) locations_default(#10002,#10000,0,0,0,0) hasLocation(#10000,#10002) #20000=* -json_errors(#20000,"Error: Trailing commas are not allowed in JSON.") -#20001=@"loc,{#10000},5,5,5,5" -locations_default(#20001,#10000,5,5,5,5) -hasLocation(#20000,#20001) +json(#20000,5,#10000,0,"{\n "" ... }\n}") +#20001=@"loc,{#10000},1,1,6,1" +locations_default(#20001,#10000,1,1,6,1) +json_locations(#20000,#20001) +#20002=* +json(#20002,5,#20000,0,"{\n ... ,\n }") +#20003=@"loc,{#10000},2,15,5,5" +locations_default(#20003,#10000,2,15,5,5) +json_locations(#20002,#20003) +#20004=* +json(#20004,2,#20002,0,"1") +#20005=@"loc,{#10000},3,16,3,16" +locations_default(#20005,#10000,3,16,3,16) +json_locations(#20004,#20005) +json_literals("1","1",#20004) +json_properties(#20002,"foo",#20004) +#20006=* +json(#20006,2,#20002,1,"2") +#20007=@"loc,{#10000},4,16,4,16" +locations_default(#20007,#10000,4,16,4,16) +json_locations(#20006,#20007) +json_literals("2","2",#20006) +json_properties(#20002,"bar",#20006) +json_properties(#20000,"object",#20002) numlines(#10000,6,0,0) filetype(#10000,"json") From e942ec9964a0b73ff2814eb4becee477bba3b185 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 28 Apr 2025 10:39:11 +0100 Subject: [PATCH 100/336] C++: Fix annotations after #19311. --- .../dataflow/modelgenerator/dataflow/summaries.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/summaries.cpp b/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/summaries.cpp index 50e94d95c8b6..74869a69994e 100644 --- a/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/summaries.cpp +++ b/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/summaries.cpp @@ -129,9 +129,9 @@ namespace Models { } } -//summary=;;true;toplevel_function;(int *);;Argument[0];ReturnValue;taint;df-generated -//summary=;;true;toplevel_function;(int *);;Argument[*0];ReturnValue;taint;df-generated -//summary=;;true;toplevel_function;(int *);;Argument[0];Argument[*0];taint;df-generated +//heuristic-summary=;;true;toplevel_function;(int *);;Argument[0];ReturnValue;taint;df-generated +//heuristic-summary=;;true;toplevel_function;(int *);;Argument[*0];ReturnValue;taint;df-generated +//heuristic-summary=;;true;toplevel_function;(int *);;Argument[0];Argument[*0];taint;df-generated //contentbased-summary=;;true;toplevel_function;(int *);;Argument[0];Argument[*0];taint;dfc-generated //contentbased-summary=;;true;toplevel_function;(int *);;Argument[0];ReturnValue;taint;dfc-generated //contentbased-summary=;;true;toplevel_function;(int *);;Argument[*0];ReturnValue;value;dfc-generated @@ -209,9 +209,9 @@ struct HasInt { //contentbased-summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[1];Argument[*0];taint;dfc-generated //contentbased-summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[1];Argument[*1];taint;dfc-generated //contentbased-summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[*1];Argument[*0];value;dfc-generated -//summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[1];Argument[*0];taint;df-generated -//summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[1];Argument[*1];taint;df-generated -//summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[*1];Argument[*0];taint;df-generated +//heuristic-summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[1];Argument[*0];taint;df-generated +//heuristic-summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[1];Argument[*1];taint;df-generated +//heuristic-summary=;;true;copy_struct;(HasInt *,const HasInt *);;Argument[*1];Argument[*0];taint;df-generated int copy_struct(HasInt *out, const HasInt *in) { *out = *in; return 1; From 2d6457e4d36d58531815fd674a8792c0b22678b5 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 28 Apr 2025 11:45:12 +0200 Subject: [PATCH 101/336] C#: Set the precision of cs/equality-on-floats to high. --- csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql b/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql index bdf3ee4e97c8..1109201fbe19 100644 --- a/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql +++ b/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql @@ -5,7 +5,7 @@ * computation does not follow the standard rules of algebra. * @kind problem * @problem.severity warning - * @precision medium + * @precision high * @id cs/equality-on-floats * @tags reliability * correctness From 318bfc6d7386f19b9e6692ef3b48ff9b8cf258eb Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 28 Apr 2025 13:32:34 +0200 Subject: [PATCH 102/336] C#: Add cs/equality-on-floats to the code-quality suite. --- csharp/ql/src/codeql-suites/csharp-code-quality.qls | 1 + 1 file changed, 1 insertion(+) diff --git a/csharp/ql/src/codeql-suites/csharp-code-quality.qls b/csharp/ql/src/codeql-suites/csharp-code-quality.qls index 64a100acda22..85bbe4db683d 100644 --- a/csharp/ql/src/codeql-suites/csharp-code-quality.qls +++ b/csharp/ql/src/codeql-suites/csharp-code-quality.qls @@ -14,3 +14,4 @@ - cs/non-short-circuit - cs/useless-assignment-to-local - cs/invalid-string-formatting + - cs/equality-on-floats From 8bc965641ae488a2175b2364f3c5c41d5f0ab502 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 28 Apr 2025 13:38:15 +0200 Subject: [PATCH 103/336] C#: Update integration tests expected output. --- .../posix/query-suite/csharp-code-quality.qls.expected | 1 + 1 file changed, 1 insertion(+) diff --git a/csharp/ql/integration-tests/posix/query-suite/csharp-code-quality.qls.expected b/csharp/ql/integration-tests/posix/query-suite/csharp-code-quality.qls.expected index 472e79575ca5..dc3791621c3e 100644 --- a/csharp/ql/integration-tests/posix/query-suite/csharp-code-quality.qls.expected +++ b/csharp/ql/integration-tests/posix/query-suite/csharp-code-quality.qls.expected @@ -5,6 +5,7 @@ ql/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql ql/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql ql/csharp/ql/src/Likely Bugs/Collections/ContainerSizeCmpZero.ql ql/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql +ql/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql ql/csharp/ql/src/Likely Bugs/ReferenceEqualsOnValueTypes.ql ql/csharp/ql/src/Likely Bugs/SelfAssignment.ql ql/csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql From f9d8be1ef75a9eb38cf57c9047ef1af1562e8087 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 28 Apr 2025 13:41:06 +0200 Subject: [PATCH 104/336] C#: Add change note. --- .../change-notes/2025-04-28-equality-on-floats-precision.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 csharp/ql/src/change-notes/2025-04-28-equality-on-floats-precision.md diff --git a/csharp/ql/src/change-notes/2025-04-28-equality-on-floats-precision.md b/csharp/ql/src/change-notes/2025-04-28-equality-on-floats-precision.md new file mode 100644 index 000000000000..a990d236eecb --- /dev/null +++ b/csharp/ql/src/change-notes/2025-04-28-equality-on-floats-precision.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Changed the precision of the `cs/equality-on-floats` query from medium to high. From e6450a17ecc3068e9ec0cc53884cf8f61ccac365 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 24 Apr 2025 11:24:51 +0200 Subject: [PATCH 105/336] Added test cases for individual AWS services, direct modification of global credentials and AWS.Credentials --- .../Security/CWE-798/HardcodedCredentials.js | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js index 9bd7b68bfbaf..215d31a21b03 100644 --- a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js +++ b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js @@ -415,3 +415,109 @@ app.use(jwt({ secret: secretKey })); // $ Sink })(); + + +(function(usr, passwd) { + const AWS = require("aws-sdk"); + + const ec2 = new AWS.EC2({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const lambda = new AWS.Lambda({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const ecs = new AWS.ECS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const eks = new AWS.EKS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const batch = new AWS.Batch({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const elasticbeanstalk = new AWS.ElasticBeanstalk({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const lightsail = new AWS.Lightsail({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const apprunner = new AWS.AppRunner({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const s3 = new AWS.S3({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const efs = new AWS.EFS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const glacier = new AWS.Glacier({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const s3control = new AWS.S3Control({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const storagegateway = new AWS.StorageGateway({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const backup = new AWS.Backup({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const dynamodb = new AWS.DynamoDB({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const dynamodbstreams = new AWS.DynamoDBStreams({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const rds = new AWS.RDS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const redshift = new AWS.Redshift({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const elasticache = new AWS.ElastiCache({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const neptune = new AWS.Neptune({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const qldb = new AWS.QLDB({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const athena = new AWS.Athena({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const route53 = new AWS.Route53({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const cloudfront = new AWS.CloudFront({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const apigateway = new AWS.APIGateway({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const apigatewayv2 = new AWS.ApiGatewayV2({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const directconnect = new AWS.DirectConnect({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const globalaccelerator = new AWS.GlobalAccelerator({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const cloudwatch = new AWS.CloudWatch({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const cloudformation = new AWS.CloudFormation({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const cloudtrail = new AWS.CloudTrail({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const config = new AWS.Config({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const organizations = new AWS.Organizations({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const servicecatalog = new AWS.ServiceCatalog({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const ssm = new AWS.SSM({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const resourcegroups = new AWS.ResourceGroups({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const iam = new AWS.IAM({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const cognitoidentity = new AWS.CognitoIdentity({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const guardduty = new AWS.GuardDuty({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const inspector = new AWS.Inspector({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const kms = new AWS.KMS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const secretsmanager = new AWS.SecretsManager({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const securityhub = new AWS.SecurityHub({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const sts = new AWS.STS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const waf = new AWS.WAF({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const wafregional = new AWS.WAFRegional({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const sagemaker = new AWS.SageMaker({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const rekognition = new AWS.Rekognition({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const comprehend = new AWS.Comprehend({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const textract = new AWS.Textract({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const translate = new AWS.Translate({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const polly = new AWS.Polly({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const lexmodelbuildingservice = new AWS.LexModelBuildingService({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const machinelearning = new AWS.MachineLearning({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const personalize = new AWS.Personalize({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const emr = new AWS.EMR({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const kinesis = new AWS.Kinesis({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const kinesisanalytics = new AWS.KinesisAnalytics({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const kinesisvideo = new AWS.KinesisVideo({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const quicksight = new AWS.QuickSight({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const datapipeline = new AWS.DataPipeline({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const glue = new AWS.Glue({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const lakeformation = new AWS.LakeFormation({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const sns = new AWS.SNS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const sqs = new AWS.SQS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const ses = new AWS.SES({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const pinpoint = new AWS.Pinpoint({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const chime = new AWS.Chime({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const connect = new AWS.Connect({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const amplify = new AWS.Amplify({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const appsync = new AWS.AppSync({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const devicefarm = new AWS.DeviceFarm({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const iotanalytics = new AWS.IoTAnalytics({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const iotevents = new AWS.IoTEvents({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const iot1clickdevicesservice = new AWS.IoT1ClickDevicesService({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const iotsitewise = new AWS.IoTSiteWise({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const mediaconvert = new AWS.MediaConvert({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const medialive = new AWS.MediaLive({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const mediapackage = new AWS.MediaPackage({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const mediastore = new AWS.MediaStore({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const elastictranscoder = new AWS.ElasticTranscoder({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const eventbridge = new AWS.EventBridge({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const mq = new AWS.MQ({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const swf = new AWS.SWF({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const stepfunctions = new AWS.StepFunctions({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING:Alert + + AWS.config.accessKeyId = "SOMEACCESSKEY"; // $ MISSING: Alert + AWS.config.secretAccessKey = "hgfedcba"; // $ MISSING: Alert + + const creds = new AWS.Credentials( + "SOMEACCESSKEY", // $ MISSING: Alert + "hgfedcba" // $ MISSING: Alert + ); + AWS.config.setCredentials(creds); + + AWS.config.update({ + accessKeyId: "SOMEACCESSKEY", // $ Alert + secretAccessKey: "hgfedcba" // $ Alert + }); +})(); From 05e4677fd167c1631e1832ffccf243b88df243f1 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 24 Apr 2025 10:58:31 +0200 Subject: [PATCH 106/336] Added ability to detect `new AWS.ServiceName` cases with hardcoded credentials --- .../lib/semmle/javascript/frameworks/AWS.qll | 41 +++ .../CWE-798/HardcodedCredentials.expected | 262 ++++++++++++++++++ .../Security/CWE-798/HardcodedCredentials.js | 170 ++++++------ 3 files changed, 388 insertions(+), 85 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll index 1eac5888b955..011311c7af18 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll @@ -5,6 +5,42 @@ import javascript module AWS { + /** + * Gets the name of a supported AWS service. + */ + private string getAWSServiceName() { + result = + [ + "EC2", "Lambda", "ECS", "EKS", "Batch", "ElasticBeanstalk", "Lightsail", "AppRunner", "S3", + "EFS", "Glacier", "S3Control", "StorageGateway", "Backup", "DynamoDB", "DynamoDBStreams", + "RDS", "Redshift", "ElastiCache", "Neptune", "QLDB", "Athena", "Route53", "CloudFront", + "APIGateway", "ApiGatewayV2", "DirectConnect", "GlobalAccelerator", "CloudWatch", + "CloudFormation", "CloudTrail", "Config", "Organizations", "ServiceCatalog", "SSM", + "ResourceGroups", "IAM", "CognitoIdentity", "CognitoIdentityServiceProvider", "GuardDuty", + "Inspector", "KMS", "SecretsManager", "SecurityHub", "STS", "WAF", "WAFRegional", + "SageMaker", "Rekognition", "Comprehend", "Textract", "Translate", "Polly", + "LexModelBuildingService", "MachineLearning", "Personalize", "EMR", "Kinesis", + "KinesisAnalytics", "KinesisVideo", "QuickSight", "DataPipeline", "Glue", "LakeFormation", + "SNS", "SQS", "SES", "Pinpoint", "Chime", "Connect", "Amplify", "AppSync", "DeviceFarm", + "IoTAnalytics", "IoTEvents", "IoT1ClickDevicesService", "IoTSiteWise", "MediaConvert", + "MediaLive", "MediaPackage", "MediaStore", "ElasticTranscoder", "EventBridge", "MQ", "SWF", + "StepFunctions" + ] + } + + /** + * Gets a node representing an import of the AWS SDK. + */ + private API::Node getAWSImport() { result = API::moduleImport("aws-sdk") } + + /** + * Gets a data flow node representing an instantiation of an AWS service. + */ + private DataFlow::Node getServiceInstantation() { + result = + getAWSImport().getMember(getAWSServiceName()).getAnInstantiation().getReturn().asSource() + } + /** * Holds if the `i`th argument of `invk` is an object hash for `AWS.Config`. */ @@ -36,6 +72,11 @@ module AWS { exists(string prop, DataFlow::InvokeNode invk, int i | takesConfigurationObject(invk, i) and this = invk.getOptionArgument(i, prop) + or + // `new AWS.ServiceName({ accessKeyId: , secretAccessKey: })` + invk = getServiceInstantation() and + i = 0 and + this = invk.getOptionArgument(i, prop) | prop = "accessKeyId" and kind = "user name" or diff --git a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected index d2da5f21b3cd..566023bb07b3 100644 --- a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected +++ b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected @@ -75,6 +75,94 @@ | HardcodedCredentials.js:375:21:375:43 | "myHard ... ateKey" | HardcodedCredentials.js:375:21:375:43 | "myHard ... ateKey" | HardcodedCredentials.js:385:31:385:39 | secretKey | The hard-coded value "myHardCodedPrivateKey" is used as $@. | HardcodedCredentials.js:385:31:385:39 | secretKey | jwt key | | HardcodedCredentials.js:396:21:396:43 | "myHard ... ateKey" | HardcodedCredentials.js:396:21:396:43 | "myHard ... ateKey" | HardcodedCredentials.js:399:17:399:25 | secretKey | The hard-coded value "myHardCodedPrivateKey" is used as $@. | HardcodedCredentials.js:399:17:399:25 | secretKey | jwt key | | HardcodedCredentials.js:414:21:414:43 | "myHard ... ateKey" | HardcodedCredentials.js:414:21:414:43 | "myHard ... ateKey" | HardcodedCredentials.js:416:27:416:35 | secretKey | The hard-coded value "myHardCodedPrivateKey" is used as $@. | HardcodedCredentials.js:416:27:416:35 | secretKey | jwt key | +| HardcodedCredentials.js:423:43:423:53 | "AccessID1" | HardcodedCredentials.js:423:43:423:53 | "AccessID1" | HardcodedCredentials.js:423:43:423:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:423:43:423:53 | "AccessID1" | user name | +| HardcodedCredentials.js:424:49:424:59 | "AccessID1" | HardcodedCredentials.js:424:49:424:59 | "AccessID1" | HardcodedCredentials.js:424:49:424:59 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:424:49:424:59 | "AccessID1" | user name | +| HardcodedCredentials.js:425:43:425:53 | "AccessID1" | HardcodedCredentials.js:425:43:425:53 | "AccessID1" | HardcodedCredentials.js:425:43:425:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:425:43:425:53 | "AccessID1" | user name | +| HardcodedCredentials.js:426:43:426:53 | "AccessID1" | HardcodedCredentials.js:426:43:426:53 | "AccessID1" | HardcodedCredentials.js:426:43:426:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:426:43:426:53 | "AccessID1" | user name | +| HardcodedCredentials.js:427:47:427:57 | "AccessID1" | HardcodedCredentials.js:427:47:427:57 | "AccessID1" | HardcodedCredentials.js:427:47:427:57 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:427:47:427:57 | "AccessID1" | user name | +| HardcodedCredentials.js:428:69:428:79 | "AccessID1" | HardcodedCredentials.js:428:69:428:79 | "AccessID1" | HardcodedCredentials.js:428:69:428:79 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:428:69:428:79 | "AccessID1" | user name | +| HardcodedCredentials.js:429:55:429:65 | "AccessID1" | HardcodedCredentials.js:429:55:429:65 | "AccessID1" | HardcodedCredentials.js:429:55:429:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:429:55:429:65 | "AccessID1" | user name | +| HardcodedCredentials.js:430:55:430:65 | "AccessID1" | HardcodedCredentials.js:430:55:430:65 | "AccessID1" | HardcodedCredentials.js:430:55:430:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:430:55:430:65 | "AccessID1" | user name | +| HardcodedCredentials.js:431:41:431:51 | "AccessID1" | HardcodedCredentials.js:431:41:431:51 | "AccessID1" | HardcodedCredentials.js:431:41:431:51 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:431:41:431:51 | "AccessID1" | user name | +| HardcodedCredentials.js:432:43:432:53 | "AccessID1" | HardcodedCredentials.js:432:43:432:53 | "AccessID1" | HardcodedCredentials.js:432:43:432:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:432:43:432:53 | "AccessID1" | user name | +| HardcodedCredentials.js:433:51:433:61 | "AccessID1" | HardcodedCredentials.js:433:51:433:61 | "AccessID1" | HardcodedCredentials.js:433:51:433:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:433:51:433:61 | "AccessID1" | user name | +| HardcodedCredentials.js:434:55:434:65 | "AccessID1" | HardcodedCredentials.js:434:55:434:65 | "AccessID1" | HardcodedCredentials.js:434:55:434:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:434:55:434:65 | "AccessID1" | user name | +| HardcodedCredentials.js:435:65:435:75 | "AccessID1" | HardcodedCredentials.js:435:65:435:75 | "AccessID1" | HardcodedCredentials.js:435:65:435:75 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:435:65:435:75 | "AccessID1" | user name | +| HardcodedCredentials.js:436:49:436:59 | "AccessID1" | HardcodedCredentials.js:436:49:436:59 | "AccessID1" | HardcodedCredentials.js:436:49:436:59 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:436:49:436:59 | "AccessID1" | user name | +| HardcodedCredentials.js:437:53:437:63 | "AccessID1" | HardcodedCredentials.js:437:53:437:63 | "AccessID1" | HardcodedCredentials.js:437:53:437:63 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:437:53:437:63 | "AccessID1" | user name | +| HardcodedCredentials.js:438:67:438:77 | "AccessID1" | HardcodedCredentials.js:438:67:438:77 | "AccessID1" | HardcodedCredentials.js:438:67:438:77 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:438:67:438:77 | "AccessID1" | user name | +| HardcodedCredentials.js:439:43:439:53 | "AccessID1" | HardcodedCredentials.js:439:43:439:53 | "AccessID1" | HardcodedCredentials.js:439:43:439:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:439:43:439:53 | "AccessID1" | user name | +| HardcodedCredentials.js:440:53:440:63 | "AccessID1" | HardcodedCredentials.js:440:53:440:63 | "AccessID1" | HardcodedCredentials.js:440:53:440:63 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:440:53:440:63 | "AccessID1" | user name | +| HardcodedCredentials.js:441:59:441:69 | "AccessID1" | HardcodedCredentials.js:441:59:441:69 | "AccessID1" | HardcodedCredentials.js:441:59:441:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:441:59:441:69 | "AccessID1" | user name | +| HardcodedCredentials.js:442:51:442:61 | "AccessID1" | HardcodedCredentials.js:442:51:442:61 | "AccessID1" | HardcodedCredentials.js:442:51:442:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:442:51:442:61 | "AccessID1" | user name | +| HardcodedCredentials.js:443:45:443:55 | "AccessID1" | HardcodedCredentials.js:443:45:443:55 | "AccessID1" | HardcodedCredentials.js:443:45:443:55 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:443:45:443:55 | "AccessID1" | user name | +| HardcodedCredentials.js:444:49:444:59 | "AccessID1" | HardcodedCredentials.js:444:49:444:59 | "AccessID1" | HardcodedCredentials.js:444:49:444:59 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:444:49:444:59 | "AccessID1" | user name | +| HardcodedCredentials.js:445:51:445:61 | "AccessID1" | HardcodedCredentials.js:445:51:445:61 | "AccessID1" | HardcodedCredentials.js:445:51:445:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:445:51:445:61 | "AccessID1" | user name | +| HardcodedCredentials.js:446:57:446:67 | "AccessID1" | HardcodedCredentials.js:446:57:446:67 | "AccessID1" | HardcodedCredentials.js:446:57:446:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:446:57:446:67 | "AccessID1" | user name | +| HardcodedCredentials.js:447:57:447:67 | "AccessID1" | HardcodedCredentials.js:447:57:447:67 | "AccessID1" | HardcodedCredentials.js:447:57:447:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:447:57:447:67 | "AccessID1" | user name | +| HardcodedCredentials.js:448:61:448:71 | "AccessID1" | HardcodedCredentials.js:448:61:448:71 | "AccessID1" | HardcodedCredentials.js:448:61:448:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:448:61:448:71 | "AccessID1" | user name | +| HardcodedCredentials.js:449:63:449:73 | "AccessID1" | HardcodedCredentials.js:449:63:449:73 | "AccessID1" | HardcodedCredentials.js:449:63:449:73 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:449:63:449:73 | "AccessID1" | user name | +| HardcodedCredentials.js:450:71:450:81 | "AccessID1" | HardcodedCredentials.js:450:71:450:81 | "AccessID1" | HardcodedCredentials.js:450:71:450:81 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:450:71:450:81 | "AccessID1" | user name | +| HardcodedCredentials.js:451:57:451:67 | "AccessID1" | HardcodedCredentials.js:451:57:451:67 | "AccessID1" | HardcodedCredentials.js:451:57:451:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:451:57:451:67 | "AccessID1" | user name | +| HardcodedCredentials.js:452:65:452:75 | "AccessID1" | HardcodedCredentials.js:452:65:452:75 | "AccessID1" | HardcodedCredentials.js:452:65:452:75 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:452:65:452:75 | "AccessID1" | user name | +| HardcodedCredentials.js:453:57:453:67 | "AccessID1" | HardcodedCredentials.js:453:57:453:67 | "AccessID1" | HardcodedCredentials.js:453:57:453:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:453:57:453:67 | "AccessID1" | user name | +| HardcodedCredentials.js:454:49:454:59 | "AccessID1" | HardcodedCredentials.js:454:49:454:59 | "AccessID1" | HardcodedCredentials.js:454:49:454:59 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:454:49:454:59 | "AccessID1" | user name | +| HardcodedCredentials.js:455:63:455:73 | "AccessID1" | HardcodedCredentials.js:455:63:455:73 | "AccessID1" | HardcodedCredentials.js:455:63:455:73 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:455:63:455:73 | "AccessID1" | user name | +| HardcodedCredentials.js:456:65:456:75 | "AccessID1" | HardcodedCredentials.js:456:65:456:75 | "AccessID1" | HardcodedCredentials.js:456:65:456:75 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:456:65:456:75 | "AccessID1" | user name | +| HardcodedCredentials.js:457:43:457:53 | "AccessID1" | HardcodedCredentials.js:457:43:457:53 | "AccessID1" | HardcodedCredentials.js:457:43:457:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:457:43:457:53 | "AccessID1" | user name | +| HardcodedCredentials.js:458:65:458:75 | "AccessID1" | HardcodedCredentials.js:458:65:458:75 | "AccessID1" | HardcodedCredentials.js:458:65:458:75 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:458:65:458:75 | "AccessID1" | user name | +| HardcodedCredentials.js:459:43:459:53 | "AccessID1" | HardcodedCredentials.js:459:43:459:53 | "AccessID1" | HardcodedCredentials.js:459:43:459:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:459:43:459:53 | "AccessID1" | user name | +| HardcodedCredentials.js:460:67:460:77 | "AccessID1" | HardcodedCredentials.js:460:67:460:77 | "AccessID1" | HardcodedCredentials.js:460:67:460:77 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:460:67:460:77 | "AccessID1" | user name | +| HardcodedCredentials.js:461:97:461:107 | "AccessID1" | HardcodedCredentials.js:461:97:461:107 | "AccessID1" | HardcodedCredentials.js:461:97:461:107 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:461:97:461:107 | "AccessID1" | user name | +| HardcodedCredentials.js:462:55:462:65 | "AccessID1" | HardcodedCredentials.js:462:55:462:65 | "AccessID1" | HardcodedCredentials.js:462:55:462:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:462:55:462:65 | "AccessID1" | user name | +| HardcodedCredentials.js:463:55:463:65 | "AccessID1" | HardcodedCredentials.js:463:55:463:65 | "AccessID1" | HardcodedCredentials.js:463:55:463:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:463:55:463:65 | "AccessID1" | user name | +| HardcodedCredentials.js:464:43:464:53 | "AccessID1" | HardcodedCredentials.js:464:43:464:53 | "AccessID1" | HardcodedCredentials.js:464:43:464:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:464:43:464:53 | "AccessID1" | user name | +| HardcodedCredentials.js:465:65:465:75 | "AccessID1" | HardcodedCredentials.js:465:65:465:75 | "AccessID1" | HardcodedCredentials.js:465:65:465:75 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:465:65:465:75 | "AccessID1" | user name | +| HardcodedCredentials.js:466:59:466:69 | "AccessID1" | HardcodedCredentials.js:466:59:466:69 | "AccessID1" | HardcodedCredentials.js:466:59:466:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:466:59:466:69 | "AccessID1" | user name | +| HardcodedCredentials.js:467:43:467:53 | "AccessID1" | HardcodedCredentials.js:467:43:467:53 | "AccessID1" | HardcodedCredentials.js:467:43:467:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:467:43:467:53 | "AccessID1" | user name | +| HardcodedCredentials.js:468:43:468:53 | "AccessID1" | HardcodedCredentials.js:468:43:468:53 | "AccessID1" | HardcodedCredentials.js:468:43:468:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:468:43:468:53 | "AccessID1" | user name | +| HardcodedCredentials.js:469:59:469:69 | "AccessID1" | HardcodedCredentials.js:469:59:469:69 | "AccessID1" | HardcodedCredentials.js:469:59:469:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:469:59:469:69 | "AccessID1" | user name | +| HardcodedCredentials.js:470:55:470:65 | "AccessID1" | HardcodedCredentials.js:470:55:470:65 | "AccessID1" | HardcodedCredentials.js:470:55:470:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:470:55:470:65 | "AccessID1" | user name | +| HardcodedCredentials.js:471:59:471:69 | "AccessID1" | HardcodedCredentials.js:471:59:471:69 | "AccessID1" | HardcodedCredentials.js:471:59:471:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:471:59:471:69 | "AccessID1" | user name | +| HardcodedCredentials.js:472:57:472:67 | "AccessID1" | HardcodedCredentials.js:472:57:472:67 | "AccessID1" | HardcodedCredentials.js:472:57:472:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:472:57:472:67 | "AccessID1" | user name | +| HardcodedCredentials.js:473:53:473:63 | "AccessID1" | HardcodedCredentials.js:473:53:473:63 | "AccessID1" | HardcodedCredentials.js:473:53:473:63 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:473:53:473:63 | "AccessID1" | user name | +| HardcodedCredentials.js:474:55:474:65 | "AccessID1" | HardcodedCredentials.js:474:55:474:65 | "AccessID1" | HardcodedCredentials.js:474:55:474:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:474:55:474:65 | "AccessID1" | user name | +| HardcodedCredentials.js:475:47:475:57 | "AccessID1" | HardcodedCredentials.js:475:47:475:57 | "AccessID1" | HardcodedCredentials.js:475:47:475:57 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:475:47:475:57 | "AccessID1" | user name | +| HardcodedCredentials.js:476:83:476:93 | "AccessID1" | HardcodedCredentials.js:476:83:476:93 | "AccessID1" | HardcodedCredentials.js:476:83:476:93 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:476:83:476:93 | "AccessID1" | user name | +| HardcodedCredentials.js:477:67:477:77 | "AccessID1" | HardcodedCredentials.js:477:67:477:77 | "AccessID1" | HardcodedCredentials.js:477:67:477:77 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:477:67:477:77 | "AccessID1" | user name | +| HardcodedCredentials.js:478:59:478:69 | "AccessID1" | HardcodedCredentials.js:478:59:478:69 | "AccessID1" | HardcodedCredentials.js:478:59:478:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:478:59:478:69 | "AccessID1" | user name | +| HardcodedCredentials.js:479:43:479:53 | "AccessID1" | HardcodedCredentials.js:479:43:479:53 | "AccessID1" | HardcodedCredentials.js:479:43:479:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:479:43:479:53 | "AccessID1" | user name | +| HardcodedCredentials.js:480:51:480:61 | "AccessID1" | HardcodedCredentials.js:480:51:480:61 | "AccessID1" | HardcodedCredentials.js:480:51:480:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:480:51:480:61 | "AccessID1" | user name | +| HardcodedCredentials.js:481:69:481:79 | "AccessID1" | HardcodedCredentials.js:481:69:481:79 | "AccessID1" | HardcodedCredentials.js:481:69:481:79 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:481:69:481:79 | "AccessID1" | user name | +| HardcodedCredentials.js:482:61:482:71 | "AccessID1" | HardcodedCredentials.js:482:61:482:71 | "AccessID1" | HardcodedCredentials.js:482:61:482:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:482:61:482:71 | "AccessID1" | user name | +| HardcodedCredentials.js:483:57:483:67 | "AccessID1" | HardcodedCredentials.js:483:57:483:67 | "AccessID1" | HardcodedCredentials.js:483:57:483:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:483:57:483:67 | "AccessID1" | user name | +| HardcodedCredentials.js:484:61:484:71 | "AccessID1" | HardcodedCredentials.js:484:61:484:71 | "AccessID1" | HardcodedCredentials.js:484:61:484:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:484:61:484:71 | "AccessID1" | user name | +| HardcodedCredentials.js:485:45:485:55 | "AccessID1" | HardcodedCredentials.js:485:45:485:55 | "AccessID1" | HardcodedCredentials.js:485:45:485:55 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:485:45:485:55 | "AccessID1" | user name | +| HardcodedCredentials.js:486:63:486:73 | "AccessID1" | HardcodedCredentials.js:486:63:486:73 | "AccessID1" | HardcodedCredentials.js:486:63:486:73 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:486:63:486:73 | "AccessID1" | user name | +| HardcodedCredentials.js:487:43:487:53 | "AccessID1" | HardcodedCredentials.js:487:43:487:53 | "AccessID1" | HardcodedCredentials.js:487:43:487:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:487:43:487:53 | "AccessID1" | user name | +| HardcodedCredentials.js:488:43:488:53 | "AccessID1" | HardcodedCredentials.js:488:43:488:53 | "AccessID1" | HardcodedCredentials.js:488:43:488:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:488:43:488:53 | "AccessID1" | user name | +| HardcodedCredentials.js:489:43:489:53 | "AccessID1" | HardcodedCredentials.js:489:43:489:53 | "AccessID1" | HardcodedCredentials.js:489:43:489:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:489:43:489:53 | "AccessID1" | user name | +| HardcodedCredentials.js:490:53:490:63 | "AccessID1" | HardcodedCredentials.js:490:53:490:63 | "AccessID1" | HardcodedCredentials.js:490:53:490:63 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:490:53:490:63 | "AccessID1" | user name | +| HardcodedCredentials.js:491:47:491:57 | "AccessID1" | HardcodedCredentials.js:491:47:491:57 | "AccessID1" | HardcodedCredentials.js:491:47:491:57 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:491:47:491:57 | "AccessID1" | user name | +| HardcodedCredentials.js:492:51:492:61 | "AccessID1" | HardcodedCredentials.js:492:51:492:61 | "AccessID1" | HardcodedCredentials.js:492:51:492:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:492:51:492:61 | "AccessID1" | user name | +| HardcodedCredentials.js:493:51:493:61 | "AccessID1" | HardcodedCredentials.js:493:51:493:61 | "AccessID1" | HardcodedCredentials.js:493:51:493:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:493:51:493:61 | "AccessID1" | user name | +| HardcodedCredentials.js:494:51:494:61 | "AccessID1" | HardcodedCredentials.js:494:51:494:61 | "AccessID1" | HardcodedCredentials.js:494:51:494:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:494:51:494:61 | "AccessID1" | user name | +| HardcodedCredentials.js:495:57:495:67 | "AccessID1" | HardcodedCredentials.js:495:57:495:67 | "AccessID1" | HardcodedCredentials.js:495:57:495:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:495:57:495:67 | "AccessID1" | user name | +| HardcodedCredentials.js:496:61:496:71 | "AccessID1" | HardcodedCredentials.js:496:61:496:71 | "AccessID1" | HardcodedCredentials.js:496:61:496:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:496:61:496:71 | "AccessID1" | user name | +| HardcodedCredentials.js:497:55:497:65 | "AccessID1" | HardcodedCredentials.js:497:55:497:65 | "AccessID1" | HardcodedCredentials.js:497:55:497:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:497:55:497:65 | "AccessID1" | user name | +| HardcodedCredentials.js:498:83:498:93 | "AccessID1" | HardcodedCredentials.js:498:83:498:93 | "AccessID1" | HardcodedCredentials.js:498:83:498:93 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:498:83:498:93 | "AccessID1" | user name | +| HardcodedCredentials.js:499:59:499:69 | "AccessID1" | HardcodedCredentials.js:499:59:499:69 | "AccessID1" | HardcodedCredentials.js:499:59:499:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:499:59:499:69 | "AccessID1" | user name | +| HardcodedCredentials.js:500:61:500:71 | "AccessID1" | HardcodedCredentials.js:500:61:500:71 | "AccessID1" | HardcodedCredentials.js:500:61:500:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:500:61:500:71 | "AccessID1" | user name | +| HardcodedCredentials.js:501:55:501:65 | "AccessID1" | HardcodedCredentials.js:501:55:501:65 | "AccessID1" | HardcodedCredentials.js:501:55:501:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:501:55:501:65 | "AccessID1" | user name | +| HardcodedCredentials.js:502:61:502:71 | "AccessID1" | HardcodedCredentials.js:502:61:502:71 | "AccessID1" | HardcodedCredentials.js:502:61:502:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:502:61:502:71 | "AccessID1" | user name | +| HardcodedCredentials.js:503:57:503:67 | "AccessID1" | HardcodedCredentials.js:503:57:503:67 | "AccessID1" | HardcodedCredentials.js:503:57:503:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:503:57:503:67 | "AccessID1" | user name | +| HardcodedCredentials.js:504:71:504:81 | "AccessID1" | HardcodedCredentials.js:504:71:504:81 | "AccessID1" | HardcodedCredentials.js:504:71:504:81 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:504:71:504:81 | "AccessID1" | user name | +| HardcodedCredentials.js:505:59:505:69 | "AccessID1" | HardcodedCredentials.js:505:59:505:69 | "AccessID1" | HardcodedCredentials.js:505:59:505:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:505:59:505:69 | "AccessID1" | user name | +| HardcodedCredentials.js:506:41:506:51 | "AccessID1" | HardcodedCredentials.js:506:41:506:51 | "AccessID1" | HardcodedCredentials.js:506:41:506:51 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:506:41:506:51 | "AccessID1" | user name | +| HardcodedCredentials.js:507:43:507:53 | "AccessID1" | HardcodedCredentials.js:507:43:507:53 | "AccessID1" | HardcodedCredentials.js:507:43:507:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:507:43:507:53 | "AccessID1" | user name | +| HardcodedCredentials.js:508:63:508:73 | "AccessID1" | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | user name | +| HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | The hard-coded value "SOMEACCESSKEY" is used as $@. | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | user name | +| HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | password | | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | The hard-coded value "dbuser" is used as $@. | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | user name | | __tests__/HardcodedCredentialsDemo.js:8:19:8:28 | 'hgfedcba' | __tests__/HardcodedCredentialsDemo.js:8:19:8:28 | 'hgfedcba' | __tests__/HardcodedCredentialsDemo.js:8:19:8:28 | 'hgfedcba' | The hard-coded value "hgfedcba" is used as $@. | __tests__/HardcodedCredentialsDemo.js:8:19:8:28 | 'hgfedcba' | password | edges @@ -297,6 +385,180 @@ nodes | HardcodedCredentials.js:414:9:414:43 | secretKey | semmle.label | secretKey | | HardcodedCredentials.js:414:21:414:43 | "myHard ... ateKey" | semmle.label | "myHard ... ateKey" | | HardcodedCredentials.js:416:27:416:35 | secretKey | semmle.label | secretKey | +| HardcodedCredentials.js:423:43:423:53 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:423:73:423:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:424:49:424:59 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:424:79:424:95 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:425:43:425:53 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:425:73:425:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:426:43:426:53 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:426:73:426:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:427:47:427:57 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:427:77:427:93 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:428:69:428:79 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:428:99:428:115 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:429:55:429:65 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:429:85:429:101 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:430:55:430:65 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:430:85:430:101 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:431:41:431:51 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:431:71:431:87 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:432:43:432:53 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:432:73:432:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:433:51:433:61 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:433:81:433:97 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:434:55:434:65 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:434:85:434:101 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:435:65:435:75 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:435:95:435:111 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:436:49:436:59 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:436:79:436:95 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:437:53:437:63 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:437:83:437:99 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:438:67:438:77 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:438:97:438:113 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:439:43:439:53 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:439:73:439:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:440:53:440:63 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:440:83:440:99 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:441:59:441:69 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:441:89:441:105 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:442:51:442:61 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:442:81:442:97 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:443:45:443:55 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:443:75:443:91 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:444:49:444:59 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:444:79:444:95 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:445:51:445:61 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:445:81:445:97 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:446:57:446:67 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:446:87:446:103 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:447:57:447:67 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:447:87:447:103 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:448:61:448:71 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:448:91:448:107 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:449:63:449:73 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:449:93:449:109 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:450:71:450:81 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:450:101:450:117 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:451:57:451:67 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:451:87:451:103 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:452:65:452:75 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:452:95:452:111 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:453:57:453:67 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:453:87:453:103 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:454:49:454:59 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:454:79:454:95 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:455:63:455:73 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:455:93:455:109 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:456:65:456:75 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:456:95:456:111 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:457:43:457:53 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:457:73:457:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:458:65:458:75 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:458:95:458:111 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:459:43:459:53 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:459:73:459:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:460:67:460:77 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:460:97:460:113 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:461:97:461:107 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:461:127:461:143 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:462:55:462:65 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:462:85:462:101 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:463:55:463:65 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:463:85:463:101 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:464:43:464:53 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:464:73:464:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:465:65:465:75 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:465:95:465:111 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:466:59:466:69 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:466:89:466:105 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:467:43:467:53 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:467:73:467:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:468:43:468:53 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:468:73:468:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:469:59:469:69 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:469:89:469:105 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:470:55:470:65 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:470:85:470:101 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:471:59:471:69 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:471:89:471:105 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:472:57:472:67 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:472:87:472:103 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:473:53:473:63 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:473:83:473:99 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:474:55:474:65 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:474:85:474:101 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:475:47:475:57 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:475:77:475:93 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:476:83:476:93 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:476:113:476:129 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:477:67:477:77 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:477:97:477:113 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:478:59:478:69 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:478:89:478:105 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:479:43:479:53 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:479:73:479:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:480:51:480:61 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:480:81:480:97 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:481:69:481:79 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:481:99:481:115 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:482:61:482:71 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:482:91:482:107 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:483:57:483:67 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:483:87:483:103 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:484:61:484:71 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:484:91:484:107 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:485:45:485:55 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:485:75:485:91 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:486:63:486:73 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:486:93:486:109 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:487:43:487:53 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:487:73:487:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:488:43:488:53 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:488:73:488:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:489:43:489:53 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:489:73:489:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:490:53:490:63 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:490:83:490:99 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:491:47:491:57 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:491:77:491:93 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:492:51:492:61 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:492:81:492:97 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:493:51:493:61 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:493:81:493:97 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:494:51:494:61 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:494:81:494:97 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:495:57:495:67 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:495:87:495:103 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:496:61:496:71 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:496:91:496:107 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:497:55:497:65 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:497:85:497:101 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:498:83:498:93 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:498:113:498:129 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:499:59:499:69 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:499:89:499:105 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:500:61:500:71 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:500:91:500:107 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:501:55:501:65 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:501:85:501:101 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:502:61:502:71 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:502:91:502:107 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:503:57:503:67 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:503:87:503:103 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:504:71:504:81 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:504:101:504:117 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:505:59:505:69 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:505:89:505:105 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:506:41:506:51 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:506:71:506:87 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:507:43:507:53 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:507:73:507:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:508:63:508:73 | "AccessID1" | semmle.label | "AccessID1" | +| HardcodedCredentials.js:508:93:508:109 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | semmle.label | "SOMEACCESSKEY" | +| HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | semmle.label | "hgfedcba" | | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | semmle.label | 'dbuser' | | __tests__/HardcodedCredentialsDemo.js:8:19:8:28 | 'hgfedcba' | semmle.label | 'hgfedcba' | subpaths diff --git a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js index 215d31a21b03..8141b4d8c584 100644 --- a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js +++ b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js @@ -420,92 +420,92 @@ (function(usr, passwd) { const AWS = require("aws-sdk"); - const ec2 = new AWS.EC2({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const lambda = new AWS.Lambda({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const ecs = new AWS.ECS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const eks = new AWS.EKS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const batch = new AWS.Batch({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const elasticbeanstalk = new AWS.ElasticBeanstalk({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const lightsail = new AWS.Lightsail({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const apprunner = new AWS.AppRunner({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const s3 = new AWS.S3({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const efs = new AWS.EFS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const glacier = new AWS.Glacier({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const s3control = new AWS.S3Control({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const storagegateway = new AWS.StorageGateway({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const backup = new AWS.Backup({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const dynamodb = new AWS.DynamoDB({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const dynamodbstreams = new AWS.DynamoDBStreams({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const rds = new AWS.RDS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const redshift = new AWS.Redshift({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const elasticache = new AWS.ElastiCache({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const neptune = new AWS.Neptune({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const qldb = new AWS.QLDB({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const athena = new AWS.Athena({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const route53 = new AWS.Route53({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const cloudfront = new AWS.CloudFront({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const apigateway = new AWS.APIGateway({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const apigatewayv2 = new AWS.ApiGatewayV2({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const directconnect = new AWS.DirectConnect({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const globalaccelerator = new AWS.GlobalAccelerator({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const cloudwatch = new AWS.CloudWatch({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const cloudformation = new AWS.CloudFormation({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const cloudtrail = new AWS.CloudTrail({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert + const ec2 = new AWS.EC2({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const lambda = new AWS.Lambda({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const ecs = new AWS.ECS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const eks = new AWS.EKS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const batch = new AWS.Batch({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const elasticbeanstalk = new AWS.ElasticBeanstalk({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const lightsail = new AWS.Lightsail({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const apprunner = new AWS.AppRunner({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const s3 = new AWS.S3({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const efs = new AWS.EFS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const glacier = new AWS.Glacier({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const s3control = new AWS.S3Control({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const storagegateway = new AWS.StorageGateway({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const backup = new AWS.Backup({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const dynamodb = new AWS.DynamoDB({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const dynamodbstreams = new AWS.DynamoDBStreams({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const rds = new AWS.RDS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const redshift = new AWS.Redshift({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const elasticache = new AWS.ElastiCache({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const neptune = new AWS.Neptune({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const qldb = new AWS.QLDB({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const athena = new AWS.Athena({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const route53 = new AWS.Route53({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const cloudfront = new AWS.CloudFront({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const apigateway = new AWS.APIGateway({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const apigatewayv2 = new AWS.ApiGatewayV2({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const directconnect = new AWS.DirectConnect({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const globalaccelerator = new AWS.GlobalAccelerator({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const cloudwatch = new AWS.CloudWatch({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const cloudformation = new AWS.CloudFormation({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const cloudtrail = new AWS.CloudTrail({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert const config = new AWS.Config({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert - const organizations = new AWS.Organizations({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const servicecatalog = new AWS.ServiceCatalog({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const ssm = new AWS.SSM({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const resourcegroups = new AWS.ResourceGroups({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const iam = new AWS.IAM({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const cognitoidentity = new AWS.CognitoIdentity({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const guardduty = new AWS.GuardDuty({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const inspector = new AWS.Inspector({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const kms = new AWS.KMS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const secretsmanager = new AWS.SecretsManager({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const securityhub = new AWS.SecurityHub({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const sts = new AWS.STS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const waf = new AWS.WAF({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const wafregional = new AWS.WAFRegional({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const sagemaker = new AWS.SageMaker({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const rekognition = new AWS.Rekognition({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const comprehend = new AWS.Comprehend({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const textract = new AWS.Textract({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const translate = new AWS.Translate({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const polly = new AWS.Polly({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const lexmodelbuildingservice = new AWS.LexModelBuildingService({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const machinelearning = new AWS.MachineLearning({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const personalize = new AWS.Personalize({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const emr = new AWS.EMR({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const kinesis = new AWS.Kinesis({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const kinesisanalytics = new AWS.KinesisAnalytics({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const kinesisvideo = new AWS.KinesisVideo({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const quicksight = new AWS.QuickSight({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const datapipeline = new AWS.DataPipeline({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const glue = new AWS.Glue({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const lakeformation = new AWS.LakeFormation({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const sns = new AWS.SNS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const sqs = new AWS.SQS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const ses = new AWS.SES({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const pinpoint = new AWS.Pinpoint({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const chime = new AWS.Chime({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const connect = new AWS.Connect({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const amplify = new AWS.Amplify({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const appsync = new AWS.AppSync({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const devicefarm = new AWS.DeviceFarm({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const iotanalytics = new AWS.IoTAnalytics({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const iotevents = new AWS.IoTEvents({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const iot1clickdevicesservice = new AWS.IoT1ClickDevicesService({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const iotsitewise = new AWS.IoTSiteWise({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const mediaconvert = new AWS.MediaConvert({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const medialive = new AWS.MediaLive({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const mediapackage = new AWS.MediaPackage({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const mediastore = new AWS.MediaStore({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const elastictranscoder = new AWS.ElasticTranscoder({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const eventbridge = new AWS.EventBridge({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const mq = new AWS.MQ({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const swf = new AWS.SWF({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING: Alert - const stepfunctions = new AWS.StepFunctions({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ MISSING:Alert + const organizations = new AWS.Organizations({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const servicecatalog = new AWS.ServiceCatalog({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const ssm = new AWS.SSM({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const resourcegroups = new AWS.ResourceGroups({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const iam = new AWS.IAM({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const cognitoidentity = new AWS.CognitoIdentity({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const guardduty = new AWS.GuardDuty({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const inspector = new AWS.Inspector({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const kms = new AWS.KMS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const secretsmanager = new AWS.SecretsManager({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const securityhub = new AWS.SecurityHub({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const sts = new AWS.STS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const waf = new AWS.WAF({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const wafregional = new AWS.WAFRegional({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const sagemaker = new AWS.SageMaker({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const rekognition = new AWS.Rekognition({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const comprehend = new AWS.Comprehend({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const textract = new AWS.Textract({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const translate = new AWS.Translate({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const polly = new AWS.Polly({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const lexmodelbuildingservice = new AWS.LexModelBuildingService({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const machinelearning = new AWS.MachineLearning({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const personalize = new AWS.Personalize({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const emr = new AWS.EMR({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const kinesis = new AWS.Kinesis({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const kinesisanalytics = new AWS.KinesisAnalytics({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const kinesisvideo = new AWS.KinesisVideo({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const quicksight = new AWS.QuickSight({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const datapipeline = new AWS.DataPipeline({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const glue = new AWS.Glue({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const lakeformation = new AWS.LakeFormation({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const sns = new AWS.SNS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const sqs = new AWS.SQS({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const ses = new AWS.SES({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const pinpoint = new AWS.Pinpoint({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const chime = new AWS.Chime({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const connect = new AWS.Connect({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const amplify = new AWS.Amplify({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const appsync = new AWS.AppSync({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const devicefarm = new AWS.DeviceFarm({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const iotanalytics = new AWS.IoTAnalytics({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const iotevents = new AWS.IoTEvents({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const iot1clickdevicesservice = new AWS.IoT1ClickDevicesService({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const iotsitewise = new AWS.IoTSiteWise({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const mediaconvert = new AWS.MediaConvert({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const medialive = new AWS.MediaLive({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const mediapackage = new AWS.MediaPackage({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const mediastore = new AWS.MediaStore({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const elastictranscoder = new AWS.ElasticTranscoder({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const eventbridge = new AWS.EventBridge({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const mq = new AWS.MQ({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const swf = new AWS.SWF({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert + const stepfunctions = new AWS.StepFunctions({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert AWS.config.accessKeyId = "SOMEACCESSKEY"; // $ MISSING: Alert AWS.config.secretAccessKey = "hgfedcba"; // $ MISSING: Alert From f69037c176c3225c5e70c2dc4a56addf1158b070 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 24 Apr 2025 11:01:35 +0200 Subject: [PATCH 107/336] Added ability to detect direct write to global `AWS.config` --- .../lib/semmle/javascript/frameworks/AWS.qll | 27 +++++++++++++++++++ .../CWE-798/HardcodedCredentials.expected | 4 +++ .../Security/CWE-798/HardcodedCredentials.js | 4 +-- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll index 011311c7af18..e07a37df6ff0 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll @@ -41,6 +41,19 @@ module AWS { getAWSImport().getMember(getAWSServiceName()).getAnInstantiation().getReturn().asSource() } + /** + * Gets a node representing the AWS global config object. + */ + private API::Node getAWSConfig() { result = getAWSImport().getMember("config") } + + /** + * Gets a property write to the AWS config object. + * This captures assignments to AWS.config properties. + */ + private DataFlow::PropWrite configAssigment() { + result = getAWSConfig().asSource().getAPropertyWrite() + } + /** * Holds if the `i`th argument of `invk` is an object hash for `AWS.Config`. */ @@ -82,6 +95,20 @@ module AWS { or prop = "secretAccessKey" and kind = "password" ) + or + // `AWS.config.accessKeyId = ` or `AWS.config.secretAccessKey = ` + exists(string prop, DataFlow::PropWrite propWrite | + propWrite = configAssigment() and + this = propWrite.getRhs() and + prop = propWrite.getPropertyName() and + ( + kind = "user name" and + prop = "accessKeyId" + or + kind = "password" and + prop = "secretAccessKey" + ) + ) } override string getCredentialsKind() { result = kind } diff --git a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected index 566023bb07b3..c73d5c10f33f 100644 --- a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected +++ b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected @@ -161,6 +161,8 @@ | HardcodedCredentials.js:506:41:506:51 | "AccessID1" | HardcodedCredentials.js:506:41:506:51 | "AccessID1" | HardcodedCredentials.js:506:41:506:51 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:506:41:506:51 | "AccessID1" | user name | | HardcodedCredentials.js:507:43:507:53 | "AccessID1" | HardcodedCredentials.js:507:43:507:53 | "AccessID1" | HardcodedCredentials.js:507:43:507:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:507:43:507:53 | "AccessID1" | user name | | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | user name | +| HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | The hard-coded value "SOMEACCESSKEY" is used as $@. | HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | user name | +| HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | password | | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | The hard-coded value "SOMEACCESSKEY" is used as $@. | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | user name | | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | password | | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | The hard-coded value "dbuser" is used as $@. | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | user name | @@ -557,6 +559,8 @@ nodes | HardcodedCredentials.js:507:73:507:89 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | semmle.label | "AccessID1" | | HardcodedCredentials.js:508:93:508:109 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | +| HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | semmle.label | "SOMEACCESSKEY" | +| HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | semmle.label | "hgfedcba" | | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | semmle.label | "SOMEACCESSKEY" | | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | semmle.label | "hgfedcba" | | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | semmle.label | 'dbuser' | diff --git a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js index 8141b4d8c584..5be11891e2a8 100644 --- a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js +++ b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js @@ -507,8 +507,8 @@ const swf = new AWS.SWF({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert const stepfunctions = new AWS.StepFunctions({accessKeyId: "AccessID1", secretAccessKey: "NotSoSecretKey1"}); // $ Alert - AWS.config.accessKeyId = "SOMEACCESSKEY"; // $ MISSING: Alert - AWS.config.secretAccessKey = "hgfedcba"; // $ MISSING: Alert + AWS.config.accessKeyId = "SOMEACCESSKEY"; // $ Alert + AWS.config.secretAccessKey = "hgfedcba"; // $ Alert const creds = new AWS.Credentials( "SOMEACCESSKEY", // $ MISSING: Alert From 42d5b80e8170943954025a2d5055092ff5f7dcca Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 24 Apr 2025 11:05:56 +0200 Subject: [PATCH 108/336] Added support for `AWS.Credentials` hardcoded credentials --- .../lib/semmle/javascript/frameworks/AWS.qll | 19 +++++++++++++++++++ .../CWE-798/HardcodedCredentials.expected | 4 ++++ .../Security/CWE-798/HardcodedCredentials.js | 4 ++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll index e07a37df6ff0..7e190ca6d5d9 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll @@ -54,6 +54,13 @@ module AWS { result = getAWSConfig().asSource().getAPropertyWrite() } + /** + * Gets a data flow node representing an instance of `new AWS.Credentials(accessKeyId, secretAccessKey)`. + */ + private DataFlow::Node getCredentialsCreationNode() { + result = getAWSImport().getMember("Credentials").getAnInstantiation().getReturn().asSource() + } + /** * Holds if the `i`th argument of `invk` is an object hash for `AWS.Config`. */ @@ -109,6 +116,18 @@ module AWS { prop = "secretAccessKey" ) ) + or + // `new AWS.Credentials({ accessKeyId: , secretAccessKey: })` + exists(DataFlow::InvokeNode invk | + invk = getCredentialsCreationNode() and + ( + this = invk.getArgument(0) and + kind = "user name" + or + this = invk.getArgument(1) and + kind = "password" + ) + ) } override string getCredentialsKind() { result = kind } diff --git a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected index c73d5c10f33f..3d2321cedc58 100644 --- a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected +++ b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected @@ -163,6 +163,8 @@ | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | user name | | HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | The hard-coded value "SOMEACCESSKEY" is used as $@. | HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | user name | | HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | password | +| HardcodedCredentials.js:514:9:514:23 | "SOMEACCESSKEY" | HardcodedCredentials.js:514:9:514:23 | "SOMEACCESSKEY" | HardcodedCredentials.js:514:9:514:23 | "SOMEACCESSKEY" | The hard-coded value "SOMEACCESSKEY" is used as $@. | HardcodedCredentials.js:514:9:514:23 | "SOMEACCESSKEY" | user name | +| HardcodedCredentials.js:515:9:515:18 | "hgfedcba" | HardcodedCredentials.js:515:9:515:18 | "hgfedcba" | HardcodedCredentials.js:515:9:515:18 | "hgfedcba" | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:515:9:515:18 | "hgfedcba" | password | | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | The hard-coded value "SOMEACCESSKEY" is used as $@. | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | user name | | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | password | | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | The hard-coded value "dbuser" is used as $@. | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | user name | @@ -561,6 +563,8 @@ nodes | HardcodedCredentials.js:508:93:508:109 | "NotSoSecretKey1" | semmle.label | "NotSoSecretKey1" | | HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | semmle.label | "SOMEACCESSKEY" | | HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | semmle.label | "hgfedcba" | +| HardcodedCredentials.js:514:9:514:23 | "SOMEACCESSKEY" | semmle.label | "SOMEACCESSKEY" | +| HardcodedCredentials.js:515:9:515:18 | "hgfedcba" | semmle.label | "hgfedcba" | | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | semmle.label | "SOMEACCESSKEY" | | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | semmle.label | "hgfedcba" | | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | semmle.label | 'dbuser' | diff --git a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js index 5be11891e2a8..7d102a4ee3dd 100644 --- a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js +++ b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.js @@ -511,8 +511,8 @@ AWS.config.secretAccessKey = "hgfedcba"; // $ Alert const creds = new AWS.Credentials( - "SOMEACCESSKEY", // $ MISSING: Alert - "hgfedcba" // $ MISSING: Alert + "SOMEACCESSKEY", // $ Alert + "hgfedcba" // $ Alert ); AWS.config.setCredentials(creds); From f7f9fb823a4f6f400ed26ae9973c94eb66cac3f1 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 24 Apr 2025 11:16:09 +0200 Subject: [PATCH 109/336] Updated `takesConfigurationObject` with API graphs --- javascript/ql/lib/semmle/javascript/frameworks/AWS.qll | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll index 7e190ca6d5d9..2eb1266c190d 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll @@ -65,12 +65,14 @@ module AWS { * Holds if the `i`th argument of `invk` is an object hash for `AWS.Config`. */ private predicate takesConfigurationObject(DataFlow::InvokeNode invk, int i) { - exists(DataFlow::ModuleImportNode mod | mod.getPath() = "aws-sdk" | + exists(API::Node mod | mod = getAWSImport() | // `AWS.config.update(nd)` - invk = mod.getAPropertyRead("config").getAMemberCall("update") and + invk = mod.getMember("config").getMember("update").getACall() and i = 0 or - exists(DataFlow::SourceNode cfg | cfg = mod.getAConstructorInvocation("Config") | + exists(DataFlow::SourceNode cfg | + cfg = mod.getMember("Config").getAnInstantiation().getReturn().asSource() + | // `new AWS.Config(nd)` invk = cfg and i = 0 From 654177daa791e7a157850dfe43fc6dc5a46b666b Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 24 Apr 2025 11:50:23 +0200 Subject: [PATCH 110/336] Fixed naming acronyms to be `PascalCase` --- .../ql/lib/semmle/javascript/frameworks/AWS.qll | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll index 2eb1266c190d..93ba66308217 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll @@ -8,7 +8,7 @@ module AWS { /** * Gets the name of a supported AWS service. */ - private string getAWSServiceName() { + private string getAwsServiceName() { result = [ "EC2", "Lambda", "ECS", "EKS", "Batch", "ElasticBeanstalk", "Lightsail", "AppRunner", "S3", @@ -31,41 +31,41 @@ module AWS { /** * Gets a node representing an import of the AWS SDK. */ - private API::Node getAWSImport() { result = API::moduleImport("aws-sdk") } + private API::Node getAwsImport() { result = API::moduleImport("aws-sdk") } /** * Gets a data flow node representing an instantiation of an AWS service. */ private DataFlow::Node getServiceInstantation() { result = - getAWSImport().getMember(getAWSServiceName()).getAnInstantiation().getReturn().asSource() + getAwsImport().getMember(getAwsServiceName()).getAnInstantiation().getReturn().asSource() } /** * Gets a node representing the AWS global config object. */ - private API::Node getAWSConfig() { result = getAWSImport().getMember("config") } + private API::Node getAwsConfig() { result = getAwsImport().getMember("config") } /** * Gets a property write to the AWS config object. * This captures assignments to AWS.config properties. */ private DataFlow::PropWrite configAssigment() { - result = getAWSConfig().asSource().getAPropertyWrite() + result = getAwsConfig().asSource().getAPropertyWrite() } /** * Gets a data flow node representing an instance of `new AWS.Credentials(accessKeyId, secretAccessKey)`. */ private DataFlow::Node getCredentialsCreationNode() { - result = getAWSImport().getMember("Credentials").getAnInstantiation().getReturn().asSource() + result = getAwsImport().getMember("Credentials").getAnInstantiation().getReturn().asSource() } /** * Holds if the `i`th argument of `invk` is an object hash for `AWS.Config`. */ private predicate takesConfigurationObject(DataFlow::InvokeNode invk, int i) { - exists(API::Node mod | mod = getAWSImport() | + exists(API::Node mod | mod = getAwsImport() | // `AWS.config.update(nd)` invk = mod.getMember("config").getMember("update").getACall() and i = 0 From 73309fb9dd969e82a4a4e6af1868c363cf9e2b45 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Mon, 28 Apr 2025 12:38:04 +0200 Subject: [PATCH 111/336] Updated modeling of `aws-sdk` with `MaD` --- javascript/ql/lib/ext/aws-sdk.model.yml | 8 + .../lib/semmle/javascript/frameworks/AWS.qll | 95 +-------- .../CWE-798/HardcodedCredentials.expected | 181 +++++++++--------- 3 files changed, 102 insertions(+), 182 deletions(-) create mode 100644 javascript/ql/lib/ext/aws-sdk.model.yml diff --git a/javascript/ql/lib/ext/aws-sdk.model.yml b/javascript/ql/lib/ext/aws-sdk.model.yml new file mode 100644 index 000000000000..eefa87fbe613 --- /dev/null +++ b/javascript/ql/lib/ext/aws-sdk.model.yml @@ -0,0 +1,8 @@ +extensions: + - addsTo: + pack: codeql/javascript-all + extensible: sinkModel + data: + - ["aws-sdk", "AnyMember.Argument[0].Member[secretAccessKey,accessKeyId]", "credentials-key"] + - ["aws-sdk", "AnyMember.Member[secretAccessKey,accessKeyId]", "credentials-key"] + - ["aws-sdk", "Member[Credentials].Argument[0,1]", "credentials-key"] diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll index 93ba66308217..1eac5888b955 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll @@ -5,74 +5,16 @@ import javascript module AWS { - /** - * Gets the name of a supported AWS service. - */ - private string getAwsServiceName() { - result = - [ - "EC2", "Lambda", "ECS", "EKS", "Batch", "ElasticBeanstalk", "Lightsail", "AppRunner", "S3", - "EFS", "Glacier", "S3Control", "StorageGateway", "Backup", "DynamoDB", "DynamoDBStreams", - "RDS", "Redshift", "ElastiCache", "Neptune", "QLDB", "Athena", "Route53", "CloudFront", - "APIGateway", "ApiGatewayV2", "DirectConnect", "GlobalAccelerator", "CloudWatch", - "CloudFormation", "CloudTrail", "Config", "Organizations", "ServiceCatalog", "SSM", - "ResourceGroups", "IAM", "CognitoIdentity", "CognitoIdentityServiceProvider", "GuardDuty", - "Inspector", "KMS", "SecretsManager", "SecurityHub", "STS", "WAF", "WAFRegional", - "SageMaker", "Rekognition", "Comprehend", "Textract", "Translate", "Polly", - "LexModelBuildingService", "MachineLearning", "Personalize", "EMR", "Kinesis", - "KinesisAnalytics", "KinesisVideo", "QuickSight", "DataPipeline", "Glue", "LakeFormation", - "SNS", "SQS", "SES", "Pinpoint", "Chime", "Connect", "Amplify", "AppSync", "DeviceFarm", - "IoTAnalytics", "IoTEvents", "IoT1ClickDevicesService", "IoTSiteWise", "MediaConvert", - "MediaLive", "MediaPackage", "MediaStore", "ElasticTranscoder", "EventBridge", "MQ", "SWF", - "StepFunctions" - ] - } - - /** - * Gets a node representing an import of the AWS SDK. - */ - private API::Node getAwsImport() { result = API::moduleImport("aws-sdk") } - - /** - * Gets a data flow node representing an instantiation of an AWS service. - */ - private DataFlow::Node getServiceInstantation() { - result = - getAwsImport().getMember(getAwsServiceName()).getAnInstantiation().getReturn().asSource() - } - - /** - * Gets a node representing the AWS global config object. - */ - private API::Node getAwsConfig() { result = getAwsImport().getMember("config") } - - /** - * Gets a property write to the AWS config object. - * This captures assignments to AWS.config properties. - */ - private DataFlow::PropWrite configAssigment() { - result = getAwsConfig().asSource().getAPropertyWrite() - } - - /** - * Gets a data flow node representing an instance of `new AWS.Credentials(accessKeyId, secretAccessKey)`. - */ - private DataFlow::Node getCredentialsCreationNode() { - result = getAwsImport().getMember("Credentials").getAnInstantiation().getReturn().asSource() - } - /** * Holds if the `i`th argument of `invk` is an object hash for `AWS.Config`. */ private predicate takesConfigurationObject(DataFlow::InvokeNode invk, int i) { - exists(API::Node mod | mod = getAwsImport() | + exists(DataFlow::ModuleImportNode mod | mod.getPath() = "aws-sdk" | // `AWS.config.update(nd)` - invk = mod.getMember("config").getMember("update").getACall() and + invk = mod.getAPropertyRead("config").getAMemberCall("update") and i = 0 or - exists(DataFlow::SourceNode cfg | - cfg = mod.getMember("Config").getAnInstantiation().getReturn().asSource() - | + exists(DataFlow::SourceNode cfg | cfg = mod.getAConstructorInvocation("Config") | // `new AWS.Config(nd)` invk = cfg and i = 0 @@ -94,42 +36,11 @@ module AWS { exists(string prop, DataFlow::InvokeNode invk, int i | takesConfigurationObject(invk, i) and this = invk.getOptionArgument(i, prop) - or - // `new AWS.ServiceName({ accessKeyId: , secretAccessKey: })` - invk = getServiceInstantation() and - i = 0 and - this = invk.getOptionArgument(i, prop) | prop = "accessKeyId" and kind = "user name" or prop = "secretAccessKey" and kind = "password" ) - or - // `AWS.config.accessKeyId = ` or `AWS.config.secretAccessKey = ` - exists(string prop, DataFlow::PropWrite propWrite | - propWrite = configAssigment() and - this = propWrite.getRhs() and - prop = propWrite.getPropertyName() and - ( - kind = "user name" and - prop = "accessKeyId" - or - kind = "password" and - prop = "secretAccessKey" - ) - ) - or - // `new AWS.Credentials({ accessKeyId: , secretAccessKey: })` - exists(DataFlow::InvokeNode invk | - invk = getCredentialsCreationNode() and - ( - this = invk.getArgument(0) and - kind = "user name" - or - this = invk.getArgument(1) and - kind = "password" - ) - ) } override string getCredentialsKind() { result = kind } diff --git a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected index 3d2321cedc58..22311127d548 100644 --- a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected +++ b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected @@ -9,7 +9,7 @@ | HardcodedCredentials.js:35:27:35:36 | 'hgfedcba' | HardcodedCredentials.js:35:27:35:36 | 'hgfedcba' | HardcodedCredentials.js:35:27:35:36 | 'hgfedcba' | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:35:27:35:36 | 'hgfedcba' | password | | HardcodedCredentials.js:41:38:41:47 | 'username' | HardcodedCredentials.js:41:38:41:47 | 'username' | HardcodedCredentials.js:41:38:41:47 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:41:38:41:47 | 'username' | user name | | HardcodedCredentials.js:41:67:41:76 | 'hgfedcba' | HardcodedCredentials.js:41:67:41:76 | 'hgfedcba' | HardcodedCredentials.js:41:67:41:76 | 'hgfedcba' | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:41:67:41:76 | 'hgfedcba' | password | -| HardcodedCredentials.js:42:35:42:44 | 'username' | HardcodedCredentials.js:42:35:42:44 | 'username' | HardcodedCredentials.js:42:35:42:44 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:42:35:42:44 | 'username' | user name | +| HardcodedCredentials.js:42:64:42:73 | 'hgfedcba' | HardcodedCredentials.js:42:64:42:73 | 'hgfedcba' | HardcodedCredentials.js:42:64:42:73 | 'hgfedcba' | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:42:64:42:73 | 'hgfedcba' | key | | HardcodedCredentials.js:42:64:42:73 | 'hgfedcba' | HardcodedCredentials.js:42:64:42:73 | 'hgfedcba' | HardcodedCredentials.js:42:64:42:73 | 'hgfedcba' | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:42:64:42:73 | 'hgfedcba' | password | | HardcodedCredentials.js:44:34:44:43 | 'username' | HardcodedCredentials.js:44:34:44:43 | 'username' | HardcodedCredentials.js:44:34:44:43 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:44:34:44:43 | 'username' | user name | | HardcodedCredentials.js:44:63:44:72 | 'hgfedcba' | HardcodedCredentials.js:44:63:44:72 | 'hgfedcba' | HardcodedCredentials.js:44:63:44:72 | 'hgfedcba' | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:44:63:44:72 | 'hgfedcba' | password | @@ -75,96 +75,97 @@ | HardcodedCredentials.js:375:21:375:43 | "myHard ... ateKey" | HardcodedCredentials.js:375:21:375:43 | "myHard ... ateKey" | HardcodedCredentials.js:385:31:385:39 | secretKey | The hard-coded value "myHardCodedPrivateKey" is used as $@. | HardcodedCredentials.js:385:31:385:39 | secretKey | jwt key | | HardcodedCredentials.js:396:21:396:43 | "myHard ... ateKey" | HardcodedCredentials.js:396:21:396:43 | "myHard ... ateKey" | HardcodedCredentials.js:399:17:399:25 | secretKey | The hard-coded value "myHardCodedPrivateKey" is used as $@. | HardcodedCredentials.js:399:17:399:25 | secretKey | jwt key | | HardcodedCredentials.js:414:21:414:43 | "myHard ... ateKey" | HardcodedCredentials.js:414:21:414:43 | "myHard ... ateKey" | HardcodedCredentials.js:416:27:416:35 | secretKey | The hard-coded value "myHardCodedPrivateKey" is used as $@. | HardcodedCredentials.js:416:27:416:35 | secretKey | jwt key | -| HardcodedCredentials.js:423:43:423:53 | "AccessID1" | HardcodedCredentials.js:423:43:423:53 | "AccessID1" | HardcodedCredentials.js:423:43:423:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:423:43:423:53 | "AccessID1" | user name | -| HardcodedCredentials.js:424:49:424:59 | "AccessID1" | HardcodedCredentials.js:424:49:424:59 | "AccessID1" | HardcodedCredentials.js:424:49:424:59 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:424:49:424:59 | "AccessID1" | user name | -| HardcodedCredentials.js:425:43:425:53 | "AccessID1" | HardcodedCredentials.js:425:43:425:53 | "AccessID1" | HardcodedCredentials.js:425:43:425:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:425:43:425:53 | "AccessID1" | user name | -| HardcodedCredentials.js:426:43:426:53 | "AccessID1" | HardcodedCredentials.js:426:43:426:53 | "AccessID1" | HardcodedCredentials.js:426:43:426:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:426:43:426:53 | "AccessID1" | user name | -| HardcodedCredentials.js:427:47:427:57 | "AccessID1" | HardcodedCredentials.js:427:47:427:57 | "AccessID1" | HardcodedCredentials.js:427:47:427:57 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:427:47:427:57 | "AccessID1" | user name | -| HardcodedCredentials.js:428:69:428:79 | "AccessID1" | HardcodedCredentials.js:428:69:428:79 | "AccessID1" | HardcodedCredentials.js:428:69:428:79 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:428:69:428:79 | "AccessID1" | user name | -| HardcodedCredentials.js:429:55:429:65 | "AccessID1" | HardcodedCredentials.js:429:55:429:65 | "AccessID1" | HardcodedCredentials.js:429:55:429:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:429:55:429:65 | "AccessID1" | user name | -| HardcodedCredentials.js:430:55:430:65 | "AccessID1" | HardcodedCredentials.js:430:55:430:65 | "AccessID1" | HardcodedCredentials.js:430:55:430:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:430:55:430:65 | "AccessID1" | user name | -| HardcodedCredentials.js:431:41:431:51 | "AccessID1" | HardcodedCredentials.js:431:41:431:51 | "AccessID1" | HardcodedCredentials.js:431:41:431:51 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:431:41:431:51 | "AccessID1" | user name | -| HardcodedCredentials.js:432:43:432:53 | "AccessID1" | HardcodedCredentials.js:432:43:432:53 | "AccessID1" | HardcodedCredentials.js:432:43:432:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:432:43:432:53 | "AccessID1" | user name | -| HardcodedCredentials.js:433:51:433:61 | "AccessID1" | HardcodedCredentials.js:433:51:433:61 | "AccessID1" | HardcodedCredentials.js:433:51:433:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:433:51:433:61 | "AccessID1" | user name | -| HardcodedCredentials.js:434:55:434:65 | "AccessID1" | HardcodedCredentials.js:434:55:434:65 | "AccessID1" | HardcodedCredentials.js:434:55:434:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:434:55:434:65 | "AccessID1" | user name | -| HardcodedCredentials.js:435:65:435:75 | "AccessID1" | HardcodedCredentials.js:435:65:435:75 | "AccessID1" | HardcodedCredentials.js:435:65:435:75 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:435:65:435:75 | "AccessID1" | user name | -| HardcodedCredentials.js:436:49:436:59 | "AccessID1" | HardcodedCredentials.js:436:49:436:59 | "AccessID1" | HardcodedCredentials.js:436:49:436:59 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:436:49:436:59 | "AccessID1" | user name | -| HardcodedCredentials.js:437:53:437:63 | "AccessID1" | HardcodedCredentials.js:437:53:437:63 | "AccessID1" | HardcodedCredentials.js:437:53:437:63 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:437:53:437:63 | "AccessID1" | user name | -| HardcodedCredentials.js:438:67:438:77 | "AccessID1" | HardcodedCredentials.js:438:67:438:77 | "AccessID1" | HardcodedCredentials.js:438:67:438:77 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:438:67:438:77 | "AccessID1" | user name | -| HardcodedCredentials.js:439:43:439:53 | "AccessID1" | HardcodedCredentials.js:439:43:439:53 | "AccessID1" | HardcodedCredentials.js:439:43:439:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:439:43:439:53 | "AccessID1" | user name | -| HardcodedCredentials.js:440:53:440:63 | "AccessID1" | HardcodedCredentials.js:440:53:440:63 | "AccessID1" | HardcodedCredentials.js:440:53:440:63 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:440:53:440:63 | "AccessID1" | user name | -| HardcodedCredentials.js:441:59:441:69 | "AccessID1" | HardcodedCredentials.js:441:59:441:69 | "AccessID1" | HardcodedCredentials.js:441:59:441:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:441:59:441:69 | "AccessID1" | user name | -| HardcodedCredentials.js:442:51:442:61 | "AccessID1" | HardcodedCredentials.js:442:51:442:61 | "AccessID1" | HardcodedCredentials.js:442:51:442:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:442:51:442:61 | "AccessID1" | user name | -| HardcodedCredentials.js:443:45:443:55 | "AccessID1" | HardcodedCredentials.js:443:45:443:55 | "AccessID1" | HardcodedCredentials.js:443:45:443:55 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:443:45:443:55 | "AccessID1" | user name | -| HardcodedCredentials.js:444:49:444:59 | "AccessID1" | HardcodedCredentials.js:444:49:444:59 | "AccessID1" | HardcodedCredentials.js:444:49:444:59 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:444:49:444:59 | "AccessID1" | user name | -| HardcodedCredentials.js:445:51:445:61 | "AccessID1" | HardcodedCredentials.js:445:51:445:61 | "AccessID1" | HardcodedCredentials.js:445:51:445:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:445:51:445:61 | "AccessID1" | user name | -| HardcodedCredentials.js:446:57:446:67 | "AccessID1" | HardcodedCredentials.js:446:57:446:67 | "AccessID1" | HardcodedCredentials.js:446:57:446:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:446:57:446:67 | "AccessID1" | user name | -| HardcodedCredentials.js:447:57:447:67 | "AccessID1" | HardcodedCredentials.js:447:57:447:67 | "AccessID1" | HardcodedCredentials.js:447:57:447:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:447:57:447:67 | "AccessID1" | user name | -| HardcodedCredentials.js:448:61:448:71 | "AccessID1" | HardcodedCredentials.js:448:61:448:71 | "AccessID1" | HardcodedCredentials.js:448:61:448:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:448:61:448:71 | "AccessID1" | user name | -| HardcodedCredentials.js:449:63:449:73 | "AccessID1" | HardcodedCredentials.js:449:63:449:73 | "AccessID1" | HardcodedCredentials.js:449:63:449:73 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:449:63:449:73 | "AccessID1" | user name | -| HardcodedCredentials.js:450:71:450:81 | "AccessID1" | HardcodedCredentials.js:450:71:450:81 | "AccessID1" | HardcodedCredentials.js:450:71:450:81 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:450:71:450:81 | "AccessID1" | user name | -| HardcodedCredentials.js:451:57:451:67 | "AccessID1" | HardcodedCredentials.js:451:57:451:67 | "AccessID1" | HardcodedCredentials.js:451:57:451:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:451:57:451:67 | "AccessID1" | user name | -| HardcodedCredentials.js:452:65:452:75 | "AccessID1" | HardcodedCredentials.js:452:65:452:75 | "AccessID1" | HardcodedCredentials.js:452:65:452:75 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:452:65:452:75 | "AccessID1" | user name | -| HardcodedCredentials.js:453:57:453:67 | "AccessID1" | HardcodedCredentials.js:453:57:453:67 | "AccessID1" | HardcodedCredentials.js:453:57:453:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:453:57:453:67 | "AccessID1" | user name | +| HardcodedCredentials.js:423:43:423:53 | "AccessID1" | HardcodedCredentials.js:423:43:423:53 | "AccessID1" | HardcodedCredentials.js:423:43:423:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:423:43:423:53 | "AccessID1" | key | +| HardcodedCredentials.js:424:49:424:59 | "AccessID1" | HardcodedCredentials.js:424:49:424:59 | "AccessID1" | HardcodedCredentials.js:424:49:424:59 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:424:49:424:59 | "AccessID1" | key | +| HardcodedCredentials.js:425:43:425:53 | "AccessID1" | HardcodedCredentials.js:425:43:425:53 | "AccessID1" | HardcodedCredentials.js:425:43:425:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:425:43:425:53 | "AccessID1" | key | +| HardcodedCredentials.js:426:43:426:53 | "AccessID1" | HardcodedCredentials.js:426:43:426:53 | "AccessID1" | HardcodedCredentials.js:426:43:426:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:426:43:426:53 | "AccessID1" | key | +| HardcodedCredentials.js:427:47:427:57 | "AccessID1" | HardcodedCredentials.js:427:47:427:57 | "AccessID1" | HardcodedCredentials.js:427:47:427:57 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:427:47:427:57 | "AccessID1" | key | +| HardcodedCredentials.js:428:69:428:79 | "AccessID1" | HardcodedCredentials.js:428:69:428:79 | "AccessID1" | HardcodedCredentials.js:428:69:428:79 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:428:69:428:79 | "AccessID1" | key | +| HardcodedCredentials.js:429:55:429:65 | "AccessID1" | HardcodedCredentials.js:429:55:429:65 | "AccessID1" | HardcodedCredentials.js:429:55:429:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:429:55:429:65 | "AccessID1" | key | +| HardcodedCredentials.js:430:55:430:65 | "AccessID1" | HardcodedCredentials.js:430:55:430:65 | "AccessID1" | HardcodedCredentials.js:430:55:430:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:430:55:430:65 | "AccessID1" | key | +| HardcodedCredentials.js:431:41:431:51 | "AccessID1" | HardcodedCredentials.js:431:41:431:51 | "AccessID1" | HardcodedCredentials.js:431:41:431:51 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:431:41:431:51 | "AccessID1" | key | +| HardcodedCredentials.js:432:43:432:53 | "AccessID1" | HardcodedCredentials.js:432:43:432:53 | "AccessID1" | HardcodedCredentials.js:432:43:432:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:432:43:432:53 | "AccessID1" | key | +| HardcodedCredentials.js:433:51:433:61 | "AccessID1" | HardcodedCredentials.js:433:51:433:61 | "AccessID1" | HardcodedCredentials.js:433:51:433:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:433:51:433:61 | "AccessID1" | key | +| HardcodedCredentials.js:434:55:434:65 | "AccessID1" | HardcodedCredentials.js:434:55:434:65 | "AccessID1" | HardcodedCredentials.js:434:55:434:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:434:55:434:65 | "AccessID1" | key | +| HardcodedCredentials.js:435:65:435:75 | "AccessID1" | HardcodedCredentials.js:435:65:435:75 | "AccessID1" | HardcodedCredentials.js:435:65:435:75 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:435:65:435:75 | "AccessID1" | key | +| HardcodedCredentials.js:436:49:436:59 | "AccessID1" | HardcodedCredentials.js:436:49:436:59 | "AccessID1" | HardcodedCredentials.js:436:49:436:59 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:436:49:436:59 | "AccessID1" | key | +| HardcodedCredentials.js:437:53:437:63 | "AccessID1" | HardcodedCredentials.js:437:53:437:63 | "AccessID1" | HardcodedCredentials.js:437:53:437:63 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:437:53:437:63 | "AccessID1" | key | +| HardcodedCredentials.js:438:67:438:77 | "AccessID1" | HardcodedCredentials.js:438:67:438:77 | "AccessID1" | HardcodedCredentials.js:438:67:438:77 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:438:67:438:77 | "AccessID1" | key | +| HardcodedCredentials.js:439:43:439:53 | "AccessID1" | HardcodedCredentials.js:439:43:439:53 | "AccessID1" | HardcodedCredentials.js:439:43:439:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:439:43:439:53 | "AccessID1" | key | +| HardcodedCredentials.js:440:53:440:63 | "AccessID1" | HardcodedCredentials.js:440:53:440:63 | "AccessID1" | HardcodedCredentials.js:440:53:440:63 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:440:53:440:63 | "AccessID1" | key | +| HardcodedCredentials.js:441:59:441:69 | "AccessID1" | HardcodedCredentials.js:441:59:441:69 | "AccessID1" | HardcodedCredentials.js:441:59:441:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:441:59:441:69 | "AccessID1" | key | +| HardcodedCredentials.js:442:51:442:61 | "AccessID1" | HardcodedCredentials.js:442:51:442:61 | "AccessID1" | HardcodedCredentials.js:442:51:442:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:442:51:442:61 | "AccessID1" | key | +| HardcodedCredentials.js:443:45:443:55 | "AccessID1" | HardcodedCredentials.js:443:45:443:55 | "AccessID1" | HardcodedCredentials.js:443:45:443:55 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:443:45:443:55 | "AccessID1" | key | +| HardcodedCredentials.js:444:49:444:59 | "AccessID1" | HardcodedCredentials.js:444:49:444:59 | "AccessID1" | HardcodedCredentials.js:444:49:444:59 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:444:49:444:59 | "AccessID1" | key | +| HardcodedCredentials.js:445:51:445:61 | "AccessID1" | HardcodedCredentials.js:445:51:445:61 | "AccessID1" | HardcodedCredentials.js:445:51:445:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:445:51:445:61 | "AccessID1" | key | +| HardcodedCredentials.js:446:57:446:67 | "AccessID1" | HardcodedCredentials.js:446:57:446:67 | "AccessID1" | HardcodedCredentials.js:446:57:446:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:446:57:446:67 | "AccessID1" | key | +| HardcodedCredentials.js:447:57:447:67 | "AccessID1" | HardcodedCredentials.js:447:57:447:67 | "AccessID1" | HardcodedCredentials.js:447:57:447:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:447:57:447:67 | "AccessID1" | key | +| HardcodedCredentials.js:448:61:448:71 | "AccessID1" | HardcodedCredentials.js:448:61:448:71 | "AccessID1" | HardcodedCredentials.js:448:61:448:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:448:61:448:71 | "AccessID1" | key | +| HardcodedCredentials.js:449:63:449:73 | "AccessID1" | HardcodedCredentials.js:449:63:449:73 | "AccessID1" | HardcodedCredentials.js:449:63:449:73 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:449:63:449:73 | "AccessID1" | key | +| HardcodedCredentials.js:450:71:450:81 | "AccessID1" | HardcodedCredentials.js:450:71:450:81 | "AccessID1" | HardcodedCredentials.js:450:71:450:81 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:450:71:450:81 | "AccessID1" | key | +| HardcodedCredentials.js:451:57:451:67 | "AccessID1" | HardcodedCredentials.js:451:57:451:67 | "AccessID1" | HardcodedCredentials.js:451:57:451:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:451:57:451:67 | "AccessID1" | key | +| HardcodedCredentials.js:452:65:452:75 | "AccessID1" | HardcodedCredentials.js:452:65:452:75 | "AccessID1" | HardcodedCredentials.js:452:65:452:75 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:452:65:452:75 | "AccessID1" | key | +| HardcodedCredentials.js:453:57:453:67 | "AccessID1" | HardcodedCredentials.js:453:57:453:67 | "AccessID1" | HardcodedCredentials.js:453:57:453:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:453:57:453:67 | "AccessID1" | key | +| HardcodedCredentials.js:454:49:454:59 | "AccessID1" | HardcodedCredentials.js:454:49:454:59 | "AccessID1" | HardcodedCredentials.js:454:49:454:59 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:454:49:454:59 | "AccessID1" | key | | HardcodedCredentials.js:454:49:454:59 | "AccessID1" | HardcodedCredentials.js:454:49:454:59 | "AccessID1" | HardcodedCredentials.js:454:49:454:59 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:454:49:454:59 | "AccessID1" | user name | -| HardcodedCredentials.js:455:63:455:73 | "AccessID1" | HardcodedCredentials.js:455:63:455:73 | "AccessID1" | HardcodedCredentials.js:455:63:455:73 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:455:63:455:73 | "AccessID1" | user name | -| HardcodedCredentials.js:456:65:456:75 | "AccessID1" | HardcodedCredentials.js:456:65:456:75 | "AccessID1" | HardcodedCredentials.js:456:65:456:75 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:456:65:456:75 | "AccessID1" | user name | -| HardcodedCredentials.js:457:43:457:53 | "AccessID1" | HardcodedCredentials.js:457:43:457:53 | "AccessID1" | HardcodedCredentials.js:457:43:457:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:457:43:457:53 | "AccessID1" | user name | -| HardcodedCredentials.js:458:65:458:75 | "AccessID1" | HardcodedCredentials.js:458:65:458:75 | "AccessID1" | HardcodedCredentials.js:458:65:458:75 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:458:65:458:75 | "AccessID1" | user name | -| HardcodedCredentials.js:459:43:459:53 | "AccessID1" | HardcodedCredentials.js:459:43:459:53 | "AccessID1" | HardcodedCredentials.js:459:43:459:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:459:43:459:53 | "AccessID1" | user name | -| HardcodedCredentials.js:460:67:460:77 | "AccessID1" | HardcodedCredentials.js:460:67:460:77 | "AccessID1" | HardcodedCredentials.js:460:67:460:77 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:460:67:460:77 | "AccessID1" | user name | -| HardcodedCredentials.js:461:97:461:107 | "AccessID1" | HardcodedCredentials.js:461:97:461:107 | "AccessID1" | HardcodedCredentials.js:461:97:461:107 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:461:97:461:107 | "AccessID1" | user name | -| HardcodedCredentials.js:462:55:462:65 | "AccessID1" | HardcodedCredentials.js:462:55:462:65 | "AccessID1" | HardcodedCredentials.js:462:55:462:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:462:55:462:65 | "AccessID1" | user name | -| HardcodedCredentials.js:463:55:463:65 | "AccessID1" | HardcodedCredentials.js:463:55:463:65 | "AccessID1" | HardcodedCredentials.js:463:55:463:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:463:55:463:65 | "AccessID1" | user name | -| HardcodedCredentials.js:464:43:464:53 | "AccessID1" | HardcodedCredentials.js:464:43:464:53 | "AccessID1" | HardcodedCredentials.js:464:43:464:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:464:43:464:53 | "AccessID1" | user name | -| HardcodedCredentials.js:465:65:465:75 | "AccessID1" | HardcodedCredentials.js:465:65:465:75 | "AccessID1" | HardcodedCredentials.js:465:65:465:75 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:465:65:465:75 | "AccessID1" | user name | -| HardcodedCredentials.js:466:59:466:69 | "AccessID1" | HardcodedCredentials.js:466:59:466:69 | "AccessID1" | HardcodedCredentials.js:466:59:466:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:466:59:466:69 | "AccessID1" | user name | -| HardcodedCredentials.js:467:43:467:53 | "AccessID1" | HardcodedCredentials.js:467:43:467:53 | "AccessID1" | HardcodedCredentials.js:467:43:467:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:467:43:467:53 | "AccessID1" | user name | -| HardcodedCredentials.js:468:43:468:53 | "AccessID1" | HardcodedCredentials.js:468:43:468:53 | "AccessID1" | HardcodedCredentials.js:468:43:468:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:468:43:468:53 | "AccessID1" | user name | -| HardcodedCredentials.js:469:59:469:69 | "AccessID1" | HardcodedCredentials.js:469:59:469:69 | "AccessID1" | HardcodedCredentials.js:469:59:469:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:469:59:469:69 | "AccessID1" | user name | -| HardcodedCredentials.js:470:55:470:65 | "AccessID1" | HardcodedCredentials.js:470:55:470:65 | "AccessID1" | HardcodedCredentials.js:470:55:470:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:470:55:470:65 | "AccessID1" | user name | -| HardcodedCredentials.js:471:59:471:69 | "AccessID1" | HardcodedCredentials.js:471:59:471:69 | "AccessID1" | HardcodedCredentials.js:471:59:471:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:471:59:471:69 | "AccessID1" | user name | -| HardcodedCredentials.js:472:57:472:67 | "AccessID1" | HardcodedCredentials.js:472:57:472:67 | "AccessID1" | HardcodedCredentials.js:472:57:472:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:472:57:472:67 | "AccessID1" | user name | -| HardcodedCredentials.js:473:53:473:63 | "AccessID1" | HardcodedCredentials.js:473:53:473:63 | "AccessID1" | HardcodedCredentials.js:473:53:473:63 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:473:53:473:63 | "AccessID1" | user name | -| HardcodedCredentials.js:474:55:474:65 | "AccessID1" | HardcodedCredentials.js:474:55:474:65 | "AccessID1" | HardcodedCredentials.js:474:55:474:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:474:55:474:65 | "AccessID1" | user name | -| HardcodedCredentials.js:475:47:475:57 | "AccessID1" | HardcodedCredentials.js:475:47:475:57 | "AccessID1" | HardcodedCredentials.js:475:47:475:57 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:475:47:475:57 | "AccessID1" | user name | -| HardcodedCredentials.js:476:83:476:93 | "AccessID1" | HardcodedCredentials.js:476:83:476:93 | "AccessID1" | HardcodedCredentials.js:476:83:476:93 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:476:83:476:93 | "AccessID1" | user name | -| HardcodedCredentials.js:477:67:477:77 | "AccessID1" | HardcodedCredentials.js:477:67:477:77 | "AccessID1" | HardcodedCredentials.js:477:67:477:77 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:477:67:477:77 | "AccessID1" | user name | -| HardcodedCredentials.js:478:59:478:69 | "AccessID1" | HardcodedCredentials.js:478:59:478:69 | "AccessID1" | HardcodedCredentials.js:478:59:478:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:478:59:478:69 | "AccessID1" | user name | -| HardcodedCredentials.js:479:43:479:53 | "AccessID1" | HardcodedCredentials.js:479:43:479:53 | "AccessID1" | HardcodedCredentials.js:479:43:479:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:479:43:479:53 | "AccessID1" | user name | -| HardcodedCredentials.js:480:51:480:61 | "AccessID1" | HardcodedCredentials.js:480:51:480:61 | "AccessID1" | HardcodedCredentials.js:480:51:480:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:480:51:480:61 | "AccessID1" | user name | -| HardcodedCredentials.js:481:69:481:79 | "AccessID1" | HardcodedCredentials.js:481:69:481:79 | "AccessID1" | HardcodedCredentials.js:481:69:481:79 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:481:69:481:79 | "AccessID1" | user name | -| HardcodedCredentials.js:482:61:482:71 | "AccessID1" | HardcodedCredentials.js:482:61:482:71 | "AccessID1" | HardcodedCredentials.js:482:61:482:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:482:61:482:71 | "AccessID1" | user name | -| HardcodedCredentials.js:483:57:483:67 | "AccessID1" | HardcodedCredentials.js:483:57:483:67 | "AccessID1" | HardcodedCredentials.js:483:57:483:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:483:57:483:67 | "AccessID1" | user name | -| HardcodedCredentials.js:484:61:484:71 | "AccessID1" | HardcodedCredentials.js:484:61:484:71 | "AccessID1" | HardcodedCredentials.js:484:61:484:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:484:61:484:71 | "AccessID1" | user name | -| HardcodedCredentials.js:485:45:485:55 | "AccessID1" | HardcodedCredentials.js:485:45:485:55 | "AccessID1" | HardcodedCredentials.js:485:45:485:55 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:485:45:485:55 | "AccessID1" | user name | -| HardcodedCredentials.js:486:63:486:73 | "AccessID1" | HardcodedCredentials.js:486:63:486:73 | "AccessID1" | HardcodedCredentials.js:486:63:486:73 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:486:63:486:73 | "AccessID1" | user name | -| HardcodedCredentials.js:487:43:487:53 | "AccessID1" | HardcodedCredentials.js:487:43:487:53 | "AccessID1" | HardcodedCredentials.js:487:43:487:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:487:43:487:53 | "AccessID1" | user name | -| HardcodedCredentials.js:488:43:488:53 | "AccessID1" | HardcodedCredentials.js:488:43:488:53 | "AccessID1" | HardcodedCredentials.js:488:43:488:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:488:43:488:53 | "AccessID1" | user name | -| HardcodedCredentials.js:489:43:489:53 | "AccessID1" | HardcodedCredentials.js:489:43:489:53 | "AccessID1" | HardcodedCredentials.js:489:43:489:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:489:43:489:53 | "AccessID1" | user name | -| HardcodedCredentials.js:490:53:490:63 | "AccessID1" | HardcodedCredentials.js:490:53:490:63 | "AccessID1" | HardcodedCredentials.js:490:53:490:63 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:490:53:490:63 | "AccessID1" | user name | -| HardcodedCredentials.js:491:47:491:57 | "AccessID1" | HardcodedCredentials.js:491:47:491:57 | "AccessID1" | HardcodedCredentials.js:491:47:491:57 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:491:47:491:57 | "AccessID1" | user name | -| HardcodedCredentials.js:492:51:492:61 | "AccessID1" | HardcodedCredentials.js:492:51:492:61 | "AccessID1" | HardcodedCredentials.js:492:51:492:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:492:51:492:61 | "AccessID1" | user name | -| HardcodedCredentials.js:493:51:493:61 | "AccessID1" | HardcodedCredentials.js:493:51:493:61 | "AccessID1" | HardcodedCredentials.js:493:51:493:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:493:51:493:61 | "AccessID1" | user name | -| HardcodedCredentials.js:494:51:494:61 | "AccessID1" | HardcodedCredentials.js:494:51:494:61 | "AccessID1" | HardcodedCredentials.js:494:51:494:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:494:51:494:61 | "AccessID1" | user name | -| HardcodedCredentials.js:495:57:495:67 | "AccessID1" | HardcodedCredentials.js:495:57:495:67 | "AccessID1" | HardcodedCredentials.js:495:57:495:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:495:57:495:67 | "AccessID1" | user name | -| HardcodedCredentials.js:496:61:496:71 | "AccessID1" | HardcodedCredentials.js:496:61:496:71 | "AccessID1" | HardcodedCredentials.js:496:61:496:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:496:61:496:71 | "AccessID1" | user name | -| HardcodedCredentials.js:497:55:497:65 | "AccessID1" | HardcodedCredentials.js:497:55:497:65 | "AccessID1" | HardcodedCredentials.js:497:55:497:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:497:55:497:65 | "AccessID1" | user name | -| HardcodedCredentials.js:498:83:498:93 | "AccessID1" | HardcodedCredentials.js:498:83:498:93 | "AccessID1" | HardcodedCredentials.js:498:83:498:93 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:498:83:498:93 | "AccessID1" | user name | -| HardcodedCredentials.js:499:59:499:69 | "AccessID1" | HardcodedCredentials.js:499:59:499:69 | "AccessID1" | HardcodedCredentials.js:499:59:499:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:499:59:499:69 | "AccessID1" | user name | -| HardcodedCredentials.js:500:61:500:71 | "AccessID1" | HardcodedCredentials.js:500:61:500:71 | "AccessID1" | HardcodedCredentials.js:500:61:500:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:500:61:500:71 | "AccessID1" | user name | -| HardcodedCredentials.js:501:55:501:65 | "AccessID1" | HardcodedCredentials.js:501:55:501:65 | "AccessID1" | HardcodedCredentials.js:501:55:501:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:501:55:501:65 | "AccessID1" | user name | -| HardcodedCredentials.js:502:61:502:71 | "AccessID1" | HardcodedCredentials.js:502:61:502:71 | "AccessID1" | HardcodedCredentials.js:502:61:502:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:502:61:502:71 | "AccessID1" | user name | -| HardcodedCredentials.js:503:57:503:67 | "AccessID1" | HardcodedCredentials.js:503:57:503:67 | "AccessID1" | HardcodedCredentials.js:503:57:503:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:503:57:503:67 | "AccessID1" | user name | -| HardcodedCredentials.js:504:71:504:81 | "AccessID1" | HardcodedCredentials.js:504:71:504:81 | "AccessID1" | HardcodedCredentials.js:504:71:504:81 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:504:71:504:81 | "AccessID1" | user name | -| HardcodedCredentials.js:505:59:505:69 | "AccessID1" | HardcodedCredentials.js:505:59:505:69 | "AccessID1" | HardcodedCredentials.js:505:59:505:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:505:59:505:69 | "AccessID1" | user name | -| HardcodedCredentials.js:506:41:506:51 | "AccessID1" | HardcodedCredentials.js:506:41:506:51 | "AccessID1" | HardcodedCredentials.js:506:41:506:51 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:506:41:506:51 | "AccessID1" | user name | -| HardcodedCredentials.js:507:43:507:53 | "AccessID1" | HardcodedCredentials.js:507:43:507:53 | "AccessID1" | HardcodedCredentials.js:507:43:507:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:507:43:507:53 | "AccessID1" | user name | -| HardcodedCredentials.js:508:63:508:73 | "AccessID1" | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | user name | -| HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | The hard-coded value "SOMEACCESSKEY" is used as $@. | HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | user name | -| HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | password | -| HardcodedCredentials.js:514:9:514:23 | "SOMEACCESSKEY" | HardcodedCredentials.js:514:9:514:23 | "SOMEACCESSKEY" | HardcodedCredentials.js:514:9:514:23 | "SOMEACCESSKEY" | The hard-coded value "SOMEACCESSKEY" is used as $@. | HardcodedCredentials.js:514:9:514:23 | "SOMEACCESSKEY" | user name | -| HardcodedCredentials.js:515:9:515:18 | "hgfedcba" | HardcodedCredentials.js:515:9:515:18 | "hgfedcba" | HardcodedCredentials.js:515:9:515:18 | "hgfedcba" | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:515:9:515:18 | "hgfedcba" | password | +| HardcodedCredentials.js:455:63:455:73 | "AccessID1" | HardcodedCredentials.js:455:63:455:73 | "AccessID1" | HardcodedCredentials.js:455:63:455:73 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:455:63:455:73 | "AccessID1" | key | +| HardcodedCredentials.js:456:65:456:75 | "AccessID1" | HardcodedCredentials.js:456:65:456:75 | "AccessID1" | HardcodedCredentials.js:456:65:456:75 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:456:65:456:75 | "AccessID1" | key | +| HardcodedCredentials.js:457:43:457:53 | "AccessID1" | HardcodedCredentials.js:457:43:457:53 | "AccessID1" | HardcodedCredentials.js:457:43:457:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:457:43:457:53 | "AccessID1" | key | +| HardcodedCredentials.js:458:65:458:75 | "AccessID1" | HardcodedCredentials.js:458:65:458:75 | "AccessID1" | HardcodedCredentials.js:458:65:458:75 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:458:65:458:75 | "AccessID1" | key | +| HardcodedCredentials.js:459:43:459:53 | "AccessID1" | HardcodedCredentials.js:459:43:459:53 | "AccessID1" | HardcodedCredentials.js:459:43:459:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:459:43:459:53 | "AccessID1" | key | +| HardcodedCredentials.js:460:67:460:77 | "AccessID1" | HardcodedCredentials.js:460:67:460:77 | "AccessID1" | HardcodedCredentials.js:460:67:460:77 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:460:67:460:77 | "AccessID1" | key | +| HardcodedCredentials.js:461:97:461:107 | "AccessID1" | HardcodedCredentials.js:461:97:461:107 | "AccessID1" | HardcodedCredentials.js:461:97:461:107 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:461:97:461:107 | "AccessID1" | key | +| HardcodedCredentials.js:462:55:462:65 | "AccessID1" | HardcodedCredentials.js:462:55:462:65 | "AccessID1" | HardcodedCredentials.js:462:55:462:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:462:55:462:65 | "AccessID1" | key | +| HardcodedCredentials.js:463:55:463:65 | "AccessID1" | HardcodedCredentials.js:463:55:463:65 | "AccessID1" | HardcodedCredentials.js:463:55:463:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:463:55:463:65 | "AccessID1" | key | +| HardcodedCredentials.js:464:43:464:53 | "AccessID1" | HardcodedCredentials.js:464:43:464:53 | "AccessID1" | HardcodedCredentials.js:464:43:464:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:464:43:464:53 | "AccessID1" | key | +| HardcodedCredentials.js:465:65:465:75 | "AccessID1" | HardcodedCredentials.js:465:65:465:75 | "AccessID1" | HardcodedCredentials.js:465:65:465:75 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:465:65:465:75 | "AccessID1" | key | +| HardcodedCredentials.js:466:59:466:69 | "AccessID1" | HardcodedCredentials.js:466:59:466:69 | "AccessID1" | HardcodedCredentials.js:466:59:466:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:466:59:466:69 | "AccessID1" | key | +| HardcodedCredentials.js:467:43:467:53 | "AccessID1" | HardcodedCredentials.js:467:43:467:53 | "AccessID1" | HardcodedCredentials.js:467:43:467:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:467:43:467:53 | "AccessID1" | key | +| HardcodedCredentials.js:468:43:468:53 | "AccessID1" | HardcodedCredentials.js:468:43:468:53 | "AccessID1" | HardcodedCredentials.js:468:43:468:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:468:43:468:53 | "AccessID1" | key | +| HardcodedCredentials.js:469:59:469:69 | "AccessID1" | HardcodedCredentials.js:469:59:469:69 | "AccessID1" | HardcodedCredentials.js:469:59:469:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:469:59:469:69 | "AccessID1" | key | +| HardcodedCredentials.js:470:55:470:65 | "AccessID1" | HardcodedCredentials.js:470:55:470:65 | "AccessID1" | HardcodedCredentials.js:470:55:470:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:470:55:470:65 | "AccessID1" | key | +| HardcodedCredentials.js:471:59:471:69 | "AccessID1" | HardcodedCredentials.js:471:59:471:69 | "AccessID1" | HardcodedCredentials.js:471:59:471:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:471:59:471:69 | "AccessID1" | key | +| HardcodedCredentials.js:472:57:472:67 | "AccessID1" | HardcodedCredentials.js:472:57:472:67 | "AccessID1" | HardcodedCredentials.js:472:57:472:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:472:57:472:67 | "AccessID1" | key | +| HardcodedCredentials.js:473:53:473:63 | "AccessID1" | HardcodedCredentials.js:473:53:473:63 | "AccessID1" | HardcodedCredentials.js:473:53:473:63 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:473:53:473:63 | "AccessID1" | key | +| HardcodedCredentials.js:474:55:474:65 | "AccessID1" | HardcodedCredentials.js:474:55:474:65 | "AccessID1" | HardcodedCredentials.js:474:55:474:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:474:55:474:65 | "AccessID1" | key | +| HardcodedCredentials.js:475:47:475:57 | "AccessID1" | HardcodedCredentials.js:475:47:475:57 | "AccessID1" | HardcodedCredentials.js:475:47:475:57 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:475:47:475:57 | "AccessID1" | key | +| HardcodedCredentials.js:476:83:476:93 | "AccessID1" | HardcodedCredentials.js:476:83:476:93 | "AccessID1" | HardcodedCredentials.js:476:83:476:93 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:476:83:476:93 | "AccessID1" | key | +| HardcodedCredentials.js:477:67:477:77 | "AccessID1" | HardcodedCredentials.js:477:67:477:77 | "AccessID1" | HardcodedCredentials.js:477:67:477:77 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:477:67:477:77 | "AccessID1" | key | +| HardcodedCredentials.js:478:59:478:69 | "AccessID1" | HardcodedCredentials.js:478:59:478:69 | "AccessID1" | HardcodedCredentials.js:478:59:478:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:478:59:478:69 | "AccessID1" | key | +| HardcodedCredentials.js:479:43:479:53 | "AccessID1" | HardcodedCredentials.js:479:43:479:53 | "AccessID1" | HardcodedCredentials.js:479:43:479:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:479:43:479:53 | "AccessID1" | key | +| HardcodedCredentials.js:480:51:480:61 | "AccessID1" | HardcodedCredentials.js:480:51:480:61 | "AccessID1" | HardcodedCredentials.js:480:51:480:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:480:51:480:61 | "AccessID1" | key | +| HardcodedCredentials.js:481:69:481:79 | "AccessID1" | HardcodedCredentials.js:481:69:481:79 | "AccessID1" | HardcodedCredentials.js:481:69:481:79 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:481:69:481:79 | "AccessID1" | key | +| HardcodedCredentials.js:482:61:482:71 | "AccessID1" | HardcodedCredentials.js:482:61:482:71 | "AccessID1" | HardcodedCredentials.js:482:61:482:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:482:61:482:71 | "AccessID1" | key | +| HardcodedCredentials.js:483:57:483:67 | "AccessID1" | HardcodedCredentials.js:483:57:483:67 | "AccessID1" | HardcodedCredentials.js:483:57:483:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:483:57:483:67 | "AccessID1" | key | +| HardcodedCredentials.js:484:61:484:71 | "AccessID1" | HardcodedCredentials.js:484:61:484:71 | "AccessID1" | HardcodedCredentials.js:484:61:484:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:484:61:484:71 | "AccessID1" | key | +| HardcodedCredentials.js:485:45:485:55 | "AccessID1" | HardcodedCredentials.js:485:45:485:55 | "AccessID1" | HardcodedCredentials.js:485:45:485:55 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:485:45:485:55 | "AccessID1" | key | +| HardcodedCredentials.js:486:63:486:73 | "AccessID1" | HardcodedCredentials.js:486:63:486:73 | "AccessID1" | HardcodedCredentials.js:486:63:486:73 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:486:63:486:73 | "AccessID1" | key | +| HardcodedCredentials.js:487:43:487:53 | "AccessID1" | HardcodedCredentials.js:487:43:487:53 | "AccessID1" | HardcodedCredentials.js:487:43:487:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:487:43:487:53 | "AccessID1" | key | +| HardcodedCredentials.js:488:43:488:53 | "AccessID1" | HardcodedCredentials.js:488:43:488:53 | "AccessID1" | HardcodedCredentials.js:488:43:488:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:488:43:488:53 | "AccessID1" | key | +| HardcodedCredentials.js:489:43:489:53 | "AccessID1" | HardcodedCredentials.js:489:43:489:53 | "AccessID1" | HardcodedCredentials.js:489:43:489:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:489:43:489:53 | "AccessID1" | key | +| HardcodedCredentials.js:490:53:490:63 | "AccessID1" | HardcodedCredentials.js:490:53:490:63 | "AccessID1" | HardcodedCredentials.js:490:53:490:63 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:490:53:490:63 | "AccessID1" | key | +| HardcodedCredentials.js:491:47:491:57 | "AccessID1" | HardcodedCredentials.js:491:47:491:57 | "AccessID1" | HardcodedCredentials.js:491:47:491:57 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:491:47:491:57 | "AccessID1" | key | +| HardcodedCredentials.js:492:51:492:61 | "AccessID1" | HardcodedCredentials.js:492:51:492:61 | "AccessID1" | HardcodedCredentials.js:492:51:492:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:492:51:492:61 | "AccessID1" | key | +| HardcodedCredentials.js:493:51:493:61 | "AccessID1" | HardcodedCredentials.js:493:51:493:61 | "AccessID1" | HardcodedCredentials.js:493:51:493:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:493:51:493:61 | "AccessID1" | key | +| HardcodedCredentials.js:494:51:494:61 | "AccessID1" | HardcodedCredentials.js:494:51:494:61 | "AccessID1" | HardcodedCredentials.js:494:51:494:61 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:494:51:494:61 | "AccessID1" | key | +| HardcodedCredentials.js:495:57:495:67 | "AccessID1" | HardcodedCredentials.js:495:57:495:67 | "AccessID1" | HardcodedCredentials.js:495:57:495:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:495:57:495:67 | "AccessID1" | key | +| HardcodedCredentials.js:496:61:496:71 | "AccessID1" | HardcodedCredentials.js:496:61:496:71 | "AccessID1" | HardcodedCredentials.js:496:61:496:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:496:61:496:71 | "AccessID1" | key | +| HardcodedCredentials.js:497:55:497:65 | "AccessID1" | HardcodedCredentials.js:497:55:497:65 | "AccessID1" | HardcodedCredentials.js:497:55:497:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:497:55:497:65 | "AccessID1" | key | +| HardcodedCredentials.js:498:83:498:93 | "AccessID1" | HardcodedCredentials.js:498:83:498:93 | "AccessID1" | HardcodedCredentials.js:498:83:498:93 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:498:83:498:93 | "AccessID1" | key | +| HardcodedCredentials.js:499:59:499:69 | "AccessID1" | HardcodedCredentials.js:499:59:499:69 | "AccessID1" | HardcodedCredentials.js:499:59:499:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:499:59:499:69 | "AccessID1" | key | +| HardcodedCredentials.js:500:61:500:71 | "AccessID1" | HardcodedCredentials.js:500:61:500:71 | "AccessID1" | HardcodedCredentials.js:500:61:500:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:500:61:500:71 | "AccessID1" | key | +| HardcodedCredentials.js:501:55:501:65 | "AccessID1" | HardcodedCredentials.js:501:55:501:65 | "AccessID1" | HardcodedCredentials.js:501:55:501:65 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:501:55:501:65 | "AccessID1" | key | +| HardcodedCredentials.js:502:61:502:71 | "AccessID1" | HardcodedCredentials.js:502:61:502:71 | "AccessID1" | HardcodedCredentials.js:502:61:502:71 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:502:61:502:71 | "AccessID1" | key | +| HardcodedCredentials.js:503:57:503:67 | "AccessID1" | HardcodedCredentials.js:503:57:503:67 | "AccessID1" | HardcodedCredentials.js:503:57:503:67 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:503:57:503:67 | "AccessID1" | key | +| HardcodedCredentials.js:504:71:504:81 | "AccessID1" | HardcodedCredentials.js:504:71:504:81 | "AccessID1" | HardcodedCredentials.js:504:71:504:81 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:504:71:504:81 | "AccessID1" | key | +| HardcodedCredentials.js:505:59:505:69 | "AccessID1" | HardcodedCredentials.js:505:59:505:69 | "AccessID1" | HardcodedCredentials.js:505:59:505:69 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:505:59:505:69 | "AccessID1" | key | +| HardcodedCredentials.js:506:41:506:51 | "AccessID1" | HardcodedCredentials.js:506:41:506:51 | "AccessID1" | HardcodedCredentials.js:506:41:506:51 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:506:41:506:51 | "AccessID1" | key | +| HardcodedCredentials.js:507:43:507:53 | "AccessID1" | HardcodedCredentials.js:507:43:507:53 | "AccessID1" | HardcodedCredentials.js:507:43:507:53 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:507:43:507:53 | "AccessID1" | key | +| HardcodedCredentials.js:508:63:508:73 | "AccessID1" | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | The hard-coded value "AccessID1" is used as $@. | HardcodedCredentials.js:508:63:508:73 | "AccessID1" | key | +| HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | The hard-coded value "SOMEACCESSKEY" is used as $@. | HardcodedCredentials.js:510:30:510:44 | "SOMEACCESSKEY" | key | +| HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:511:34:511:43 | "hgfedcba" | key | +| HardcodedCredentials.js:514:9:514:23 | "SOMEACCESSKEY" | HardcodedCredentials.js:514:9:514:23 | "SOMEACCESSKEY" | HardcodedCredentials.js:514:9:514:23 | "SOMEACCESSKEY" | The hard-coded value "SOMEACCESSKEY" is used as $@. | HardcodedCredentials.js:514:9:514:23 | "SOMEACCESSKEY" | key | +| HardcodedCredentials.js:515:9:515:18 | "hgfedcba" | HardcodedCredentials.js:515:9:515:18 | "hgfedcba" | HardcodedCredentials.js:515:9:515:18 | "hgfedcba" | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:515:9:515:18 | "hgfedcba" | key | | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | The hard-coded value "SOMEACCESSKEY" is used as $@. | HardcodedCredentials.js:520:20:520:34 | "SOMEACCESSKEY" | user name | | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | The hard-coded value "hgfedcba" is used as $@. | HardcodedCredentials.js:521:24:521:33 | "hgfedcba" | password | | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | The hard-coded value "dbuser" is used as $@. | __tests__/HardcodedCredentialsDemo.js:5:15:5:22 | 'dbuser' | user name | From 0bb0b5c58759e0b334c39111eca76666794162c2 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Mon, 28 Apr 2025 14:13:14 +0200 Subject: [PATCH 112/336] C++: Add use-after-free FP tests --- .../tests/UseAfterFree/UseAfterFree.expected | 24 +++++++++++++++++ .../semmle/tests/UseAfterFree/test.cpp | 27 ++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-416/semmle/tests/UseAfterFree/UseAfterFree.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-416/semmle/tests/UseAfterFree/UseAfterFree.expected index 22cb3f2fe810..b7decda26517 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-416/semmle/tests/UseAfterFree/UseAfterFree.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-416/semmle/tests/UseAfterFree/UseAfterFree.expected @@ -11,6 +11,16 @@ edges | test.cpp:203:7:203:10 | pointer to free output argument | test.cpp:209:6:209:9 | data | provenance | | | test.cpp:207:8:207:11 | pointer to free output argument | test.cpp:209:6:209:9 | data | provenance | | | test.cpp:216:9:216:9 | pointer to operator delete output argument | test.cpp:217:6:217:6 | x | provenance | | +| test.cpp:243:7:243:7 | *s [post update] [i1, data] | test.cpp:248:6:248:6 | *s [i1, data] | provenance | | +| test.cpp:243:7:243:16 | pointer to free output argument | test.cpp:243:10:243:11 | *i1 [post update] [data] | provenance | | +| test.cpp:243:10:243:11 | *i1 [post update] [data] | test.cpp:243:7:243:7 | *s [post update] [i1, data] | provenance | | +| test.cpp:248:6:248:6 | *s [i1, data] | test.cpp:248:9:248:10 | *i1 [data] | provenance | | +| test.cpp:248:9:248:10 | *i1 [data] | test.cpp:248:12:248:15 | data | provenance | | +| test.cpp:250:7:250:7 | *s [post update] [*i2, data] | test.cpp:255:6:255:6 | *s [*i2, data] | provenance | | +| test.cpp:250:7:250:17 | pointer to free output argument | test.cpp:250:10:250:11 | *i2 [post update] [data] | provenance | | +| test.cpp:250:10:250:11 | *i2 [post update] [data] | test.cpp:250:7:250:7 | *s [post update] [*i2, data] | provenance | | +| test.cpp:255:6:255:6 | *s [*i2, data] | test.cpp:255:9:255:10 | *i2 [data] | provenance | | +| test.cpp:255:9:255:10 | *i2 [data] | test.cpp:255:13:255:16 | data | provenance | | nodes | test.cpp:39:7:39:10 | pointer to free output argument | semmle.label | pointer to free output argument | | test.cpp:41:6:41:9 | data | semmle.label | data | @@ -35,6 +45,18 @@ nodes | test.cpp:209:6:209:9 | data | semmle.label | data | | test.cpp:216:9:216:9 | pointer to operator delete output argument | semmle.label | pointer to operator delete output argument | | test.cpp:217:6:217:6 | x | semmle.label | x | +| test.cpp:243:7:243:7 | *s [post update] [i1, data] | semmle.label | *s [post update] [i1, data] | +| test.cpp:243:7:243:16 | pointer to free output argument | semmle.label | pointer to free output argument | +| test.cpp:243:10:243:11 | *i1 [post update] [data] | semmle.label | *i1 [post update] [data] | +| test.cpp:248:6:248:6 | *s [i1, data] | semmle.label | *s [i1, data] | +| test.cpp:248:9:248:10 | *i1 [data] | semmle.label | *i1 [data] | +| test.cpp:248:12:248:15 | data | semmle.label | data | +| test.cpp:250:7:250:7 | *s [post update] [*i2, data] | semmle.label | *s [post update] [*i2, data] | +| test.cpp:250:7:250:17 | pointer to free output argument | semmle.label | pointer to free output argument | +| test.cpp:250:10:250:11 | *i2 [post update] [data] | semmle.label | *i2 [post update] [data] | +| test.cpp:255:6:255:6 | *s [*i2, data] | semmle.label | *s [*i2, data] | +| test.cpp:255:9:255:10 | *i2 [data] | semmle.label | *i2 [data] | +| test.cpp:255:13:255:16 | data | semmle.label | data | subpaths #select | test.cpp:41:6:41:9 | data | test.cpp:39:7:39:10 | pointer to free output argument | test.cpp:41:6:41:9 | data | Memory may have been previously freed by $@. | test.cpp:39:2:39:5 | call to free | call to free | @@ -49,3 +71,5 @@ subpaths | test.cpp:209:6:209:9 | data | test.cpp:203:7:203:10 | pointer to free output argument | test.cpp:209:6:209:9 | data | Memory may have been previously freed by $@. | test.cpp:203:2:203:5 | call to free | call to free | | test.cpp:209:6:209:9 | data | test.cpp:207:8:207:11 | pointer to free output argument | test.cpp:209:6:209:9 | data | Memory may have been previously freed by $@. | test.cpp:207:3:207:6 | call to free | call to free | | test.cpp:217:6:217:6 | x | test.cpp:216:9:216:9 | pointer to operator delete output argument | test.cpp:217:6:217:6 | x | Memory may have been previously freed by $@. | test.cpp:216:2:216:9 | delete | delete | +| test.cpp:248:12:248:15 | data | test.cpp:243:7:243:16 | pointer to free output argument | test.cpp:248:12:248:15 | data | Memory may have been previously freed by $@. | test.cpp:243:2:243:5 | call to free | call to free | +| test.cpp:255:13:255:16 | data | test.cpp:250:7:250:17 | pointer to free output argument | test.cpp:255:13:255:16 | data | Memory may have been previously freed by $@. | test.cpp:250:2:250:5 | call to free | call to free | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-416/semmle/tests/UseAfterFree/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-416/semmle/tests/UseAfterFree/test.cpp index ad49eb6416fc..deac38663362 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-416/semmle/tests/UseAfterFree/test.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-416/semmle/tests/UseAfterFree/test.cpp @@ -134,7 +134,7 @@ void noReturnWrapper() { noReturn(); } void test9() { - char *data, *data2; + char *data; free(data); noReturnWrapper(); use_if_nonzero(data); // GOOD @@ -229,3 +229,28 @@ void regression_test_for_static_var_handling() data = (char *)malloc(100*sizeof(char)); use(data); // GOOD } + +struct myInnerStruct { + char *data; +}; + +struct myStruct { + myInnerStruct i1; + myInnerStruct *i2; +}; + +void malloc_after_free(myStruct *s) { + free(s->i1.data); + s->i1.data = (char *)malloc(100*sizeof(char)); + if (s->i1.data == 0) { + return; + } + use(s->i1.data); // GOOD [FALSE POSITIVE] + + free(s->i2->data); + s->i2->data = (char *)malloc(100*sizeof(char)); + if (s->i2->data == 0) { + return; + } + use(s->i2->data); // GOOD [FALSE POSITIVE] +} From 8b53f8f2a67cd456c48420c2ab950e506fa67c67 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Mon, 28 Apr 2025 12:21:21 +0200 Subject: [PATCH 113/336] Fix, prevent addHook return values from being treated as XSS sinks --- javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll index aaf1dbfdd770..cf8dd76b75e3 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll @@ -328,7 +328,11 @@ module Fastify { ResponseSendArgument() { this = rh.getAResponseSource().ref().getAMethodCall("send").getArgument(0) or - this = rh.(DataFlow::FunctionNode).getAReturn() + exists(RouteSetup setup | + rh = setup.getARouteHandler() and + this = rh.(DataFlow::FunctionNode).getAReturn() and + setup.getMethodName() != "addHook" + ) } override RouteHandler getRouteHandler() { result = rh } From 69bc12dd4fc8ba30f08be407a438773e61b9a225 Mon Sep 17 00:00:00 2001 From: Nick Rolfe Date: Mon, 28 Apr 2025 14:40:27 +0100 Subject: [PATCH 114/336] Fix spelling/wording in qhelp for rb/uninitialized-local-variable --- ruby/ql/src/queries/variables/UninitializedLocal.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ruby/ql/src/queries/variables/UninitializedLocal.md b/ruby/ql/src/queries/variables/UninitializedLocal.md index c99b24b11013..4dd3fce43041 100644 --- a/ruby/ql/src/queries/variables/UninitializedLocal.md +++ b/ruby/ql/src/queries/variables/UninitializedLocal.md @@ -2,14 +2,14 @@ ## Description In Ruby, it is not necessary to explicitly initialize variables. -If a local variable has not been explicitly initialized, it will have the value `nil`. If this happens unintended, though, the variable will not represent an object with the expected methods, and a method call on the variable will raise a `NoMethodError`. +If a local variable has not been explicitly initialized, it will have the value `nil`. If this happens unintentionally, though, the variable will not represent an object with the expected methods, and a method call on the variable will raise a `NoMethodError`. ## Recommendation -Ensure that the variable cannot be `nil` at the point hightligted by the alert. +Ensure that the variable cannot be `nil` at the point highlighted by the alert. This can be achieved by using a safe navigation or adding a check for `nil`. -Note: You do not need to explicitly initialize the variable, if you can make the program deal with the possible `nil` value. In particular, initializing the variable to `nil` will have no effect, as this is already the value of the variable. If `nil` is the only possibly default value, you need to handle the `nil` value instead of initializing the variable. +Note: You do not need to explicitly initialize the variable, if you can make the program deal with the possible `nil` value. In particular, initializing the variable to `nil` will have no effect, as this is already the value of the variable. If `nil` is the only possible default value, you need to handle the `nil` value instead of initializing the variable. ## Examples From 2e0699ab2b4aae114eab0929488923ea6f6a2868 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 28 Apr 2025 14:03:28 +0000 Subject: [PATCH 115/336] Post-release preparation for codeql-cli-2.21.2 --- actions/ql/lib/qlpack.yml | 2 +- actions/ql/src/qlpack.yml | 2 +- cpp/ql/lib/qlpack.yml | 2 +- cpp/ql/src/qlpack.yml | 2 +- csharp/ql/campaigns/Solorigate/lib/qlpack.yml | 2 +- csharp/ql/campaigns/Solorigate/src/qlpack.yml | 2 +- csharp/ql/lib/qlpack.yml | 2 +- csharp/ql/src/qlpack.yml | 2 +- go/ql/consistency-queries/qlpack.yml | 2 +- go/ql/lib/qlpack.yml | 2 +- go/ql/src/qlpack.yml | 2 +- java/ql/lib/qlpack.yml | 2 +- java/ql/src/qlpack.yml | 2 +- javascript/ql/lib/qlpack.yml | 2 +- javascript/ql/src/qlpack.yml | 2 +- misc/suite-helpers/qlpack.yml | 2 +- python/ql/lib/qlpack.yml | 2 +- python/ql/src/qlpack.yml | 2 +- ruby/ql/lib/qlpack.yml | 2 +- ruby/ql/src/qlpack.yml | 2 +- rust/ql/lib/qlpack.yml | 2 +- rust/ql/src/qlpack.yml | 2 +- shared/controlflow/qlpack.yml | 2 +- shared/dataflow/qlpack.yml | 2 +- shared/mad/qlpack.yml | 2 +- shared/rangeanalysis/qlpack.yml | 2 +- shared/regex/qlpack.yml | 2 +- shared/ssa/qlpack.yml | 2 +- shared/threat-models/qlpack.yml | 2 +- shared/tutorial/qlpack.yml | 2 +- shared/typeflow/qlpack.yml | 2 +- shared/typeinference/qlpack.yml | 2 +- shared/typetracking/qlpack.yml | 2 +- shared/typos/qlpack.yml | 2 +- shared/util/qlpack.yml | 2 +- shared/xml/qlpack.yml | 2 +- shared/yaml/qlpack.yml | 2 +- swift/ql/lib/qlpack.yml | 2 +- swift/ql/src/qlpack.yml | 2 +- 39 files changed, 39 insertions(+), 39 deletions(-) diff --git a/actions/ql/lib/qlpack.yml b/actions/ql/lib/qlpack.yml index d4598e6cdfb3..81973859a2bc 100644 --- a/actions/ql/lib/qlpack.yml +++ b/actions/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/actions-all -version: 0.4.8 +version: 0.4.9-dev library: true warnOnImplicitThis: true dependencies: diff --git a/actions/ql/src/qlpack.yml b/actions/ql/src/qlpack.yml index 242fd24d7289..942c10d3bcfa 100644 --- a/actions/ql/src/qlpack.yml +++ b/actions/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/actions-queries -version: 0.6.0 +version: 0.6.1-dev library: false warnOnImplicitThis: true groups: [actions, queries] diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index 81d4e6e33395..109eb3bf0cc1 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-all -version: 4.3.0 +version: 4.3.1-dev groups: cpp dbscheme: semmlecode.cpp.dbscheme extractor: cpp diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml index 6466daf58cc2..b911fdb21934 100644 --- a/cpp/ql/src/qlpack.yml +++ b/cpp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-queries -version: 1.3.9 +version: 1.3.10-dev groups: - cpp - queries diff --git a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml index 00e256471506..e39ac3a9763b 100644 --- a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-all -version: 1.7.39 +version: 1.7.40-dev groups: - csharp - solorigate diff --git a/csharp/ql/campaigns/Solorigate/src/qlpack.yml b/csharp/ql/campaigns/Solorigate/src/qlpack.yml index 38faa5645955..bc910490374b 100644 --- a/csharp/ql/campaigns/Solorigate/src/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-queries -version: 1.7.39 +version: 1.7.40-dev groups: - csharp - solorigate diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml index 2c840d1a3f6a..632931bcd7e3 100644 --- a/csharp/ql/lib/qlpack.yml +++ b/csharp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-all -version: 5.1.5 +version: 5.1.6-dev groups: csharp dbscheme: semmlecode.csharp.dbscheme extractor: csharp diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index a58388ec20d9..664f83f6980c 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-queries -version: 1.1.2 +version: 1.1.3-dev groups: - csharp - queries diff --git a/go/ql/consistency-queries/qlpack.yml b/go/ql/consistency-queries/qlpack.yml index a414966bc9de..e09a33e17f57 100644 --- a/go/ql/consistency-queries/qlpack.yml +++ b/go/ql/consistency-queries/qlpack.yml @@ -1,5 +1,5 @@ name: codeql-go-consistency-queries -version: 1.0.22 +version: 1.0.23-dev groups: - go - queries diff --git a/go/ql/lib/qlpack.yml b/go/ql/lib/qlpack.yml index ac6ccfb48820..8367d8c5dee6 100644 --- a/go/ql/lib/qlpack.yml +++ b/go/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-all -version: 4.2.4 +version: 4.2.5-dev groups: go dbscheme: go.dbscheme extractor: go diff --git a/go/ql/src/qlpack.yml b/go/ql/src/qlpack.yml index 3618a9b59bad..2cd2db243850 100644 --- a/go/ql/src/qlpack.yml +++ b/go/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-queries -version: 1.1.13 +version: 1.1.14-dev groups: - go - queries diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index c6c8a86440fe..1acaa5702377 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-all -version: 7.1.4 +version: 7.1.5-dev groups: java dbscheme: config/semmlecode.dbscheme extractor: java diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index d6908853bc1b..d077b42e4433 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-queries -version: 1.4.2 +version: 1.4.3-dev groups: - java - queries diff --git a/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml index b9716f1bc572..36814d319281 100644 --- a/javascript/ql/lib/qlpack.yml +++ b/javascript/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-all -version: 2.6.2 +version: 2.6.3-dev groups: javascript dbscheme: semmlecode.javascript.dbscheme extractor: javascript diff --git a/javascript/ql/src/qlpack.yml b/javascript/ql/src/qlpack.yml index 3a539acdf6fd..288baf974d3c 100644 --- a/javascript/ql/src/qlpack.yml +++ b/javascript/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-queries -version: 1.5.4 +version: 1.5.5-dev groups: - javascript - queries diff --git a/misc/suite-helpers/qlpack.yml b/misc/suite-helpers/qlpack.yml index 12c9234e4590..06c89edc7723 100644 --- a/misc/suite-helpers/qlpack.yml +++ b/misc/suite-helpers/qlpack.yml @@ -1,4 +1,4 @@ name: codeql/suite-helpers -version: 1.0.22 +version: 1.0.23-dev groups: shared warnOnImplicitThis: true diff --git a/python/ql/lib/qlpack.yml b/python/ql/lib/qlpack.yml index 03b7a3e54be4..78eec8158e86 100644 --- a/python/ql/lib/qlpack.yml +++ b/python/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-all -version: 4.0.6 +version: 4.0.7-dev groups: python dbscheme: semmlecode.python.dbscheme extractor: python diff --git a/python/ql/src/qlpack.yml b/python/ql/src/qlpack.yml index 5dd9400dab3e..a1c976dfdfae 100644 --- a/python/ql/src/qlpack.yml +++ b/python/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-queries -version: 1.4.8 +version: 1.4.9-dev groups: - python - queries diff --git a/ruby/ql/lib/qlpack.yml b/ruby/ql/lib/qlpack.yml index 6ecaf5163c63..bb7cfb00c9b4 100644 --- a/ruby/ql/lib/qlpack.yml +++ b/ruby/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-all -version: 4.1.5 +version: 4.1.6-dev groups: ruby extractor: ruby dbscheme: ruby.dbscheme diff --git a/ruby/ql/src/qlpack.yml b/ruby/ql/src/qlpack.yml index 0419cb30b2fa..b2f8b36fc8a8 100644 --- a/ruby/ql/src/qlpack.yml +++ b/ruby/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-queries -version: 1.2.1 +version: 1.2.2-dev groups: - ruby - queries diff --git a/rust/ql/lib/qlpack.yml b/rust/ql/lib/qlpack.yml index 0955915fefda..9b7b15b43faf 100644 --- a/rust/ql/lib/qlpack.yml +++ b/rust/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/rust-all -version: 0.1.7 +version: 0.1.8-dev groups: rust extractor: rust dbscheme: rust.dbscheme diff --git a/rust/ql/src/qlpack.yml b/rust/ql/src/qlpack.yml index a1e5f32bd206..b1a919d02eb6 100644 --- a/rust/ql/src/qlpack.yml +++ b/rust/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/rust-queries -version: 0.1.7 +version: 0.1.8-dev groups: - rust - queries diff --git a/shared/controlflow/qlpack.yml b/shared/controlflow/qlpack.yml index e1a757c8fa08..70edae6befd5 100644 --- a/shared/controlflow/qlpack.yml +++ b/shared/controlflow/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/controlflow -version: 2.0.6 +version: 2.0.7-dev groups: shared library: true dependencies: diff --git a/shared/dataflow/qlpack.yml b/shared/dataflow/qlpack.yml index 1582f9999b62..de4dfb3dfe0e 100644 --- a/shared/dataflow/qlpack.yml +++ b/shared/dataflow/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/dataflow -version: 2.0.6 +version: 2.0.7-dev groups: shared library: true dependencies: diff --git a/shared/mad/qlpack.yml b/shared/mad/qlpack.yml index 7e0e982ac709..d1e4d3fd45e6 100644 --- a/shared/mad/qlpack.yml +++ b/shared/mad/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/mad -version: 1.0.22 +version: 1.0.23-dev groups: shared library: true dependencies: diff --git a/shared/rangeanalysis/qlpack.yml b/shared/rangeanalysis/qlpack.yml index d071cdb31a2f..ccb83d389295 100644 --- a/shared/rangeanalysis/qlpack.yml +++ b/shared/rangeanalysis/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/rangeanalysis -version: 1.0.22 +version: 1.0.23-dev groups: shared library: true dependencies: diff --git a/shared/regex/qlpack.yml b/shared/regex/qlpack.yml index 9d6f8e822a17..763f7edc7433 100644 --- a/shared/regex/qlpack.yml +++ b/shared/regex/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/regex -version: 1.0.22 +version: 1.0.23-dev groups: shared library: true dependencies: diff --git a/shared/ssa/qlpack.yml b/shared/ssa/qlpack.yml index 3a5ec8c5496d..2010bbe1e12e 100644 --- a/shared/ssa/qlpack.yml +++ b/shared/ssa/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ssa -version: 1.1.1 +version: 1.1.2-dev groups: shared library: true dependencies: diff --git a/shared/threat-models/qlpack.yml b/shared/threat-models/qlpack.yml index 464d5a7e2624..7b0cad6d5f99 100644 --- a/shared/threat-models/qlpack.yml +++ b/shared/threat-models/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/threat-models -version: 1.0.22 +version: 1.0.23-dev library: true groups: shared dataExtensions: diff --git a/shared/tutorial/qlpack.yml b/shared/tutorial/qlpack.yml index f25d695e7735..3ae10d7b4a1b 100644 --- a/shared/tutorial/qlpack.yml +++ b/shared/tutorial/qlpack.yml @@ -1,7 +1,7 @@ name: codeql/tutorial description: Library for the CodeQL detective tutorials, helping new users learn to write CodeQL queries. -version: 1.0.22 +version: 1.0.23-dev groups: shared library: true warnOnImplicitThis: true diff --git a/shared/typeflow/qlpack.yml b/shared/typeflow/qlpack.yml index 9a1264adac4d..85f2c86741d2 100644 --- a/shared/typeflow/qlpack.yml +++ b/shared/typeflow/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/typeflow -version: 1.0.22 +version: 1.0.23-dev groups: shared library: true dependencies: diff --git a/shared/typeinference/qlpack.yml b/shared/typeinference/qlpack.yml index 0ac8eba3de12..d949e23fe0fa 100644 --- a/shared/typeinference/qlpack.yml +++ b/shared/typeinference/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/typeinference -version: 0.0.3 +version: 0.0.4-dev groups: shared library: true dependencies: diff --git a/shared/typetracking/qlpack.yml b/shared/typetracking/qlpack.yml index d5ceed7f6aed..924fd143829d 100644 --- a/shared/typetracking/qlpack.yml +++ b/shared/typetracking/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/typetracking -version: 2.0.6 +version: 2.0.7-dev groups: shared library: true dependencies: diff --git a/shared/typos/qlpack.yml b/shared/typos/qlpack.yml index ad67983a2a2f..21912e1efdfa 100644 --- a/shared/typos/qlpack.yml +++ b/shared/typos/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/typos -version: 1.0.22 +version: 1.0.23-dev groups: shared library: true warnOnImplicitThis: true diff --git a/shared/util/qlpack.yml b/shared/util/qlpack.yml index 0b56fe498f80..e14572c562a8 100644 --- a/shared/util/qlpack.yml +++ b/shared/util/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/util -version: 2.0.9 +version: 2.0.10-dev groups: shared library: true dependencies: null diff --git a/shared/xml/qlpack.yml b/shared/xml/qlpack.yml index da24a6ce78aa..bfac4d918413 100644 --- a/shared/xml/qlpack.yml +++ b/shared/xml/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/xml -version: 1.0.22 +version: 1.0.23-dev groups: shared library: true dependencies: diff --git a/shared/yaml/qlpack.yml b/shared/yaml/qlpack.yml index 318094b9d40b..7aed9bae5e95 100644 --- a/shared/yaml/qlpack.yml +++ b/shared/yaml/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/yaml -version: 1.0.22 +version: 1.0.23-dev groups: shared library: true warnOnImplicitThis: true diff --git a/swift/ql/lib/qlpack.yml b/swift/ql/lib/qlpack.yml index ac76e2e270b4..667ce5588c8e 100644 --- a/swift/ql/lib/qlpack.yml +++ b/swift/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/swift-all -version: 4.2.0 +version: 4.2.1-dev groups: swift extractor: swift dbscheme: swift.dbscheme diff --git a/swift/ql/src/qlpack.yml b/swift/ql/src/qlpack.yml index 39e1f65a2c10..482affb8e16d 100644 --- a/swift/ql/src/qlpack.yml +++ b/swift/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/swift-queries -version: 1.1.2 +version: 1.1.3-dev groups: - swift - queries From 28ccc833464e64d3e5dbdc5fd34c7fb59bde3bbb Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 28 Apr 2025 11:33:37 -0400 Subject: [PATCH 116/336] Adding a means to distinguish asymmetric algorithms. --- shared/cryptography/codeql/cryptography/Model.qll | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 510f334bc626..1ea862b470d2 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -2122,6 +2122,12 @@ module CryptographyBase Input> { */ KeyOpAlg::Algorithm getAlgorithmType() { result = instance.asAlg().getAlgorithmType() } + predicate isAsymmetric() { + this.getAlgorithmType() instanceof KeyOpAlg::TAsymmetricCipher + or + this.getAlgorithmType() instanceof KeyOpAlg::TSignature + } + /** * Gets the mode of operation of this cipher, e.g., "GCM" or "CBC". */ @@ -2442,4 +2448,11 @@ module CryptographyBase Input> { location = this.getLocation() } } + + predicate isAsymmetricAlgorithm(AlgorithmNode node) { + node instanceof EllipticCurveNode + or + node instanceof KeyOperationAlgorithmNode and node.(KeyOperationAlgorithmNode).isAsymmetric() + // TODO: get unknown algorithms from known asymmetric operations + } } From fdd09a4dbffafa8e5e1e5ff08589f117b706980a Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 28 Apr 2025 11:34:16 -0400 Subject: [PATCH 117/336] Adding a new means for determining if there is nonce reuse. --- .../InventoryFilters/ArtifactReuse.qll | 70 +++++++++++++++++++ .../Quantum/InventoryFilters/ReusedNonce.ql | 12 ++++ .../Quantum/PossibleReusedNonce.ql | 36 ---------- 3 files changed, 82 insertions(+), 36 deletions(-) create mode 100644 java/ql/src/experimental/Quantum/InventoryFilters/ArtifactReuse.qll create mode 100644 java/ql/src/experimental/Quantum/InventoryFilters/ReusedNonce.ql delete mode 100644 java/ql/src/experimental/Quantum/PossibleReusedNonce.ql diff --git a/java/ql/src/experimental/Quantum/InventoryFilters/ArtifactReuse.qll b/java/ql/src/experimental/Quantum/InventoryFilters/ArtifactReuse.qll new file mode 100644 index 000000000000..de283f89775e --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventoryFilters/ArtifactReuse.qll @@ -0,0 +1,70 @@ +import java +import semmle.code.java.dataflow.DataFlow +import experimental.Quantum.Language + +/** + * Flow from any function that appears to return a value + * to an artifact node. + * NOTE: TODO: need to handle call by refernece for now. Need to re-evaluate (see notes below) + * Such functions may be 'wrappers' for some derived value. + */ +private module WrapperConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + exists(Call c | + c = source.asExpr() + // not handling references yet, I think we want to flat say references are only ok + // if I know the source, otherwise, it has to be through an additional flow step, which + // we filter as a source, i.e., references are only allowed as sources only, + // no inferrece? Not sure if that would work + //or + // source.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = c.getAnArgument() + ) and + // Filter out sources that are known additional flow steps, as these are likely not the + // kind of wrapper source we are looking for. + not exists(AdditionalFlowInputStep s | s.getOutput() = source) + } + + // Flow through additional flow steps + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + node1.(AdditionalFlowInputStep).getOutput() = node2 + } + + predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(Crypto::ArtifactNode i).asElement() } +} + +module WrapperFlow = DataFlow::Global; + +/** + * Using a set approach to determine if reuse of an artifact exists. + * This predicate produces a set of 'wrappers' that flow to the artifact node. + * This set can be compared with the set to another artifact node to determine if they are the same. + */ +private DataFlow::Node getWrapperSet(Crypto::NonceArtifactNode a) { + WrapperFlow::flow(result, DataFlow::exprNode(a.asElement())) + or + result.asExpr() = a.getSourceElement() +} + +/** + * Two different artifact nodes are considered reuse if any of the following conditions are met: + * 1. The source for artifact `a` and artifact `b` are the same and the source is a literal. + * 2. The source for artifact `a` and artifact `b` are not the same and the source is a literal of the same value. + * 3. For all 'wrappers' that return the source of artifact `a`, and that wrapper also exists for artifact `b`. + * 4. For all 'wrappers' that return the source of artifact `b`, and that wrapper also exists for artifact `a`. + */ +predicate isArtifactReuse(Crypto::ArtifactNode a, Crypto::ArtifactNode b) { + a != b and + ( + a.getSourceElement() = b.getSourceElement() and a.getSourceElement() instanceof Literal + or + a.getSourceElement().(Literal).getValue() = b.getSourceElement().(Literal).getValue() + or + forex(DataFlow::Node e | e = getWrapperSet(a) | + exists(DataFlow::Node e2 | e2 = getWrapperSet(b) | e = e2) + ) + or + forex(DataFlow::Node e | e = getWrapperSet(b) | + exists(DataFlow::Node e2 | e2 = getWrapperSet(a) | e = e2) + ) + ) +} diff --git a/java/ql/src/experimental/Quantum/InventoryFilters/ReusedNonce.ql b/java/ql/src/experimental/Quantum/InventoryFilters/ReusedNonce.ql new file mode 100644 index 000000000000..d8adccace557 --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventoryFilters/ReusedNonce.ql @@ -0,0 +1,12 @@ +/** + * @name Detects reuse of the same nonce in multiple operations + * @id java/crypto_inventory_filter/nonce_reuse + * @kind problem + */ + +import java +import ArtifactReuse + +from Crypto::NonceArtifactNode nonce1, Crypto::NonceArtifactNode nonce2 +where isArtifactReuse(nonce1, nonce2) +select nonce1, "Reuse with nonce $@", nonce2, nonce2.toString() diff --git a/java/ql/src/experimental/Quantum/PossibleReusedNonce.ql b/java/ql/src/experimental/Quantum/PossibleReusedNonce.ql deleted file mode 100644 index 2263f05d56eb..000000000000 --- a/java/ql/src/experimental/Quantum/PossibleReusedNonce.ql +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @name Possible Nonce Reuse: Produces false positives if reuse occurs in a source that is a re-entry point. - * @id java/possible-nonce-reuse - * @kind problem - */ - -import experimental.Quantum.Language -import semmle.code.java.dataflow.DataFlow - -from - Crypto::KeyOperationNode op1, Crypto::KeyOperationNode op2, Crypto::NonceArtifactNode nonce1, - Crypto::NonceArtifactNode nonce2, Crypto::FlowAwareElement src1, Crypto::FlowAwareElement src2 -where - // NOTE: not looking at value of the nonce, if we knew value, it would be insecure (hard coded) - // Instead trying to find nonce sources that trace to multiple operations. - // Only looking for encryption operations, presumably if reuse for decryption either wouldn't be observable - // (the encryption happened else where) or we are able to see the encryption and decryption operation and - // reuse for encryption is the concern) - ( - op1.getKeyOperationSubtype() instanceof Crypto::EncryptionSubtype or - op1.getKeyOperationSubtype() instanceof Crypto::WrapSubtype or - op1.getKeyOperationSubtype() instanceof Crypto::UnknownCipherOperationSubtype - ) and - ( - op2.getKeyOperationSubtype() instanceof Crypto::EncryptionSubtype or - op2.getKeyOperationSubtype() instanceof Crypto::WrapSubtype or - op2.getKeyOperationSubtype() instanceof Crypto::UnknownCipherOperationSubtype - ) and - nonce1 = op1.getANonce() and - nonce2 = op2.getANonce() and - op1 != op2 and - nonce1.getSourceElement() = src1 and - nonce2.getSourceElement() = src2 and - src1 = src2 -// TODO: need to clarify that a reuse in a non-finalize is ok, need to check if 'finalize' through a modeled predicate -select op1, "Operation has a possible reused nonce with source $@", src1, src1.toString() From 7b7ed61beb039071e32a263921d38714329b59e0 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 28 Apr 2025 11:34:32 -0400 Subject: [PATCH 118/336] Adding an asymmetric algorithm slice. --- .../Quantum/InventorySlices/AsymmetricAlgorithm.ql | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 java/ql/src/experimental/Quantum/InventorySlices/AsymmetricAlgorithm.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/AsymmetricAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/AsymmetricAlgorithm.ql new file mode 100644 index 000000000000..1d4519784007 --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventorySlices/AsymmetricAlgorithm.ql @@ -0,0 +1,12 @@ +/** + * @name Detects known uses of asymmetric algorithms + * @id java/crypto_inventory_slices/known_asymmetric_algorithm + * @kind problem + */ + +import java +import experimental.Quantum.Language + +from Crypto::AlgorithmNode a +where Crypto::isAsymmetricAlgorithm(a) +select a, "Instance of asymmetric algorithm " + a.getAlgorithmName() From b91a2cc1594c7a69d1d18a11c00c4f7d825b8342 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 28 Apr 2025 17:36:37 +0100 Subject: [PATCH 119/336] Shared: Use 'isSink/1' in 'PropagateFlowConfig'. --- .../mad/modelgenerator/internal/ModelGeneratorImpl.qll | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll b/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll index 27521b31d00b..b9592964f931 100644 --- a/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll +++ b/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll @@ -484,10 +484,14 @@ module MakeModelGenerator< } predicate isSink(DataFlow::Node sink, FlowState state) { + // Sinks are provided by `isSink/1` + none() + } + + predicate isSink(DataFlow::Node sink) { sink instanceof ReturnNodeExt and not isOwnInstanceAccessNode(sink) and - not exists(captureQualifierFlow(getAsExprEnclosingCallable(sink))) and - (state instanceof TaintRead or state instanceof TaintStore) + not exists(captureQualifierFlow(getAsExprEnclosingCallable(sink))) } predicate isAdditionalFlowStep( From 1fd7643ab3ad1f2b15817ca0839e67ae69129cec Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 28 Apr 2025 14:54:38 -0400 Subject: [PATCH 120/336] Adding example slicing queries. --- .../KnownAsymmetricAlgorithm.ql | 12 ++++++++++ .../KnownAsymmetricOperationAlgorithm.ql | 12 ++++++++++ .../KnownEllipticCurveAlgorithm.ql | 11 ++++++++++ .../InventorySlices/KnownHashingAlgorithm.ql | 11 ++++++++++ .../InventorySlices/KnownHashingOperation.ql | 11 ++++++++++ .../KnownHashingOperationAlgorithm.ql | 12 ++++++++++ .../KnownKeyDerivationAlgorithm.ql | 11 ++++++++++ .../KnownKeyDerivationOperation.ql | 11 ++++++++++ .../KnownKeyDerivationOperationAlgorithm.ql | 12 ++++++++++ .../LikelyCryptoAPIFunction.ql | 16 ++++++++++++++ .../UnknownOperationAlgorithm.ql | 22 +++++++++++++++++++ 11 files changed, 141 insertions(+) create mode 100644 java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricAlgorithm.ql create mode 100644 java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql create mode 100644 java/ql/src/experimental/Quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql create mode 100644 java/ql/src/experimental/Quantum/InventorySlices/KnownHashingAlgorithm.ql create mode 100644 java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperation.ql create mode 100644 java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperationAlgorithm.ql create mode 100644 java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql create mode 100644 java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperation.ql create mode 100644 java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql create mode 100644 java/ql/src/experimental/Quantum/InventorySlices/LikelyCryptoAPIFunction.ql create mode 100644 java/ql/src/experimental/Quantum/InventorySlices/UnknownOperationAlgorithm.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricAlgorithm.ql new file mode 100644 index 000000000000..1e5a7c5bced1 --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricAlgorithm.ql @@ -0,0 +1,12 @@ +/** + * @name Detects known asymmetric algorithms + * @id java/crypto_inventory_slices/known_asymmetric_algorithm + * @kind problem + */ + +import java +import experimental.Quantum.Language + +from Crypto::AlgorithmNode a +where Crypto::isKnownAsymmetricAlgorithm(a) +select a, "Instance of asymmetric algorithm " + a.getAlgorithmName() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql new file mode 100644 index 000000000000..0900401b80d7 --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql @@ -0,0 +1,12 @@ +/** + * @name Detects operations where the algorithm applied is a known asymmetric algorithms + * @id java/crypto_inventory_slices/known_asymmetric_operation_algorithm + * @kind problem + */ + +import java +import experimental.Quantum.Language + +from Crypto::OperationNode op, Crypto::AlgorithmNode a +where a = op.getAKnownAlgorithm() and Crypto::isKnownAsymmetricAlgorithm(a) +select op, "Operation using asymmetric algorithm $@", a, a.getAlgorithmName() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql new file mode 100644 index 000000000000..0112e9d96dff --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql @@ -0,0 +1,11 @@ +/** + * @name Detects known elliptic curve algorithms + * @id java/crypto_inventory_slices/known_elliptic_curvee_algorithm + * @kind problem + */ + +import java +import experimental.Quantum.Language + +from Crypto::EllipticCurveNode a +select a, "Instance of elliptic curve algorithm " + a.getAlgorithmName() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingAlgorithm.ql new file mode 100644 index 000000000000..632872725e71 --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingAlgorithm.ql @@ -0,0 +1,11 @@ +/** + * @name Detects algorithms that are known hashing algorithms + * @id java/crypto_inventory_slices/known_hashing_algorithm + * @kind problem + */ + +import java +import experimental.Quantum.Language + +from Crypto::HashAlgorithmNode a +select a, "Instance of hashing algorithm " + a.getAlgorithmName() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperation.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperation.ql new file mode 100644 index 000000000000..b3556393173d --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperation.ql @@ -0,0 +1,11 @@ +/** + * @name Detects uses of hashing operations (operations exlicitly for hashing only, irrespective of the algorithm used) + * @id java/crypto_inventory_slices/known_hashing_operation + * @kind problem + */ + +import java +import experimental.Quantum.Language + +from Crypto::HashOperationNode op +select op, "Known hashing operation" diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperationAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperationAlgorithm.ql new file mode 100644 index 000000000000..ce0f4d37d4d1 --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperationAlgorithm.ql @@ -0,0 +1,12 @@ +/** + * @name Detects operations where the algorithm applied is a known hashing algorithm + * @id java/crypto_inventory_slices/operation_with_known_hashing_algorithm + * @kind problem + */ + +import java +import experimental.Quantum.Language + +from Crypto::OperationNode op, Crypto::HashAlgorithmNode a +where a = op.getAKnownAlgorithm() +select op, "Operation using hashing algorithm $@", a, a.getAlgorithmName() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql new file mode 100644 index 000000000000..584ffef0bbfa --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql @@ -0,0 +1,11 @@ +/** + * @name Detects known key derivation algorithms + * @id java/crypto_inventory_slices/known_key_derivation_algorithm + * @kind problem + */ + +import java +import experimental.Quantum.Language + +from Crypto::KeyDerivationAlgorithmNode alg +select alg, "Known key derivation algorithm " + alg.getAlgorithmName() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperation.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperation.ql new file mode 100644 index 000000000000..8c77b2aa984d --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperation.ql @@ -0,0 +1,11 @@ +/** + * @name Detects uses of key derivation operations (operations exlicitly for key derivation only, irrespective of the algorithm used) + * @id java/crypto_inventory_slices/known_key_derivation_operation + * @kind problem + */ + +import java +import experimental.Quantum.Language + +from Crypto::KeyDerivationOperationNode op +select op, "Known key derivation operation" diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql new file mode 100644 index 000000000000..cf9a4e96f4da --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql @@ -0,0 +1,12 @@ +/** + * @name Detects operations where the algorithm applied is a known key derivation algorithm + * @id java/crypto_inventory_slices/operation_with_known_key_derivation_algorithm + * @kind problem + */ + +import java +import experimental.Quantum.Language + +from Crypto::OperationNode op, Crypto::KeyDerivationAlgorithmNode a +where a = op.getAKnownAlgorithm() +select op, "Operation using key derivation algorithm $@", a, a.getAlgorithmName() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/LikelyCryptoAPIFunction.ql b/java/ql/src/experimental/Quantum/InventorySlices/LikelyCryptoAPIFunction.ql new file mode 100644 index 000000000000..0076c478dec9 --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventorySlices/LikelyCryptoAPIFunction.ql @@ -0,0 +1,16 @@ +/** + * @name Detects functions that take in crypto configuration parameters but calls are not detected in source. + * @id java/crypto_inventory_slices/likely_crypto_api_function + * @kind problem + */ + +import java +import experimental.Quantum.Language + +from Callable f, Parameter p, Crypto::OperationNode op +where + op.asElement().(Expr).getEnclosingCallable() = f and + op.getAnAlgorithmOrGenericSource().asElement() = p +select f, + "Likely crypto API function: Operation $@ configured by parameter $@ with no known configuring call", + op, op.toString(), p, p.toString() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/UnknownOperationAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/UnknownOperationAlgorithm.ql new file mode 100644 index 000000000000..61a27c75dac2 --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventorySlices/UnknownOperationAlgorithm.ql @@ -0,0 +1,22 @@ +/** + * @name Detects operations where the algorithm applied is unknown + * @id java/crypto_inventory_slices/unknown_operation_algorithm + * @kind problem + */ + +import java +import experimental.Quantum.Language + +//TODO: can we have an unknown node concept? +from Crypto::OperationNode op, Element e, string msg +where + not exists(op.getAnAlgorithmOrGenericSource()) and + e = op.asElement() and + msg = "Operation with unconfigured algorithm (no known sources)." + or + exists(Crypto::GenericSourceNode n | + n = op.getAnAlgorithmOrGenericSource() and + e = n.asElement() + ) and + msg = "Operation with unknown algorithm source: $@" +select op, msg, e, e.toString() From 5a8bffac11d352f02e83219d24d357021368ef7b Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 28 Apr 2025 14:56:08 -0400 Subject: [PATCH 121/336] Removing old asymmetric algorithm slice --- .../Quantum/InventorySlices/AsymmetricAlgorithm.ql | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 java/ql/src/experimental/Quantum/InventorySlices/AsymmetricAlgorithm.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/AsymmetricAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/AsymmetricAlgorithm.ql deleted file mode 100644 index 1d4519784007..000000000000 --- a/java/ql/src/experimental/Quantum/InventorySlices/AsymmetricAlgorithm.ql +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @name Detects known uses of asymmetric algorithms - * @id java/crypto_inventory_slices/known_asymmetric_algorithm - * @kind problem - */ - -import java -import experimental.Quantum.Language - -from Crypto::AlgorithmNode a -where Crypto::isAsymmetricAlgorithm(a) -select a, "Instance of asymmetric algorithm " + a.getAlgorithmName() From ce3eabf05ac98a255ccddf483ae9b1b120b1a120 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 28 Apr 2025 14:56:28 -0400 Subject: [PATCH 122/336] Updating model to support slicing. --- shared/cryptography/codeql/cryptography/Model.qll | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 1ea862b470d2..704be38362bf 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -1249,7 +1249,7 @@ module CryptographyBase Input> { /** * A generic source node is a source of data that is not resolvable to a specific asset. */ - private class GenericSourceNode extends NodeBase, TGenericSourceNode { + final class GenericSourceNode extends NodeBase, TGenericSourceNode { GenericSourceInstance instance; GenericSourceNode() { this = TGenericSourceNode(instance) } @@ -2449,10 +2449,9 @@ module CryptographyBase Input> { } } - predicate isAsymmetricAlgorithm(AlgorithmNode node) { + predicate isKnownAsymmetricAlgorithm(AlgorithmNode node) { node instanceof EllipticCurveNode or node instanceof KeyOperationAlgorithmNode and node.(KeyOperationAlgorithmNode).isAsymmetric() - // TODO: get unknown algorithms from known asymmetric operations } } From 219476cee01bb9042945345f1d08f19f959ba731 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 28 Apr 2025 15:47:58 -0400 Subject: [PATCH 123/336] Adding KDF iteration count inventory filters. --- .../KnownWeakKDFIterationCount.ql | 15 +++++++++++++++ .../UnknownKDFIterationCount.ql | 19 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 java/ql/src/experimental/Quantum/InventoryFilters/KnownWeakKDFIterationCount.ql create mode 100644 java/ql/src/experimental/Quantum/InventoryFilters/UnknownKDFIterationCount.ql diff --git a/java/ql/src/experimental/Quantum/InventoryFilters/KnownWeakKDFIterationCount.ql b/java/ql/src/experimental/Quantum/InventoryFilters/KnownWeakKDFIterationCount.ql new file mode 100644 index 000000000000..439295f74e36 --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventoryFilters/KnownWeakKDFIterationCount.ql @@ -0,0 +1,15 @@ +/** + * @name Detects known weak KDf iteration counts (less than 100k and the count is statically known) + * @id java/crypto_inventory_filters/known_weak_kdf_iteration_count + * @kind problem + */ + +import java +import experimental.Quantum.Language + +from Crypto::KeyDerivationOperationNode op, Literal l +where + op.getIterationCount().asElement() = l and + l.getValue().toInt() < 100000 +select op, "Key derivation operation configures iteration count below 100k: $@", l, + l.getValue().toString() diff --git a/java/ql/src/experimental/Quantum/InventoryFilters/UnknownKDFIterationCount.ql b/java/ql/src/experimental/Quantum/InventoryFilters/UnknownKDFIterationCount.ql new file mode 100644 index 000000000000..0c91e66d52bc --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventoryFilters/UnknownKDFIterationCount.ql @@ -0,0 +1,19 @@ +/** + * @name Detects unknown KDf iteration counts + * @id java/crypto_inventory_filters/unknown_kdf_iteration_count + * @kind problem + */ + +import java +import experimental.Quantum.Language + +from Crypto::KeyDerivationOperationNode op, Element e, string msg +where + e = op.getIterationCount().asElement() and + not e instanceof Literal and + msg = "Key derivation operation with unknown iteration: $@" + or + not exists(op.getIterationCount()) and + e = op.asElement() and + msg = "Key derivation operation with no iteration configuration." +select op, msg, e, e.toString() From ac3675bdac65175d5f39df239223afa68764d127 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 28 Apr 2025 16:00:41 -0400 Subject: [PATCH 124/336] Typo fix --- .../Quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql index 0112e9d96dff..048bcd8182ce 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql @@ -1,6 +1,6 @@ /** * @name Detects known elliptic curve algorithms - * @id java/crypto_inventory_slices/known_elliptic_curvee_algorithm + * @id java/crypto_inventory_slices/known_elliptic_curve_algorithm * @kind problem */ From ac798f2bc6dc5ca0a952682805767077442b641d Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 28 Apr 2025 16:03:41 -0400 Subject: [PATCH 125/336] Cipher Algorithm Slices --- .../KnownAsymmetricCipherAlgorithm.ql | 12 ++++++++++++ .../InventorySlices/KnownCipherAlgorithm.ql | 15 +++++++++++++++ .../KnownSymmetricCipherAlgorithm.ql | 0 shared/cryptography/codeql/cryptography/Model.qll | 8 ++++++++ 4 files changed, 35 insertions(+) create mode 100644 java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql create mode 100644 java/ql/src/experimental/Quantum/InventorySlices/KnownCipherAlgorithm.ql create mode 100644 java/ql/src/experimental/Quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql new file mode 100644 index 000000000000..962a6b720159 --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql @@ -0,0 +1,12 @@ +/** + * @name Detects known asymmetric cipher algorithms + * @id java/crypto_inventory_slices/known_symmetric_cipher_algorithm + * @kind problem + */ + +import java +import experimental.Quantum.Language + +from Crypto::KeyOperationAlgorithmNode a +where a.getAlgorithmType() instanceof Crypto::KeyOpAlg::AsymmetricCipherAlgorithm +select a, "Instance of asymmetric cipher algorithm " + a.getAlgorithmName() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownCipherAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownCipherAlgorithm.ql new file mode 100644 index 000000000000..4096fe16d29c --- /dev/null +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownCipherAlgorithm.ql @@ -0,0 +1,15 @@ +/** + * @name Detects known cipher algorithms + * @id java/crypto_inventory_slices/known_cipher_algorithm + * @kind problem + */ + +import java +import experimental.Quantum.Language + +// TODO: should there be a cipher algorithm node? +from Crypto::KeyOperationAlgorithmNode a +where + a.getAlgorithmType() instanceof Crypto::KeyOpAlg::AsymmetricCipherAlgorithm or + a.getAlgorithmType() instanceof Crypto::KeyOpAlg::SymmetricCipherAlgorithm +select a, "Instance of cipher algorithm " + a.getAlgorithmName() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 704be38362bf..bfc527e108db 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -659,6 +659,14 @@ module CryptographyBase Input> { TSymmetricCipherType getType() { result = type } } + + class AsymmetricCipherAlgorithm extends Algorithm, TAsymmetricCipher { + TAsymmetricCipherType type; + + AsymmetricCipherAlgorithm() { this = TAsymmetricCipher(type) } + + TAsymmetricCipherType getType() { result = type } + } } /** From a408e216ae445041985665be1017b7566a01a700 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 28 Apr 2025 08:45:41 +0200 Subject: [PATCH 126/336] Add query suite inclusion tests for cpp, python --- .../query-suite/cpp-code-quality.qls.expected | 1 + .../cpp-code-scanning.qls.expected | 60 +++ .../cpp-security-and-quality.qls.expected | 181 +++++++ .../cpp-security-extended.qls.expected | 97 ++++ .../query-suite/not_included_in_qls.expected | 449 ++++++++++++++++++ cpp/ql/integration-tests/query-suite/test.py | 14 + .../query-suite/not_included_in_qls.expected | 176 +++++++ .../python-code-quality.qls.expected | 4 + .../python-code-scanning.qls.expected | 43 ++ .../python-security-and-quality.qls.expected | 173 +++++++ .../python-security-extended.qls.expected | 51 ++ .../ql/integration-tests/query-suite/test.py | 14 + 12 files changed, 1263 insertions(+) create mode 100644 cpp/ql/integration-tests/query-suite/cpp-code-quality.qls.expected create mode 100644 cpp/ql/integration-tests/query-suite/cpp-code-scanning.qls.expected create mode 100644 cpp/ql/integration-tests/query-suite/cpp-security-and-quality.qls.expected create mode 100644 cpp/ql/integration-tests/query-suite/cpp-security-extended.qls.expected create mode 100644 cpp/ql/integration-tests/query-suite/not_included_in_qls.expected create mode 100644 cpp/ql/integration-tests/query-suite/test.py create mode 100644 python/ql/integration-tests/query-suite/not_included_in_qls.expected create mode 100644 python/ql/integration-tests/query-suite/python-code-quality.qls.expected create mode 100644 python/ql/integration-tests/query-suite/python-code-scanning.qls.expected create mode 100644 python/ql/integration-tests/query-suite/python-security-and-quality.qls.expected create mode 100644 python/ql/integration-tests/query-suite/python-security-extended.qls.expected create mode 100644 python/ql/integration-tests/query-suite/test.py diff --git a/cpp/ql/integration-tests/query-suite/cpp-code-quality.qls.expected b/cpp/ql/integration-tests/query-suite/cpp-code-quality.qls.expected new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/cpp/ql/integration-tests/query-suite/cpp-code-quality.qls.expected @@ -0,0 +1 @@ + diff --git a/cpp/ql/integration-tests/query-suite/cpp-code-scanning.qls.expected b/cpp/ql/integration-tests/query-suite/cpp-code-scanning.qls.expected new file mode 100644 index 000000000000..c307f26d3dbf --- /dev/null +++ b/cpp/ql/integration-tests/query-suite/cpp-code-scanning.qls.expected @@ -0,0 +1,60 @@ +ql/cpp/ql/src/Critical/DoubleFree.ql +ql/cpp/ql/src/Critical/IncorrectCheckScanf.ql +ql/cpp/ql/src/Critical/NewFreeMismatch.ql +ql/cpp/ql/src/Critical/OverflowStatic.ql +ql/cpp/ql/src/Critical/UseAfterFree.ql +ql/cpp/ql/src/Diagnostics/ExtractedFiles.ql +ql/cpp/ql/src/Diagnostics/ExtractionWarnings.ql +ql/cpp/ql/src/Diagnostics/FailedExtractorInvocations.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/BadAdditionOverflowCheck.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +ql/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql +ql/cpp/ql/src/Likely Bugs/Format/SnprintfOverflow.ql +ql/cpp/ql/src/Likely Bugs/Format/WrongNumberOfFormatArguments.ql +ql/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflow.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/UsingExpiredStackAddress.ql +ql/cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql +ql/cpp/ql/src/Likely Bugs/RedundantNullCheckSimple.ql +ql/cpp/ql/src/Likely Bugs/Underspecified Functions/TooFewArguments.ql +ql/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.ql +ql/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql +ql/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql +ql/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql +ql/cpp/ql/src/Security/CWE/CWE-120/BadlyBoundedWrite.ql +ql/cpp/ql/src/Security/CWE/CWE-120/VeryLikelyOverrunWrite.ql +ql/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql +ql/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql +ql/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql +ql/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql +ql/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql +ql/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql +ql/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql +ql/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +ql/cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql +ql/cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql +ql/cpp/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql +ql/cpp/ql/src/Security/CWE/CWE-327/OpenSslHeartbleed.ql +ql/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRace.ql +ql/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.ql +ql/cpp/ql/src/Security/CWE/CWE-416/UseOfStringAfterLifetimeEnds.ql +ql/cpp/ql/src/Security/CWE/CWE-416/UseOfUniquePointerAfterLifetimeEnds.ql +ql/cpp/ql/src/Security/CWE/CWE-468/SuspiciousAddWithSizeof.ql +ql/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql +ql/cpp/ql/src/Security/CWE/CWE-611/XXE.ql +ql/cpp/ql/src/Security/CWE/CWE-676/DangerousFunctionOverflow.ql +ql/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql +ql/cpp/ql/src/Security/CWE/CWE-704/WcharCharConversion.ql +ql/cpp/ql/src/Security/CWE/CWE-732/OpenCallMissingModeArgument.ql +ql/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql +ql/cpp/ql/src/Summary/LinesOfCode.ql +ql/cpp/ql/src/Summary/LinesOfUserCode.ql +ql/cpp/ql/src/Telemetry/CompilerErrors.ql +ql/cpp/ql/src/Telemetry/DatabaseQuality.ql +ql/cpp/ql/src/Telemetry/ExtractionMetrics.ql +ql/cpp/ql/src/Telemetry/MissingIncludes.ql +ql/cpp/ql/src/Telemetry/SucceededIncludes.ql diff --git a/cpp/ql/integration-tests/query-suite/cpp-security-and-quality.qls.expected b/cpp/ql/integration-tests/query-suite/cpp-security-and-quality.qls.expected new file mode 100644 index 000000000000..9ef67d525cd0 --- /dev/null +++ b/cpp/ql/integration-tests/query-suite/cpp-security-and-quality.qls.expected @@ -0,0 +1,181 @@ +ql/cpp/ql/src/Best Practices/BlockWithTooManyStatements.ql +ql/cpp/ql/src/Best Practices/ComplexCondition.ql +ql/cpp/ql/src/Best Practices/Exceptions/AccidentalRethrow.ql +ql/cpp/ql/src/Best Practices/Exceptions/CatchingByValue.ql +ql/cpp/ql/src/Best Practices/Exceptions/LeakyCatch.ql +ql/cpp/ql/src/Best Practices/Exceptions/ThrowingPointers.ql +ql/cpp/ql/src/Best Practices/GuardedFree.ql +ql/cpp/ql/src/Best Practices/Hiding/DeclarationHidesParameter.ql +ql/cpp/ql/src/Best Practices/Hiding/DeclarationHidesVariable.ql +ql/cpp/ql/src/Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql +ql/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +ql/cpp/ql/src/Best Practices/Likely Errors/EmptyBlock.ql +ql/cpp/ql/src/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql +ql/cpp/ql/src/Best Practices/Likely Errors/Slicing.ql +ql/cpp/ql/src/Best Practices/RuleOfTwo.ql +ql/cpp/ql/src/Best Practices/SloppyGlobal.ql +ql/cpp/ql/src/Best Practices/SwitchLongCase.ql +ql/cpp/ql/src/Best Practices/Unused Entities/UnusedLocals.ql +ql/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticFunctions.ql +ql/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticVariables.ql +ql/cpp/ql/src/Best Practices/UseOfGoto.ql +ql/cpp/ql/src/Critical/DeadCodeGoto.ql +ql/cpp/ql/src/Critical/DoubleFree.ql +ql/cpp/ql/src/Critical/IncorrectCheckScanf.ql +ql/cpp/ql/src/Critical/LargeParameter.ql +ql/cpp/ql/src/Critical/MissingCheckScanf.ql +ql/cpp/ql/src/Critical/NewArrayDeleteMismatch.ql +ql/cpp/ql/src/Critical/NewDeleteArrayMismatch.ql +ql/cpp/ql/src/Critical/NewFreeMismatch.ql +ql/cpp/ql/src/Critical/OverflowStatic.ql +ql/cpp/ql/src/Critical/SizeCheck.ql +ql/cpp/ql/src/Critical/SizeCheck2.ql +ql/cpp/ql/src/Critical/UseAfterFree.ql +ql/cpp/ql/src/Diagnostics/ExtractedFiles.ql +ql/cpp/ql/src/Diagnostics/ExtractionWarnings.ql +ql/cpp/ql/src/Diagnostics/FailedExtractorInvocations.ql +ql/cpp/ql/src/Documentation/CommentedOutCode.ql +ql/cpp/ql/src/Documentation/FixmeComments.ql +ql/cpp/ql/src/Documentation/UncommentedFunction.ql +ql/cpp/ql/src/Header Cleanup/Cleanup-DuplicateIncludeGuard.ql +ql/cpp/ql/src/Likely Bugs/AmbiguouslySignedBitField.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/BadAdditionOverflowCheck.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/BadCheckOdd.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/BitwiseSignCheck.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonPrecedence.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/FloatComparison.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/PointlessComparison.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/UnsignedGEZero.ql +ql/cpp/ql/src/Likely Bugs/ContinueInFalseLoop.ql +ql/cpp/ql/src/Likely Bugs/Conversion/ArrayArgSizeMismatch.ql +ql/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql +ql/cpp/ql/src/Likely Bugs/Conversion/ImplicitDowncastFromBitfield.ql +ql/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql +ql/cpp/ql/src/Likely Bugs/Conversion/LossyPointerCast.ql +ql/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql +ql/cpp/ql/src/Likely Bugs/Format/SnprintfOverflow.ql +ql/cpp/ql/src/Likely Bugs/Format/TooManyFormatArguments.ql +ql/cpp/ql/src/Likely Bugs/Format/WrongNumberOfFormatArguments.ql +ql/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql +ql/cpp/ql/src/Likely Bugs/InconsistentCallOnResult.ql +ql/cpp/ql/src/Likely Bugs/InconsistentCheckReturnNull.ql +ql/cpp/ql/src/Likely Bugs/Leap Year/Adding365DaysPerYear.ql +ql/cpp/ql/src/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification.ql +ql/cpp/ql/src/Likely Bugs/Leap Year/UncheckedReturnValueForTimeFunctions.ql +ql/cpp/ql/src/Likely Bugs/Likely Typos/AssignWhereCompareMeant.ql +ql/cpp/ql/src/Likely Bugs/Likely Typos/CompareWhereAssignMeant.ql +ql/cpp/ql/src/Likely Bugs/Likely Typos/DubiousNullCheck.ql +ql/cpp/ql/src/Likely Bugs/Likely Typos/ExprHasNoEffect.ql +ql/cpp/ql/src/Likely Bugs/Likely Typos/FutileConditional.ql +ql/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.ql +ql/cpp/ql/src/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.ql +ql/cpp/ql/src/Likely Bugs/Likely Typos/ShortCircuitBitMask.ql +ql/cpp/ql/src/Likely Bugs/Likely Typos/UsingStrcpyAsBoolean.ql +ql/cpp/ql/src/Likely Bugs/Likely Typos/inconsistentLoopDirection.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflow.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/StackAddressEscapes.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousSizeof.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/UninitializedLocal.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/UsingExpiredStackAddress.ql +ql/cpp/ql/src/Likely Bugs/NestedLoopSameVar.ql +ql/cpp/ql/src/Likely Bugs/OO/IncorrectConstructorDelegation.ql +ql/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructorInBaseClass.ql +ql/cpp/ql/src/Likely Bugs/OO/ThrowInDestructor.ql +ql/cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql +ql/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql +ql/cpp/ql/src/Likely Bugs/Protocols/UseOfDeprecatedHardcodedProtocol.ql +ql/cpp/ql/src/Likely Bugs/RedundantNullCheckSimple.ql +ql/cpp/ql/src/Likely Bugs/ReturnConstType.ql +ql/cpp/ql/src/Likely Bugs/ReturnConstTypeMember.ql +ql/cpp/ql/src/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.ql +ql/cpp/ql/src/Likely Bugs/Underspecified Functions/MistypedFunctionArguments.ql +ql/cpp/ql/src/Likely Bugs/Underspecified Functions/TooFewArguments.ql +ql/cpp/ql/src/Likely Bugs/Underspecified Functions/TooManyArguments.ql +ql/cpp/ql/src/Likely Bugs/UseInOwnInitializer.ql +ql/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.ql +ql/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql +ql/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql +ql/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql +ql/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql +ql/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql +ql/cpp/ql/src/Security/CWE/CWE-119/OverflowBuffer.ql +ql/cpp/ql/src/Security/CWE/CWE-119/OverrunWriteProductFlow.ql +ql/cpp/ql/src/Security/CWE/CWE-120/BadlyBoundedWrite.ql +ql/cpp/ql/src/Security/CWE/CWE-120/OverrunWrite.ql +ql/cpp/ql/src/Security/CWE/CWE-120/OverrunWriteFloat.ql +ql/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql +ql/cpp/ql/src/Security/CWE/CWE-120/VeryLikelyOverrunWrite.ql +ql/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql +ql/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql +ql/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql +ql/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql +ql/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql +ql/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +ql/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql +ql/cpp/ql/src/Security/CWE/CWE-193/InvalidPointerDeref.ql +ql/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql +ql/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql +ql/cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql +ql/cpp/ql/src/Security/CWE/CWE-295/SSLResultNotChecked.ql +ql/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql +ql/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql +ql/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +ql/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql +ql/cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql +ql/cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql +ql/cpp/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql +ql/cpp/ql/src/Security/CWE/CWE-327/OpenSslHeartbleed.ql +ql/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRace.ql +ql/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.ql +ql/cpp/ql/src/Security/CWE/CWE-416/UseOfStringAfterLifetimeEnds.ql +ql/cpp/ql/src/Security/CWE/CWE-416/UseOfUniquePointerAfterLifetimeEnds.ql +ql/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql +ql/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScaling.ql +ql/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingVoid.ql +ql/cpp/ql/src/Security/CWE/CWE-468/SuspiciousAddWithSizeof.ql +ql/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql +ql/cpp/ql/src/Security/CWE/CWE-497/PotentiallyExposedSystemData.ql +ql/cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.ql +ql/cpp/ql/src/Security/CWE/CWE-611/XXE.ql +ql/cpp/ql/src/Security/CWE/CWE-676/DangerousFunctionOverflow.ql +ql/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql +ql/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql +ql/cpp/ql/src/Security/CWE/CWE-704/WcharCharConversion.ql +ql/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql +ql/cpp/ql/src/Security/CWE/CWE-732/OpenCallMissingModeArgument.ql +ql/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql +ql/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql +ql/cpp/ql/src/Security/CWE/CWE-843/TypeConfusion.ql +ql/cpp/ql/src/Summary/LinesOfCode.ql +ql/cpp/ql/src/Summary/LinesOfUserCode.ql +ql/cpp/ql/src/Telemetry/CompilerErrors.ql +ql/cpp/ql/src/Telemetry/DatabaseQuality.ql +ql/cpp/ql/src/Telemetry/ExtractionMetrics.ql +ql/cpp/ql/src/Telemetry/MissingIncludes.ql +ql/cpp/ql/src/Telemetry/SucceededIncludes.ql +ql/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 32.ql +ql/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.1.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 82.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 89.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 95.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.ql +ql/cpp/ql/src/jsf/4.13 Functions/AV Rule 107.ql +ql/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql +ql/cpp/ql/src/jsf/4.16 Initialization/AV Rule 145.ql +ql/cpp/ql/src/jsf/4.17 Types/AV Rule 148.ql +ql/cpp/ql/src/jsf/4.21 Operators/AV Rule 166.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 196.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 197.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 201.ql diff --git a/cpp/ql/integration-tests/query-suite/cpp-security-extended.qls.expected b/cpp/ql/integration-tests/query-suite/cpp-security-extended.qls.expected new file mode 100644 index 000000000000..f014b6d5dc51 --- /dev/null +++ b/cpp/ql/integration-tests/query-suite/cpp-security-extended.qls.expected @@ -0,0 +1,97 @@ +ql/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +ql/cpp/ql/src/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql +ql/cpp/ql/src/Critical/DoubleFree.ql +ql/cpp/ql/src/Critical/IncorrectCheckScanf.ql +ql/cpp/ql/src/Critical/MissingCheckScanf.ql +ql/cpp/ql/src/Critical/NewFreeMismatch.ql +ql/cpp/ql/src/Critical/OverflowStatic.ql +ql/cpp/ql/src/Critical/SizeCheck.ql +ql/cpp/ql/src/Critical/SizeCheck2.ql +ql/cpp/ql/src/Critical/UseAfterFree.ql +ql/cpp/ql/src/Diagnostics/ExtractedFiles.ql +ql/cpp/ql/src/Diagnostics/ExtractionWarnings.ql +ql/cpp/ql/src/Diagnostics/FailedExtractorInvocations.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/BadAdditionOverflowCheck.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +ql/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql +ql/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql +ql/cpp/ql/src/Likely Bugs/Format/SnprintfOverflow.ql +ql/cpp/ql/src/Likely Bugs/Format/WrongNumberOfFormatArguments.ql +ql/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql +ql/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflow.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousSizeof.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/UninitializedLocal.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/UsingExpiredStackAddress.ql +ql/cpp/ql/src/Likely Bugs/OO/UnsafeUseOfThis.ql +ql/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql +ql/cpp/ql/src/Likely Bugs/Protocols/UseOfDeprecatedHardcodedProtocol.ql +ql/cpp/ql/src/Likely Bugs/RedundantNullCheckSimple.ql +ql/cpp/ql/src/Likely Bugs/Underspecified Functions/TooFewArguments.ql +ql/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.ql +ql/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql +ql/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql +ql/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql +ql/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql +ql/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql +ql/cpp/ql/src/Security/CWE/CWE-119/OverflowBuffer.ql +ql/cpp/ql/src/Security/CWE/CWE-119/OverrunWriteProductFlow.ql +ql/cpp/ql/src/Security/CWE/CWE-120/BadlyBoundedWrite.ql +ql/cpp/ql/src/Security/CWE/CWE-120/OverrunWrite.ql +ql/cpp/ql/src/Security/CWE/CWE-120/OverrunWriteFloat.ql +ql/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql +ql/cpp/ql/src/Security/CWE/CWE-120/VeryLikelyOverrunWrite.ql +ql/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql +ql/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql +ql/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql +ql/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql +ql/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql +ql/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +ql/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql +ql/cpp/ql/src/Security/CWE/CWE-193/InvalidPointerDeref.ql +ql/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql +ql/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql +ql/cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql +ql/cpp/ql/src/Security/CWE/CWE-295/SSLResultNotChecked.ql +ql/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql +ql/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql +ql/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +ql/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql +ql/cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql +ql/cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql +ql/cpp/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql +ql/cpp/ql/src/Security/CWE/CWE-327/OpenSslHeartbleed.ql +ql/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRace.ql +ql/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.ql +ql/cpp/ql/src/Security/CWE/CWE-416/UseOfStringAfterLifetimeEnds.ql +ql/cpp/ql/src/Security/CWE/CWE-416/UseOfUniquePointerAfterLifetimeEnds.ql +ql/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql +ql/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScaling.ql +ql/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingVoid.ql +ql/cpp/ql/src/Security/CWE/CWE-468/SuspiciousAddWithSizeof.ql +ql/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql +ql/cpp/ql/src/Security/CWE/CWE-497/PotentiallyExposedSystemData.ql +ql/cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.ql +ql/cpp/ql/src/Security/CWE/CWE-611/XXE.ql +ql/cpp/ql/src/Security/CWE/CWE-676/DangerousFunctionOverflow.ql +ql/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql +ql/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql +ql/cpp/ql/src/Security/CWE/CWE-704/WcharCharConversion.ql +ql/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql +ql/cpp/ql/src/Security/CWE/CWE-732/OpenCallMissingModeArgument.ql +ql/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql +ql/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql +ql/cpp/ql/src/Security/CWE/CWE-843/TypeConfusion.ql +ql/cpp/ql/src/Summary/LinesOfCode.ql +ql/cpp/ql/src/Summary/LinesOfUserCode.ql +ql/cpp/ql/src/Telemetry/CompilerErrors.ql +ql/cpp/ql/src/Telemetry/DatabaseQuality.ql +ql/cpp/ql/src/Telemetry/ExtractionMetrics.ql +ql/cpp/ql/src/Telemetry/MissingIncludes.ql +ql/cpp/ql/src/Telemetry/SucceededIncludes.ql diff --git a/cpp/ql/integration-tests/query-suite/not_included_in_qls.expected b/cpp/ql/integration-tests/query-suite/not_included_in_qls.expected new file mode 100644 index 000000000000..393f35606cbf --- /dev/null +++ b/cpp/ql/integration-tests/query-suite/not_included_in_qls.expected @@ -0,0 +1,449 @@ +ql/cpp/ql/src/AlertSuppression.ql +ql/cpp/ql/src/Architecture/FeatureEnvy.ql +ql/cpp/ql/src/Architecture/General Class-Level Information/ClassHierarchies.ql +ql/cpp/ql/src/Architecture/General Class-Level Information/HubClasses.ql +ql/cpp/ql/src/Architecture/General Class-Level Information/InheritanceDepthDistribution.ql +ql/cpp/ql/src/Architecture/General Namespace-Level Information/CyclicNamespaces.ql +ql/cpp/ql/src/Architecture/General Namespace-Level Information/GlobalNamespaceClasses.ql +ql/cpp/ql/src/Architecture/General Namespace-Level Information/NamespaceDependencies.ql +ql/cpp/ql/src/Architecture/General Top-Level Information/GeneralStatistics.ql +ql/cpp/ql/src/Architecture/InappropriateIntimacy.ql +ql/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyDependencies.ql +ql/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.ql +ql/cpp/ql/src/Architecture/Refactoring Opportunities/ComplexFunctions.ql +ql/cpp/ql/src/Architecture/Refactoring Opportunities/CyclomaticComplexity.ql +ql/cpp/ql/src/Architecture/Refactoring Opportunities/FunctionsWithManyParameters.ql +ql/cpp/ql/src/Best Practices/Magic Constants/JapaneseEraDate.ql +ql/cpp/ql/src/Best Practices/Magic Constants/MagicConstantsNumbers.ql +ql/cpp/ql/src/Best Practices/Magic Constants/MagicConstantsString.ql +ql/cpp/ql/src/Best Practices/Magic Constants/MagicNumbersUseConstant.ql +ql/cpp/ql/src/Best Practices/Magic Constants/MagicStringsUseConstant.ql +ql/cpp/ql/src/Best Practices/NVI.ql +ql/cpp/ql/src/Best Practices/NVIHub.ql +ql/cpp/ql/src/Best Practices/RuleOfThree.ql +ql/cpp/ql/src/Best Practices/Unused Entities/UnusedIncludes.ql +ql/cpp/ql/src/Critical/DeadCodeCondition.ql +ql/cpp/ql/src/Critical/DeadCodeFunction.ql +ql/cpp/ql/src/Critical/DescriptorMayNotBeClosed.ql +ql/cpp/ql/src/Critical/DescriptorNeverClosed.ql +ql/cpp/ql/src/Critical/FileMayNotBeClosed.ql +ql/cpp/ql/src/Critical/FileNeverClosed.ql +ql/cpp/ql/src/Critical/GlobalUseBeforeInit.ql +ql/cpp/ql/src/Critical/InconsistentNullnessTesting.ql +ql/cpp/ql/src/Critical/InitialisationNotRun.ql +ql/cpp/ql/src/Critical/LateNegativeTest.ql +ql/cpp/ql/src/Critical/MemoryMayNotBeFreed.ql +ql/cpp/ql/src/Critical/MemoryNeverFreed.ql +ql/cpp/ql/src/Critical/MissingNegativityTest.ql +ql/cpp/ql/src/Critical/MissingNullTest.ql +ql/cpp/ql/src/Critical/NotInitialised.ql +ql/cpp/ql/src/Critical/OverflowCalculated.ql +ql/cpp/ql/src/Critical/OverflowDestination.ql +ql/cpp/ql/src/Critical/ReturnStackAllocatedObject.ql +ql/cpp/ql/src/Critical/ReturnValueIgnored.ql +ql/cpp/ql/src/Critical/Unused.ql +ql/cpp/ql/src/Diagnostics/Internal/ExtractionErrors.ql +ql/cpp/ql/src/Documentation/DocumentApi.ql +ql/cpp/ql/src/Documentation/TodoComments.ql +ql/cpp/ql/src/JPL_C/LOC-2/Rule 03/ExitNonterminatingLoop.ql +ql/cpp/ql/src/JPL_C/LOC-2/Rule 03/LoopBounds.ql +ql/cpp/ql/src/JPL_C/LOC-2/Rule 04/Recursion.ql +ql/cpp/ql/src/JPL_C/LOC-2/Rule 05/HeapMemory.ql +ql/cpp/ql/src/JPL_C/LOC-2/Rule 07/ThreadSafety.ql +ql/cpp/ql/src/JPL_C/LOC-2/Rule 09/AvoidNestedSemaphores.ql +ql/cpp/ql/src/JPL_C/LOC-2/Rule 09/AvoidSemaphores.ql +ql/cpp/ql/src/JPL_C/LOC-2/Rule 09/OutOfOrderLocks.ql +ql/cpp/ql/src/JPL_C/LOC-2/Rule 09/ReleaseLocksWhenAcquired.ql +ql/cpp/ql/src/JPL_C/LOC-2/Rule 11/SimpleControlFlowGoto.ql +ql/cpp/ql/src/JPL_C/LOC-2/Rule 11/SimpleControlFlowJmp.ql +ql/cpp/ql/src/JPL_C/LOC-2/Rule 12/EnumInitialization.ql +ql/cpp/ql/src/JPL_C/LOC-3/Rule 13/ExternDeclsInHeader.ql +ql/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFile.ql +ql/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFunction.ql +ql/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeLocalHidesGlobal.ql +ql/cpp/ql/src/JPL_C/LOC-3/Rule 14/CheckingReturnValues.ql +ql/cpp/ql/src/JPL_C/LOC-3/Rule 15/CheckingParameterValues.ql +ql/cpp/ql/src/JPL_C/LOC-3/Rule 16/UseOfAssertionsConstant.ql +ql/cpp/ql/src/JPL_C/LOC-3/Rule 16/UseOfAssertionsDensity.ql +ql/cpp/ql/src/JPL_C/LOC-3/Rule 16/UseOfAssertionsNonBoolean.ql +ql/cpp/ql/src/JPL_C/LOC-3/Rule 16/UseOfAssertionsSideEffect.ql +ql/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql +ql/cpp/ql/src/JPL_C/LOC-3/Rule 18/CompoundExpressions.ql +ql/cpp/ql/src/JPL_C/LOC-3/Rule 19/NoBooleanSideEffects.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUse.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUseIfdef.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUsePartial.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUseUndisciplined.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 21/MacroInBlock.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 22/UseOfUndef.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 23/MismatchedIfdefs.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleStmtsPerLine.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleVarDeclsPerLine.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 25/FunctionSizeLimits.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 26/DeclarationPointerNesting.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 27/PointerDereferenceInStmt.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 28/HiddenPointerDereferenceMacro.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 28/HiddenPointerIndirectionTypedef.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 29/NonConstFunctionPointer.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 30/FunctionPointerConversions.ql +ql/cpp/ql/src/JPL_C/LOC-4/Rule 31/IncludesFirst.ql +ql/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonWithCancelingSubExpr.ql +ql/cpp/ql/src/Likely Bugs/Conversion/ConversionChangesSign.ql +ql/cpp/ql/src/Likely Bugs/Conversion/NonzeroValueCastToPointer.ql +ql/cpp/ql/src/Likely Bugs/JapaneseEra/ConstructorOrMethodWithExactEraDate.ql +ql/cpp/ql/src/Likely Bugs/JapaneseEra/StructWithExactEraDate.ql +ql/cpp/ql/src/Likely Bugs/Leap Year/UnsafeArrayForDaysOfYear.ql +ql/cpp/ql/src/Likely Bugs/Likely Typos/BoolValueInBitOp.ql +ql/cpp/ql/src/Likely Bugs/Likely Typos/LogicalExprCouldBeSimplified.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/Padding/More64BitWaste.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/Padding/NonPortablePrintf.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/Padding/Suboptimal64BitType.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/PotentialBufferOverflow.ql +ql/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToMemset.ql +ql/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructor.ql +ql/cpp/ql/src/Likely Bugs/OO/SelfAssignmentCheck.ql +ql/cpp/ql/src/Likely Bugs/OO/VirtualCallInStructor.ql +ql/cpp/ql/src/Likely Bugs/ShortLoopVarName.ql +ql/cpp/ql/src/Metrics/Classes/CAfferentCoupling.ql +ql/cpp/ql/src/Metrics/Classes/CEfferentCoupling.ql +ql/cpp/ql/src/Metrics/Classes/CHalsteadBugs.ql +ql/cpp/ql/src/Metrics/Classes/CHalsteadDifficulty.ql +ql/cpp/ql/src/Metrics/Classes/CHalsteadEffort.ql +ql/cpp/ql/src/Metrics/Classes/CHalsteadLength.ql +ql/cpp/ql/src/Metrics/Classes/CHalsteadVocabulary.ql +ql/cpp/ql/src/Metrics/Classes/CHalsteadVolume.ql +ql/cpp/ql/src/Metrics/Classes/CInheritanceDepth.ql +ql/cpp/ql/src/Metrics/Classes/CLackOfCohesionCK.ql +ql/cpp/ql/src/Metrics/Classes/CLackOfCohesionHS.ql +ql/cpp/ql/src/Metrics/Classes/CLinesOfCode.ql +ql/cpp/ql/src/Metrics/Classes/CNumberOfFields.ql +ql/cpp/ql/src/Metrics/Classes/CNumberOfFunctions.ql +ql/cpp/ql/src/Metrics/Classes/CNumberOfStatements.ql +ql/cpp/ql/src/Metrics/Classes/CPercentageOfComplexCode.ql +ql/cpp/ql/src/Metrics/Classes/CResponse.ql +ql/cpp/ql/src/Metrics/Classes/CSizeOfAPI.ql +ql/cpp/ql/src/Metrics/Classes/CSpecialisation.ql +ql/cpp/ql/src/Metrics/Dependencies/ExternalDependencies.ql +ql/cpp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql +ql/cpp/ql/src/Metrics/External/FileCompilationDisplayStrings.ql +ql/cpp/ql/src/Metrics/External/FileCompilationSourceLinks.ql +ql/cpp/ql/src/Metrics/Files/AutogeneratedLOC.ql +ql/cpp/ql/src/Metrics/Files/ConditionalSegmentConditions.ql +ql/cpp/ql/src/Metrics/Files/ConditionalSegmentLines.ql +ql/cpp/ql/src/Metrics/Files/FAfferentCoupling.ql +ql/cpp/ql/src/Metrics/Files/FCommentRatio.ql +ql/cpp/ql/src/Metrics/Files/FCyclomaticComplexity.ql +ql/cpp/ql/src/Metrics/Files/FDirectIncludes.ql +ql/cpp/ql/src/Metrics/Files/FEfferentCoupling.ql +ql/cpp/ql/src/Metrics/Files/FHalsteadBugs.ql +ql/cpp/ql/src/Metrics/Files/FHalsteadDifficulty.ql +ql/cpp/ql/src/Metrics/Files/FHalsteadEffort.ql +ql/cpp/ql/src/Metrics/Files/FHalsteadLength.ql +ql/cpp/ql/src/Metrics/Files/FHalsteadVocabulary.ql +ql/cpp/ql/src/Metrics/Files/FHalsteadVolume.ql +ql/cpp/ql/src/Metrics/Files/FLines.ql +ql/cpp/ql/src/Metrics/Files/FLinesOfCode.ql +ql/cpp/ql/src/Metrics/Files/FLinesOfCommentedOutCode.ql +ql/cpp/ql/src/Metrics/Files/FLinesOfComments.ql +ql/cpp/ql/src/Metrics/Files/FMacroRatio.ql +ql/cpp/ql/src/Metrics/Files/FNumberOfClasses.ql +ql/cpp/ql/src/Metrics/Files/FNumberOfTests.ql +ql/cpp/ql/src/Metrics/Files/FTimeInFrontend.ql +ql/cpp/ql/src/Metrics/Files/FTodoComments.ql +ql/cpp/ql/src/Metrics/Files/FTransitiveIncludes.ql +ql/cpp/ql/src/Metrics/Files/FTransitiveSourceIncludes.ql +ql/cpp/ql/src/Metrics/Files/FunctionLength.ql +ql/cpp/ql/src/Metrics/Files/NumberOfFunctions.ql +ql/cpp/ql/src/Metrics/Files/NumberOfGlobals.ql +ql/cpp/ql/src/Metrics/Files/NumberOfParameters.ql +ql/cpp/ql/src/Metrics/Files/NumberOfPublicFunctions.ql +ql/cpp/ql/src/Metrics/Files/NumberOfPublicGlobals.ql +ql/cpp/ql/src/Metrics/Functions/FunCyclomaticComplexity.ql +ql/cpp/ql/src/Metrics/Functions/FunIterationNestingDepth.ql +ql/cpp/ql/src/Metrics/Functions/FunLinesOfCode.ql +ql/cpp/ql/src/Metrics/Functions/FunLinesOfComments.ql +ql/cpp/ql/src/Metrics/Functions/FunNumberOfCalls.ql +ql/cpp/ql/src/Metrics/Functions/FunNumberOfParameters.ql +ql/cpp/ql/src/Metrics/Functions/FunNumberOfStatements.ql +ql/cpp/ql/src/Metrics/Functions/FunPercentageOfComments.ql +ql/cpp/ql/src/Metrics/Functions/StatementNestingDepth.ql +ql/cpp/ql/src/Metrics/Internal/ASTConsistency.ql +ql/cpp/ql/src/Metrics/Internal/CallableDisplayStrings.ql +ql/cpp/ql/src/Metrics/Internal/CallableExtents.ql +ql/cpp/ql/src/Metrics/Internal/CallableSourceLinks.ql +ql/cpp/ql/src/Metrics/Internal/DiagnosticsSumElapsedTimes.ql +ql/cpp/ql/src/Metrics/Internal/IRConsistency.ql +ql/cpp/ql/src/Metrics/Internal/IncludeResolutionStatus.ql +ql/cpp/ql/src/Metrics/Internal/ReftypeDisplayStrings.ql +ql/cpp/ql/src/Metrics/Internal/ReftypeSourceLinks.ql +ql/cpp/ql/src/Metrics/Namespaces/AbstractNamespaces.ql +ql/cpp/ql/src/Metrics/Namespaces/ConcreteNamespaces.ql +ql/cpp/ql/src/Metrics/Namespaces/HighAfferentCouplingNamespaces.ql +ql/cpp/ql/src/Metrics/Namespaces/HighDistanceFromMainLineNamespaces.ql +ql/cpp/ql/src/Metrics/Namespaces/HighEfferentCouplingNamespaces.ql +ql/cpp/ql/src/Metrics/Namespaces/StableNamespaces.ql +ql/cpp/ql/src/Metrics/Namespaces/UnstableNamespaces.ql +ql/cpp/ql/src/Microsoft/CallWithNullSAL.ql +ql/cpp/ql/src/Microsoft/IgnoreReturnValueSAL.ql +ql/cpp/ql/src/Microsoft/InconsistentSAL.ql +ql/cpp/ql/src/PointsTo/Debug.ql +ql/cpp/ql/src/PointsTo/PreparedStagedPointsTo.ql +ql/cpp/ql/src/PointsTo/Stats.ql +ql/cpp/ql/src/PointsTo/TaintedFormatStrings.ql +ql/cpp/ql/src/Power of 10/Rule 1/UseOfGoto.ql +ql/cpp/ql/src/Power of 10/Rule 1/UseOfJmp.ql +ql/cpp/ql/src/Power of 10/Rule 1/UseOfRecursion.ql +ql/cpp/ql/src/Power of 10/Rule 2/BoundedLoopIterations.ql +ql/cpp/ql/src/Power of 10/Rule 2/ExitPermanentLoop.ql +ql/cpp/ql/src/Power of 10/Rule 3/DynamicAllocAfterInit.ql +ql/cpp/ql/src/Power of 10/Rule 4/FunctionTooLong.ql +ql/cpp/ql/src/Power of 10/Rule 4/OneStmtPerLine.ql +ql/cpp/ql/src/Power of 10/Rule 5/AssertionDensity.ql +ql/cpp/ql/src/Power of 10/Rule 5/AssertionSideEffect.ql +ql/cpp/ql/src/Power of 10/Rule 5/ConstantAssertion.ql +ql/cpp/ql/src/Power of 10/Rule 5/NonBooleanAssertion.ql +ql/cpp/ql/src/Power of 10/Rule 6/GlobalCouldBeStatic.ql +ql/cpp/ql/src/Power of 10/Rule 6/VariableScopeTooLarge.ql +ql/cpp/ql/src/Power of 10/Rule 7/CheckArguments.ql +ql/cpp/ql/src/Power of 10/Rule 7/CheckReturnValues.ql +ql/cpp/ql/src/Power of 10/Rule 8/AvoidConditionalCompilation.ql +ql/cpp/ql/src/Power of 10/Rule 8/PartialMacro.ql +ql/cpp/ql/src/Power of 10/Rule 8/RestrictPreprocessor.ql +ql/cpp/ql/src/Power of 10/Rule 8/UndisciplinedMacro.ql +ql/cpp/ql/src/Power of 10/Rule 9/FunctionPointer.ql +ql/cpp/ql/src/Power of 10/Rule 9/HiddenPointerIndirection.ql +ql/cpp/ql/src/Power of 10/Rule 9/PointerNesting.ql +ql/cpp/ql/src/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.ql +ql/cpp/ql/src/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.ql +ql/cpp/ql/src/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql +ql/cpp/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql +ql/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql +ql/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql +ql/cpp/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql +ql/cpp/ql/src/Security/CWE/CWE-190/ArithmeticWithExtremeValues.ql +ql/cpp/ql/src/Security/CWE/CWE-190/IntegerOverflowTainted.ql +ql/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql +ql/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingChar.ql +ql/cpp/ql/src/Security/CWE/CWE-764/LockOrderCycle.ql +ql/cpp/ql/src/Security/CWE/CWE-764/TwiceLocked.ql +ql/cpp/ql/src/Security/CWE/CWE-764/UnreleasedLock.ql +ql/cpp/ql/src/Security/CWE/CWE-835/InfiniteLoopWithUnsatisfiableExitCondition.ql +ql/cpp/ql/src/definitions.ql +ql/cpp/ql/src/experimental/Best Practices/UselessTest.ql +ql/cpp/ql/src/experimental/Best Practices/WrongUintAccess.ql +ql/cpp/ql/src/experimental/Likely Bugs/ArrayAccessProductFlow.ql +ql/cpp/ql/src/experimental/Likely Bugs/DerefNullResult.ql +ql/cpp/ql/src/experimental/Likely Bugs/RedundantNullCheckParam.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-020/LateCheckOfFunctionArgument.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-078/WordexpTainted.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-120/MemoryUnsafeFunctionScan.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-1240/CustomCryptographicPrimitive.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-125/DangerousWorksWithMultibyteOrWideCharacters.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-190/DangerousUseOfTransformationAfterOperation.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-190/IfStatementAdditionOverflow.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-200/ExposureSensitiveInformationUnauthorizedActor.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-243/IncorrectChangingWorkingDirectory.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-273/PrivilegeDroppingOutoforder.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-285/PamAuthorization.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-295/CurlSSL.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-362/double-fetch.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-369/DivideByZeroUsingReturnValue.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-377/InsecureTemporaryFile.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-409/DecompressionBombs.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-416/UseAfterExpiredLifetime.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-476/DangerousUseOfExceptionBlocks.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-561/FindIncorrectlyUsedSwitch.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-670/DangerousUseSSL_shutdown.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-691/InsufficientControlFlowManagementAfterRefactoringTheCode.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-691/InsufficientControlFlowManagementWhenUsingBitOperations.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-703/FindIncorrectlyUsedExceptions.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-758/UndefinedOrImplementationDefinedBehavior.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-783/OperatorPrecedenceLogicErrorWhenUseBitwiseOrLogicalOperations.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-783/OperatorPrecedenceLogicErrorWhenUseBoolType.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-787/UnsignedToSignedPointerArith.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql +ql/cpp/ql/src/experimental/Security/CWE/CWE-805/BufferAccessWithIncorrectLengthValue.ql +ql/cpp/ql/src/experimental/cryptography/example_alerts/UnknownAsymmetricKeyGen.ql +ql/cpp/ql/src/experimental/cryptography/example_alerts/WeakAsymmetricKeyGen.ql +ql/cpp/ql/src/experimental/cryptography/example_alerts/WeakBlockMode.ql +ql/cpp/ql/src/experimental/cryptography/example_alerts/WeakEllipticCurve.ql +ql/cpp/ql/src/experimental/cryptography/example_alerts/WeakEncryption.ql +ql/cpp/ql/src/experimental/cryptography/example_alerts/WeakHashes.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/AllAsymmetricAlgorithms.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/AllCryptoAlgorithms.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/AsymmetricEncryptionAlgorithms.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/AsymmetricPaddingAlgorithms.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/AuthenticatedEncryptionAlgorithms.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/BlockModeAlgorithms.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/BlockModeKnownIVsOrNonces.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/BlockModeUnknownIVsOrNonces.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/EllipticCurveAlgorithmSize.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/EllipticCurveAlgorithms.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/HashingAlgorithms.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/KeyExchangeAlgorithms.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/KnownAsymmetricKeyGeneration.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/SigningAlgorithms.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/SymmetricEncryptionAlgorithms.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/SymmetricPaddingAlgorithms.ql +ql/cpp/ql/src/experimental/cryptography/inventory/new_models/UnknownAsymmetricKeyGeneration.ql +ql/cpp/ql/src/external/examples/filters/BumpMetricBy10.ql +ql/cpp/ql/src/external/examples/filters/EditDefectMessage.ql +ql/cpp/ql/src/external/examples/filters/ExcludeGeneratedCode.ql +ql/cpp/ql/src/filters/ClassifyFiles.ql +ql/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 1.ql +ql/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 2.ql +ql/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 3.ql +ql/cpp/ql/src/jsf/4.04 Environment/AV Rule 11.ql +ql/cpp/ql/src/jsf/4.04 Environment/AV Rule 12.ql +ql/cpp/ql/src/jsf/4.04 Environment/AV Rule 13.ql +ql/cpp/ql/src/jsf/4.04 Environment/AV Rule 14.ql +ql/cpp/ql/src/jsf/4.04 Environment/AV Rule 9.ql +ql/cpp/ql/src/jsf/4.05 Libraries/AV Rule 17.ql +ql/cpp/ql/src/jsf/4.05 Libraries/AV Rule 18.ql +ql/cpp/ql/src/jsf/4.05 Libraries/AV Rule 19.ql +ql/cpp/ql/src/jsf/4.05 Libraries/AV Rule 20.ql +ql/cpp/ql/src/jsf/4.05 Libraries/AV Rule 21.ql +ql/cpp/ql/src/jsf/4.05 Libraries/AV Rule 22.ql +ql/cpp/ql/src/jsf/4.05 Libraries/AV Rule 23.ql +ql/cpp/ql/src/jsf/4.05 Libraries/AV Rule 24.ql +ql/cpp/ql/src/jsf/4.05 Libraries/AV Rule 25.ql +ql/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 26.ql +ql/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 27.ql +ql/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 28.ql +ql/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 29.ql +ql/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 30.ql +ql/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 31.ql +ql/cpp/ql/src/jsf/4.07 Header Files/AV Rule 33.ql +ql/cpp/ql/src/jsf/4.07 Header Files/AV Rule 39.ql +ql/cpp/ql/src/jsf/4.08 Implementation Files/AV Rule 40.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 41.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 42.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 43.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 44.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 45.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 46.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 47.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 48.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 49.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 50.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 51.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 52.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 53.1.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 53.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 54.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 57.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 58.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 59.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 60.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 61.ql +ql/cpp/ql/src/jsf/4.09 Style/AV Rule 63.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 68.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 69.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 70.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 73.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 74.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 75.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 76.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 77.1.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 78.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 81.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 85.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.1.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 94.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 96.ql +ql/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql +ql/cpp/ql/src/jsf/4.11 Namespaces/AV Rule 99.ql +ql/cpp/ql/src/jsf/4.12 Templates/AV Rule 104.ql +ql/cpp/ql/src/jsf/4.13 Functions/AV Rule 108.ql +ql/cpp/ql/src/jsf/4.13 Functions/AV Rule 110.ql +ql/cpp/ql/src/jsf/4.13 Functions/AV Rule 111.ql +ql/cpp/ql/src/jsf/4.13 Functions/AV Rule 113.ql +ql/cpp/ql/src/jsf/4.13 Functions/AV Rule 115.ql +ql/cpp/ql/src/jsf/4.13 Functions/AV Rule 119.ql +ql/cpp/ql/src/jsf/4.14 Comments/AV Rule 126.ql +ql/cpp/ql/src/jsf/4.14 Comments/AV Rule 127.ql +ql/cpp/ql/src/jsf/4.14 Comments/AV Rule 133.ql +ql/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 135.ql +ql/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 138.ql +ql/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 139.ql +ql/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 140.ql +ql/cpp/ql/src/jsf/4.16 Initialization/AV Rule 142.ql +ql/cpp/ql/src/jsf/4.16 Initialization/AV Rule 143.ql +ql/cpp/ql/src/jsf/4.17 Types/AV Rule 147.ql +ql/cpp/ql/src/jsf/4.18 Constants/AV Rule 149.ql +ql/cpp/ql/src/jsf/4.18 Constants/AV Rule 150.ql +ql/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.1.ql +ql/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.ql +ql/cpp/ql/src/jsf/4.19 Variables/AV Rule 152.ql +ql/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 153.ql +ql/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 154.ql +ql/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 155.ql +ql/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 156.ql +ql/cpp/ql/src/jsf/4.21 Operators/AV Rule 157.ql +ql/cpp/ql/src/jsf/4.21 Operators/AV Rule 158.ql +ql/cpp/ql/src/jsf/4.21 Operators/AV Rule 159.ql +ql/cpp/ql/src/jsf/4.21 Operators/AV Rule 160.ql +ql/cpp/ql/src/jsf/4.21 Operators/AV Rule 162.ql +ql/cpp/ql/src/jsf/4.21 Operators/AV Rule 163.ql +ql/cpp/ql/src/jsf/4.21 Operators/AV Rule 164.ql +ql/cpp/ql/src/jsf/4.21 Operators/AV Rule 165.ql +ql/cpp/ql/src/jsf/4.21 Operators/AV Rule 168.ql +ql/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 170.ql +ql/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 171.ql +ql/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 173.ql +ql/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 175.ql +ql/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 176.ql +ql/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 178.ql +ql/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 179.ql +ql/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 180.ql +ql/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 181.ql +ql/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 182.ql +ql/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 184.ql +ql/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 185.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 186.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 187.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 188.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 189.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 190.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 191.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 192.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 193.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 194.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 195.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 198.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 199.ql +ql/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 200.ql +ql/cpp/ql/src/jsf/4.25 Expressions/AV Rule 202.ql +ql/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.1.ql +ql/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.ql +ql/cpp/ql/src/jsf/4.25 Expressions/AV Rule 205.ql +ql/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 206.ql +ql/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 207.ql +ql/cpp/ql/src/jsf/4.27 Fault Handling/AV Rule 208.ql +ql/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 209.ql +ql/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 210.ql +ql/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 212.ql +ql/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 213.ql +ql/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 214.ql +ql/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 215.ql +ql/cpp/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql +ql/cpp/ql/src/utils/modelgenerator/CaptureMixedNeutralModels.ql +ql/cpp/ql/src/utils/modelgenerator/CaptureMixedSummaryModels.ql +ql/cpp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql +ql/cpp/ql/src/utils/modelgenerator/CaptureSinkModels.ql +ql/cpp/ql/src/utils/modelgenerator/CaptureSourceModels.ql +ql/cpp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql diff --git a/cpp/ql/integration-tests/query-suite/test.py b/cpp/ql/integration-tests/query-suite/test.py new file mode 100644 index 000000000000..232630c4d2a9 --- /dev/null +++ b/cpp/ql/integration-tests/query-suite/test.py @@ -0,0 +1,14 @@ +import runs_on +import pytest +from query_suites import * + +well_known_query_suites = ['cpp-code-quality.qls', 'cpp-security-and-quality.qls', 'cpp-security-extended.qls', 'cpp-code-scanning.qls'] + +@runs_on.posix +@pytest.mark.parametrize("query_suite", well_known_query_suites) +def test(codeql, cpp, check_query_suite, query_suite): + check_query_suite(query_suite) + +@runs_on.posix +def test_not_included_queries(codeql, cpp, check_queries_not_included): + check_queries_not_included('cpp', well_known_query_suites) diff --git a/python/ql/integration-tests/query-suite/not_included_in_qls.expected b/python/ql/integration-tests/query-suite/not_included_in_qls.expected new file mode 100644 index 000000000000..9921f13aa558 --- /dev/null +++ b/python/ql/integration-tests/query-suite/not_included_in_qls.expected @@ -0,0 +1,176 @@ +ql/python/ql/src/AlertSuppression.ql +ql/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql +ql/python/ql/src/Classes/ShouldBeContextManager.ql +ql/python/ql/src/Classes/UndefinedClassAttribute.ql +ql/python/ql/src/Classes/UselessClass.ql +ql/python/ql/src/Expressions/NonPortableComparisonUsingIs.ql +ql/python/ql/src/Filters/ClassifyFiles.ql +ql/python/ql/src/Functions/ReturnValueIgnored.ql +ql/python/ql/src/Imports/ImportShadowedByLoopVar.ql +ql/python/ql/src/Imports/ImportStarUsed.ql +ql/python/ql/src/Imports/Imports.ql +ql/python/ql/src/Lexical/FCommentedOutCode.ql +ql/python/ql/src/Lexical/ToDoComment.ql +ql/python/ql/src/Metrics/CLinesOfCode.ql +ql/python/ql/src/Metrics/ClassAfferentCoupling.ql +ql/python/ql/src/Metrics/ClassEfferentCoupling.ql +ql/python/ql/src/Metrics/CommentRatio.ql +ql/python/ql/src/Metrics/CyclomaticComplexity.ql +ql/python/ql/src/Metrics/Dependencies/ExternalDependencies.ql +ql/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql +ql/python/ql/src/Metrics/DirectImports.ql +ql/python/ql/src/Metrics/DocStringRatio.ql +ql/python/ql/src/Metrics/External/CommitDisplayStrings.ql +ql/python/ql/src/Metrics/External/CommitSourceLinks.ql +ql/python/ql/src/Metrics/FClasses.ql +ql/python/ql/src/Metrics/FFunctionsAndMethods.ql +ql/python/ql/src/Metrics/FLines.ql +ql/python/ql/src/Metrics/FLinesOfCode.ql +ql/python/ql/src/Metrics/FLinesOfComments.ql +ql/python/ql/src/Metrics/FLinesOfDuplicatedCode.ql +ql/python/ql/src/Metrics/FLinesOfSimilarCode.ql +ql/python/ql/src/Metrics/FNumberOfTests.ql +ql/python/ql/src/Metrics/FunctionNumberOfCalls.ql +ql/python/ql/src/Metrics/FunctionStatementNestingDepth.ql +ql/python/ql/src/Metrics/History/HChurn.ql +ql/python/ql/src/Metrics/History/HLinesAdded.ql +ql/python/ql/src/Metrics/History/HLinesDeleted.ql +ql/python/ql/src/Metrics/History/HNumberOfAuthors.ql +ql/python/ql/src/Metrics/History/HNumberOfCoCommits.ql +ql/python/ql/src/Metrics/History/HNumberOfCommits.ql +ql/python/ql/src/Metrics/History/HNumberOfReCommits.ql +ql/python/ql/src/Metrics/History/HNumberOfRecentAuthors.ql +ql/python/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql +ql/python/ql/src/Metrics/History/HNumberOfRecentCommits.ql +ql/python/ql/src/Metrics/Internal/CallableDisplayStrings.ql +ql/python/ql/src/Metrics/Internal/CallableExtents.ql +ql/python/ql/src/Metrics/Internal/CallableSourceLinks.ql +ql/python/ql/src/Metrics/Internal/ClassDisplayStrings.ql +ql/python/ql/src/Metrics/Internal/ClassExtents.ql +ql/python/ql/src/Metrics/Internal/ClassSourceLinks.ql +ql/python/ql/src/Metrics/Internal/TypeAnnotations.ql +ql/python/ql/src/Metrics/LackofCohesionInMethodsCK.ql +ql/python/ql/src/Metrics/LackofCohesionInMethodsHM.ql +ql/python/ql/src/Metrics/ModuleAfferentCoupling.ql +ql/python/ql/src/Metrics/ModuleEfferentCoupling.ql +ql/python/ql/src/Metrics/NumberOfParametersWithoutDefault.ql +ql/python/ql/src/Metrics/NumberOfStatements.ql +ql/python/ql/src/Metrics/TransitiveImports.ql +ql/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql +ql/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql +ql/python/ql/src/Statements/AssertLiteralConstant.ql +ql/python/ql/src/Statements/C_StyleParentheses.ql +ql/python/ql/src/Statements/DocStrings.ql +ql/python/ql/src/Statements/ExecUsed.ql +ql/python/ql/src/Statements/StringConcatenationInLoop.ql +ql/python/ql/src/Variables/Global.ql +ql/python/ql/src/Variables/ShadowBuiltin.ql +ql/python/ql/src/Variables/ShadowGlobal.ql +ql/python/ql/src/Variables/UndefinedGlobal.ql +ql/python/ql/src/Variables/UnusedParameter.ql +ql/python/ql/src/analysis/CallGraphEfficiency.ql +ql/python/ql/src/analysis/CallGraphMarginalEfficiency.ql +ql/python/ql/src/analysis/Consistency.ql +ql/python/ql/src/analysis/ContextEfficiency.ql +ql/python/ql/src/analysis/ContextMarginalEfficiency.ql +ql/python/ql/src/analysis/Definitions.ql +ql/python/ql/src/analysis/Efficiency.ql +ql/python/ql/src/analysis/FailedInference.ql +ql/python/ql/src/analysis/ImportFailure.ql +ql/python/ql/src/analysis/KeyPointsToFailure.ql +ql/python/ql/src/analysis/PointsToFailure.ql +ql/python/ql/src/analysis/Pruned.ql +ql/python/ql/src/analysis/RatioOfDefinitions.ql +ql/python/ql/src/analysis/Summary.ql +ql/python/ql/src/analysis/TypeHierarchyFailure.ql +ql/python/ql/src/analysis/TypeInferenceFailure.ql +ql/python/ql/src/experimental/Classes/NamingConventionsClasses.ql +ql/python/ql/src/experimental/Functions/NamingConventionsFunctions.ql +ql/python/ql/src/experimental/Security/CWE-022/ZipSlip.ql +ql/python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.ql +ql/python/ql/src/experimental/Security/CWE-022bis/UnsafeUnpack.ql +ql/python/ql/src/experimental/Security/CWE-074/remoteCommandExecution/RemoteCommandExecution.ql +ql/python/ql/src/experimental/Security/CWE-079/EmailXss.ql +ql/python/ql/src/experimental/Security/CWE-091/XsltInjection.ql +ql/python/ql/src/experimental/Security/CWE-094/Js2Py.ql +ql/python/ql/src/experimental/Security/CWE-1236/CsvInjection.ql +ql/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidation.ql +ql/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql +ql/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.ql +ql/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.ql +ql/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.ql +ql/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.ql +ql/python/ql/src/experimental/Security/CWE-287-ConstantSecretKey/WebAppConstantSecretKey.ql +ql/python/ql/src/experimental/Security/CWE-287/ImproperLdapAuth.ql +ql/python/ql/src/experimental/Security/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql +ql/python/ql/src/experimental/Security/CWE-338/InsecureRandomness.ql +ql/python/ql/src/experimental/Security/CWE-340/TokenBuiltFromUUID.ql +ql/python/ql/src/experimental/Security/CWE-346/CorsBypass.ql +ql/python/ql/src/experimental/Security/CWE-347/JWTEmptyKeyOrAlgorithm.ql +ql/python/ql/src/experimental/Security/CWE-347/JWTMissingSecretOrPublicKeyVerification.ql +ql/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql +ql/python/ql/src/experimental/Security/CWE-409/DecompressionBombs.ql +ql/python/ql/src/experimental/Security/CWE-522/LdapInsecureAuth.ql +ql/python/ql/src/experimental/Security/CWE-611/SimpleXmlRpcServer.ql +ql/python/ql/src/experimental/Security/CWE-770/UnicodeDoS.ql +ql/python/ql/src/experimental/Security/CWE-942/CorsMisconfigurationMiddleware.ql +ql/python/ql/src/experimental/cryptography/example_alerts/UnknownAsymmetricKeyGen.ql +ql/python/ql/src/experimental/cryptography/example_alerts/WeakAsymmetricKeyGen.ql +ql/python/ql/src/experimental/cryptography/example_alerts/WeakAsymmetricPadding.ql +ql/python/ql/src/experimental/cryptography/example_alerts/WeakBlockMode.ql +ql/python/ql/src/experimental/cryptography/example_alerts/WeakBlockModeIVorNonce.ql +ql/python/ql/src/experimental/cryptography/example_alerts/WeakEllipticCurve.ql +ql/python/ql/src/experimental/cryptography/example_alerts/WeakHashes.ql +ql/python/ql/src/experimental/cryptography/example_alerts/WeakKDFAlgorithm.ql +ql/python/ql/src/experimental/cryptography/example_alerts/WeakKDFIteration.ql +ql/python/ql/src/experimental/cryptography/example_alerts/WeakKDFKeyLength.ql +ql/python/ql/src/experimental/cryptography/example_alerts/WeakKDFMode.ql +ql/python/ql/src/experimental/cryptography/example_alerts/WeakKDFSaltGen.ql +ql/python/ql/src/experimental/cryptography/example_alerts/WeakKDFSaltSize.ql +ql/python/ql/src/experimental/cryptography/example_alerts/WeakSymmetricEncryption.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/AllAsymmetricAlgorithms.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/AllCryptoAlgorithms.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/AsymmetricEncryptionAlgorithms.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/AsymmetricKeyGenOperation.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/AsymmetricPaddingAlgorithms.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/AuthenticatedEncryptionAlgorithms.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/BlockModeAlgorithms.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/BlockModeKnownIVsOrNonces.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/BlockModeUnknownIVsOrNonces.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/EllipticCurveAlgorithms.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/HashingAlgorithms.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/KeyDerivationAlgorithms.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/KeyExchangeAlgorithms.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/SigningAlgorithms.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/SymmetricEncryptionAlgorithms.ql +ql/python/ql/src/experimental/cryptography/inventory/new_models/SymmetricPaddingAlgorithms.ql +ql/python/ql/src/experimental/cryptography/inventory/old_models/AllCryptoAlgorithms.ql +ql/python/ql/src/experimental/cryptography/inventory/old_models/BlockModeAlgorithms.ql +ql/python/ql/src/experimental/cryptography/inventory/old_models/HashingAlgorithms.ql +ql/python/ql/src/external/DuplicateBlock.ql +ql/python/ql/src/external/DuplicateFunction.ql +ql/python/ql/src/external/MostlyDuplicateClass.ql +ql/python/ql/src/external/MostlyDuplicateFile.ql +ql/python/ql/src/external/MostlySimilarFile.ql +ql/python/ql/src/external/SimilarFunction.ql +ql/python/ql/src/meta/ClassHierarchy/Find.ql +ql/python/ql/src/meta/alerts/InterestingTaintSinks.ql +ql/python/ql/src/meta/alerts/RemoteFlowSources.ql +ql/python/ql/src/meta/alerts/RemoteFlowSourcesReach.ql +ql/python/ql/src/meta/alerts/RequestHandlers.ql +ql/python/ql/src/meta/alerts/TaintSinks.ql +ql/python/ql/src/meta/analysis-quality/CallGraph.ql +ql/python/ql/src/meta/analysis-quality/PointsToResolvableCallRatio.ql +ql/python/ql/src/meta/analysis-quality/PointsToResolvableCalls.ql +ql/python/ql/src/meta/analysis-quality/PointsToResolvableCallsRelevantTarget.ql +ql/python/ql/src/meta/analysis-quality/ResolvableCallCandidates.ql +ql/python/ql/src/meta/analysis-quality/SummarizedCallableCallSites.ql +ql/python/ql/src/meta/analysis-quality/TTCallGraph.ql +ql/python/ql/src/meta/analysis-quality/TTCallGraphMissing.ql +ql/python/ql/src/meta/analysis-quality/TTCallGraphNew.ql +ql/python/ql/src/meta/analysis-quality/TTCallGraphNewAmbiguous.ql +ql/python/ql/src/meta/analysis-quality/TTCallGraphOverview.ql +ql/python/ql/src/meta/analysis-quality/TTCallGraphShared.ql +ql/python/ql/src/meta/debug/DebugStats.ql +ql/python/ql/src/meta/debug/SimpleClassDebug.ql +ql/python/ql/src/utils/modeleditor/FrameworkModeEndpoints.ql diff --git a/python/ql/integration-tests/query-suite/python-code-quality.qls.expected b/python/ql/integration-tests/query-suite/python-code-quality.qls.expected new file mode 100644 index 000000000000..47643f6a3196 --- /dev/null +++ b/python/ql/integration-tests/query-suite/python-code-quality.qls.expected @@ -0,0 +1,4 @@ +ql/python/ql/src/Functions/NonCls.ql +ql/python/ql/src/Functions/NonSelf.ql +ql/python/ql/src/Functions/SignatureSpecialMethods.ql +ql/python/ql/src/Resources/FileNotAlwaysClosed.ql diff --git a/python/ql/integration-tests/query-suite/python-code-scanning.qls.expected b/python/ql/integration-tests/query-suite/python-code-scanning.qls.expected new file mode 100644 index 000000000000..4db5af9c1a2f --- /dev/null +++ b/python/ql/integration-tests/query-suite/python-code-scanning.qls.expected @@ -0,0 +1,43 @@ +ql/python/ql/src/Diagnostics/ExtractedFiles.ql +ql/python/ql/src/Diagnostics/ExtractionWarnings.ql +ql/python/ql/src/Expressions/UseofInput.ql +ql/python/ql/src/Security/CVE-2018-1281/BindToAllInterfaces.ql +ql/python/ql/src/Security/CWE-020/CookieInjection.ql +ql/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql +ql/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql +ql/python/ql/src/Security/CWE-020/OverlyLargeRange.ql +ql/python/ql/src/Security/CWE-022/PathInjection.ql +ql/python/ql/src/Security/CWE-074/TemplateInjection.ql +ql/python/ql/src/Security/CWE-078/CommandInjection.ql +ql/python/ql/src/Security/CWE-079/ReflectedXss.ql +ql/python/ql/src/Security/CWE-089/SqlInjection.ql +ql/python/ql/src/Security/CWE-090/LdapInjection.ql +ql/python/ql/src/Security/CWE-094/CodeInjection.ql +ql/python/ql/src/Security/CWE-113/HeaderInjection.ql +ql/python/ql/src/Security/CWE-116/BadTagFilter.ql +ql/python/ql/src/Security/CWE-209/StackTraceExposure.ql +ql/python/ql/src/Security/CWE-215/FlaskDebug.ql +ql/python/ql/src/Security/CWE-285/PamAuthorization.ql +ql/python/ql/src/Security/CWE-295/MissingHostKeyValidation.ql +ql/python/ql/src/Security/CWE-312/CleartextLogging.ql +ql/python/ql/src/Security/CWE-312/CleartextStorage.ql +ql/python/ql/src/Security/CWE-326/WeakCryptoKey.ql +ql/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql +ql/python/ql/src/Security/CWE-327/InsecureDefaultProtocol.ql +ql/python/ql/src/Security/CWE-327/InsecureProtocol.ql +ql/python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.ql +ql/python/ql/src/Security/CWE-352/CSRFProtectionDisabled.ql +ql/python/ql/src/Security/CWE-377/InsecureTemporaryFile.ql +ql/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql +ql/python/ql/src/Security/CWE-601/UrlRedirect.ql +ql/python/ql/src/Security/CWE-611/Xxe.ql +ql/python/ql/src/Security/CWE-614/InsecureCookie.ql +ql/python/ql/src/Security/CWE-643/XpathInjection.ql +ql/python/ql/src/Security/CWE-730/PolynomialReDoS.ql +ql/python/ql/src/Security/CWE-730/ReDoS.ql +ql/python/ql/src/Security/CWE-730/RegexInjection.ql +ql/python/ql/src/Security/CWE-776/XmlBomb.ql +ql/python/ql/src/Security/CWE-918/FullServerSideRequestForgery.ql +ql/python/ql/src/Security/CWE-943/NoSqlInjection.ql +ql/python/ql/src/Summary/LinesOfCode.ql +ql/python/ql/src/Summary/LinesOfUserCode.ql diff --git a/python/ql/integration-tests/query-suite/python-security-and-quality.qls.expected b/python/ql/integration-tests/query-suite/python-security-and-quality.qls.expected new file mode 100644 index 000000000000..4560c92f36d6 --- /dev/null +++ b/python/ql/integration-tests/query-suite/python-security-and-quality.qls.expected @@ -0,0 +1,173 @@ +ql/python/ql/src/Classes/ConflictingAttributesInBaseClasses.ql +ql/python/ql/src/Classes/DefineEqualsWhenAddingAttributes.ql +ql/python/ql/src/Classes/EqualsOrHash.ql +ql/python/ql/src/Classes/EqualsOrNotEquals.ql +ql/python/ql/src/Classes/IncompleteOrdering.ql +ql/python/ql/src/Classes/InconsistentMRO.ql +ql/python/ql/src/Classes/InitCallsSubclassMethod.ql +ql/python/ql/src/Classes/MissingCallToDel.ql +ql/python/ql/src/Classes/MissingCallToInit.ql +ql/python/ql/src/Classes/MutatingDescriptor.ql +ql/python/ql/src/Classes/OverwritingAttributeInSuperClass.ql +ql/python/ql/src/Classes/PropertyInOldStyleClass.ql +ql/python/ql/src/Classes/SlotsInOldStyleClass.ql +ql/python/ql/src/Classes/SubclassShadowing.ql +ql/python/ql/src/Classes/SuperInOldStyleClass.ql +ql/python/ql/src/Classes/SuperclassDelCalledMultipleTimes.ql +ql/python/ql/src/Classes/SuperclassInitCalledMultipleTimes.ql +ql/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql +ql/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql +ql/python/ql/src/Diagnostics/ExtractedFiles.ql +ql/python/ql/src/Diagnostics/ExtractionWarnings.ql +ql/python/ql/src/Exceptions/CatchingBaseException.ql +ql/python/ql/src/Exceptions/EmptyExcept.ql +ql/python/ql/src/Exceptions/IllegalExceptionHandlerType.ql +ql/python/ql/src/Exceptions/IllegalRaise.ql +ql/python/ql/src/Exceptions/IncorrectExceptOrder.ql +ql/python/ql/src/Exceptions/NotImplementedIsNotAnException.ql +ql/python/ql/src/Exceptions/RaisingTuple.ql +ql/python/ql/src/Exceptions/UnguardedNextInGenerator.ql +ql/python/ql/src/Expressions/CallToSuperWrongClass.ql +ql/python/ql/src/Expressions/CompareConstants.ql +ql/python/ql/src/Expressions/CompareIdenticalValues.ql +ql/python/ql/src/Expressions/CompareIdenticalValuesMissingSelf.ql +ql/python/ql/src/Expressions/Comparisons/UselessComparisonTest.ql +ql/python/ql/src/Expressions/ContainsNonContainer.ql +ql/python/ql/src/Expressions/DuplicateKeyInDictionaryLiteral.ql +ql/python/ql/src/Expressions/EqualsNone.ql +ql/python/ql/src/Expressions/ExpectedMappingForFormatString.ql +ql/python/ql/src/Expressions/ExplicitCallToDel.ql +ql/python/ql/src/Expressions/Formatting/MixedExplicitImplicitIn3101Format.ql +ql/python/ql/src/Expressions/Formatting/UnusedArgumentIn3101Format.ql +ql/python/ql/src/Expressions/Formatting/UnusedNamedArgumentIn3101Format.ql +ql/python/ql/src/Expressions/Formatting/WrongNameInArgumentsFor3101Format.ql +ql/python/ql/src/Expressions/Formatting/WrongNumberArgumentsFor3101Format.ql +ql/python/ql/src/Expressions/HashedButNoHash.ql +ql/python/ql/src/Expressions/IncorrectComparisonUsingIs.ql +ql/python/ql/src/Expressions/NonCallableCalled.ql +ql/python/ql/src/Expressions/Regex/BackspaceEscape.ql +ql/python/ql/src/Expressions/Regex/DuplicateCharacterInSet.ql +ql/python/ql/src/Expressions/Regex/MissingPartSpecialGroup.ql +ql/python/ql/src/Expressions/Regex/UnmatchableCaret.ql +ql/python/ql/src/Expressions/Regex/UnmatchableDollar.ql +ql/python/ql/src/Expressions/TruncatedDivision.ql +ql/python/ql/src/Expressions/UnintentionalImplicitStringConcatenation.ql +ql/python/ql/src/Expressions/UnnecessaryLambda.ql +ql/python/ql/src/Expressions/UnsupportedFormatCharacter.ql +ql/python/ql/src/Expressions/UseofApply.ql +ql/python/ql/src/Expressions/UseofInput.ql +ql/python/ql/src/Expressions/WrongNameForArgumentInCall.ql +ql/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql +ql/python/ql/src/Expressions/WrongNumberArgumentsInCall.ql +ql/python/ql/src/Functions/ConsistentReturns.ql +ql/python/ql/src/Functions/DeprecatedSliceMethod.ql +ql/python/ql/src/Functions/ExplicitReturnInInit.ql +ql/python/ql/src/Functions/IncorrectRaiseInSpecialMethod.ql +ql/python/ql/src/Functions/IncorrectlyOverriddenMethod.ql +ql/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql +ql/python/ql/src/Functions/InitIsGenerator.ql +ql/python/ql/src/Functions/IterReturnsNonIterator.ql +ql/python/ql/src/Functions/IterReturnsNonSelf.ql +ql/python/ql/src/Functions/ModificationOfParameterWithDefault.ql +ql/python/ql/src/Functions/NonCls.ql +ql/python/ql/src/Functions/NonSelf.ql +ql/python/ql/src/Functions/OverlyComplexDelMethod.ql +ql/python/ql/src/Functions/ReturnConsistentTupleSizes.ql +ql/python/ql/src/Functions/SignatureOverriddenMethod.ql +ql/python/ql/src/Functions/SignatureSpecialMethods.ql +ql/python/ql/src/Functions/UseImplicitNoneReturnValue.ql +ql/python/ql/src/Imports/CyclicImport.ql +ql/python/ql/src/Imports/DeprecatedModule.ql +ql/python/ql/src/Imports/EncodingError.ql +ql/python/ql/src/Imports/FromImportOfMutableAttribute.ql +ql/python/ql/src/Imports/ImportandImportFrom.ql +ql/python/ql/src/Imports/ModuleImportsItself.ql +ql/python/ql/src/Imports/ModuleLevelCyclicImport.ql +ql/python/ql/src/Imports/MultipleImports.ql +ql/python/ql/src/Imports/SyntaxError.ql +ql/python/ql/src/Imports/UnintentionalImport.ql +ql/python/ql/src/Imports/UnusedImport.ql +ql/python/ql/src/Lexical/CommentedOutCode.ql +ql/python/ql/src/Lexical/OldOctalLiteral.ql +ql/python/ql/src/Numerics/Pythagorean.ql +ql/python/ql/src/Resources/FileNotAlwaysClosed.ql +ql/python/ql/src/Security/CVE-2018-1281/BindToAllInterfaces.ql +ql/python/ql/src/Security/CWE-020/CookieInjection.ql +ql/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql +ql/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql +ql/python/ql/src/Security/CWE-020/OverlyLargeRange.ql +ql/python/ql/src/Security/CWE-022/PathInjection.ql +ql/python/ql/src/Security/CWE-022/TarSlip.ql +ql/python/ql/src/Security/CWE-074/TemplateInjection.ql +ql/python/ql/src/Security/CWE-078/CommandInjection.ql +ql/python/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql +ql/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.ql +ql/python/ql/src/Security/CWE-079/ReflectedXss.ql +ql/python/ql/src/Security/CWE-089/SqlInjection.ql +ql/python/ql/src/Security/CWE-090/LdapInjection.ql +ql/python/ql/src/Security/CWE-094/CodeInjection.ql +ql/python/ql/src/Security/CWE-113/HeaderInjection.ql +ql/python/ql/src/Security/CWE-116/BadTagFilter.ql +ql/python/ql/src/Security/CWE-117/LogInjection.ql +ql/python/ql/src/Security/CWE-209/StackTraceExposure.ql +ql/python/ql/src/Security/CWE-215/FlaskDebug.ql +ql/python/ql/src/Security/CWE-285/PamAuthorization.ql +ql/python/ql/src/Security/CWE-295/MissingHostKeyValidation.ql +ql/python/ql/src/Security/CWE-295/RequestWithoutValidation.ql +ql/python/ql/src/Security/CWE-312/CleartextLogging.ql +ql/python/ql/src/Security/CWE-312/CleartextStorage.ql +ql/python/ql/src/Security/CWE-326/WeakCryptoKey.ql +ql/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql +ql/python/ql/src/Security/CWE-327/InsecureDefaultProtocol.ql +ql/python/ql/src/Security/CWE-327/InsecureProtocol.ql +ql/python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.ql +ql/python/ql/src/Security/CWE-352/CSRFProtectionDisabled.ql +ql/python/ql/src/Security/CWE-377/InsecureTemporaryFile.ql +ql/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql +ql/python/ql/src/Security/CWE-601/UrlRedirect.ql +ql/python/ql/src/Security/CWE-611/Xxe.ql +ql/python/ql/src/Security/CWE-614/InsecureCookie.ql +ql/python/ql/src/Security/CWE-643/XpathInjection.ql +ql/python/ql/src/Security/CWE-730/PolynomialReDoS.ql +ql/python/ql/src/Security/CWE-730/ReDoS.ql +ql/python/ql/src/Security/CWE-730/RegexInjection.ql +ql/python/ql/src/Security/CWE-732/WeakFilePermissions.ql +ql/python/ql/src/Security/CWE-776/XmlBomb.ql +ql/python/ql/src/Security/CWE-798/HardcodedCredentials.ql +ql/python/ql/src/Security/CWE-918/FullServerSideRequestForgery.ql +ql/python/ql/src/Security/CWE-918/PartialServerSideRequestForgery.ql +ql/python/ql/src/Security/CWE-943/NoSqlInjection.ql +ql/python/ql/src/Statements/AssertOnTuple.ql +ql/python/ql/src/Statements/BreakOrReturnInFinally.ql +ql/python/ql/src/Statements/ConstantInConditional.ql +ql/python/ql/src/Statements/IterableStringOrSequence.ql +ql/python/ql/src/Statements/MismatchInMultipleAssignment.ql +ql/python/ql/src/Statements/ModificationOfLocals.ql +ql/python/ql/src/Statements/NestedLoopsSameVariable.ql +ql/python/ql/src/Statements/NestedLoopsSameVariableWithReuse.ql +ql/python/ql/src/Statements/NonIteratorInForLoop.ql +ql/python/ql/src/Statements/RedundantAssignment.ql +ql/python/ql/src/Statements/ReturnOrYieldOutsideFunction.ql +ql/python/ql/src/Statements/ShouldUseWithStatement.ql +ql/python/ql/src/Statements/SideEffectInAssert.ql +ql/python/ql/src/Statements/StatementNoEffect.ql +ql/python/ql/src/Statements/TopLevelPrint.ql +ql/python/ql/src/Statements/UnnecessaryDelete.ql +ql/python/ql/src/Statements/UnnecessaryElseClause.ql +ql/python/ql/src/Statements/UnnecessaryPass.ql +ql/python/ql/src/Statements/UnreachableCode.ql +ql/python/ql/src/Statements/UnusedExceptionObject.ql +ql/python/ql/src/Statements/UseOfExit.ql +ql/python/ql/src/Summary/LinesOfCode.ql +ql/python/ql/src/Summary/LinesOfUserCode.ql +ql/python/ql/src/Testing/ImpreciseAssert.ql +ql/python/ql/src/Variables/GlobalAtModuleLevel.ql +ql/python/ql/src/Variables/LeakingListComprehension.ql +ql/python/ql/src/Variables/LoopVariableCapture/LoopVariableCapture.ql +ql/python/ql/src/Variables/MultiplyDefined.ql +ql/python/ql/src/Variables/SuspiciousUnusedLoopIterationVariable.ql +ql/python/ql/src/Variables/UndefinedExport.ql +ql/python/ql/src/Variables/UndefinedPlaceHolder.ql +ql/python/ql/src/Variables/UninitializedLocal.ql +ql/python/ql/src/Variables/UnusedLocalVariable.ql +ql/python/ql/src/Variables/UnusedModuleVariable.ql diff --git a/python/ql/integration-tests/query-suite/python-security-extended.qls.expected b/python/ql/integration-tests/query-suite/python-security-extended.qls.expected new file mode 100644 index 000000000000..398da79f01e4 --- /dev/null +++ b/python/ql/integration-tests/query-suite/python-security-extended.qls.expected @@ -0,0 +1,51 @@ +ql/python/ql/src/Diagnostics/ExtractedFiles.ql +ql/python/ql/src/Diagnostics/ExtractionWarnings.ql +ql/python/ql/src/Expressions/UseofInput.ql +ql/python/ql/src/Security/CVE-2018-1281/BindToAllInterfaces.ql +ql/python/ql/src/Security/CWE-020/CookieInjection.ql +ql/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql +ql/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql +ql/python/ql/src/Security/CWE-020/OverlyLargeRange.ql +ql/python/ql/src/Security/CWE-022/PathInjection.ql +ql/python/ql/src/Security/CWE-022/TarSlip.ql +ql/python/ql/src/Security/CWE-074/TemplateInjection.ql +ql/python/ql/src/Security/CWE-078/CommandInjection.ql +ql/python/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql +ql/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.ql +ql/python/ql/src/Security/CWE-079/ReflectedXss.ql +ql/python/ql/src/Security/CWE-089/SqlInjection.ql +ql/python/ql/src/Security/CWE-090/LdapInjection.ql +ql/python/ql/src/Security/CWE-094/CodeInjection.ql +ql/python/ql/src/Security/CWE-113/HeaderInjection.ql +ql/python/ql/src/Security/CWE-116/BadTagFilter.ql +ql/python/ql/src/Security/CWE-117/LogInjection.ql +ql/python/ql/src/Security/CWE-209/StackTraceExposure.ql +ql/python/ql/src/Security/CWE-215/FlaskDebug.ql +ql/python/ql/src/Security/CWE-285/PamAuthorization.ql +ql/python/ql/src/Security/CWE-295/MissingHostKeyValidation.ql +ql/python/ql/src/Security/CWE-295/RequestWithoutValidation.ql +ql/python/ql/src/Security/CWE-312/CleartextLogging.ql +ql/python/ql/src/Security/CWE-312/CleartextStorage.ql +ql/python/ql/src/Security/CWE-326/WeakCryptoKey.ql +ql/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql +ql/python/ql/src/Security/CWE-327/InsecureDefaultProtocol.ql +ql/python/ql/src/Security/CWE-327/InsecureProtocol.ql +ql/python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.ql +ql/python/ql/src/Security/CWE-352/CSRFProtectionDisabled.ql +ql/python/ql/src/Security/CWE-377/InsecureTemporaryFile.ql +ql/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql +ql/python/ql/src/Security/CWE-601/UrlRedirect.ql +ql/python/ql/src/Security/CWE-611/Xxe.ql +ql/python/ql/src/Security/CWE-614/InsecureCookie.ql +ql/python/ql/src/Security/CWE-643/XpathInjection.ql +ql/python/ql/src/Security/CWE-730/PolynomialReDoS.ql +ql/python/ql/src/Security/CWE-730/ReDoS.ql +ql/python/ql/src/Security/CWE-730/RegexInjection.ql +ql/python/ql/src/Security/CWE-732/WeakFilePermissions.ql +ql/python/ql/src/Security/CWE-776/XmlBomb.ql +ql/python/ql/src/Security/CWE-798/HardcodedCredentials.ql +ql/python/ql/src/Security/CWE-918/FullServerSideRequestForgery.ql +ql/python/ql/src/Security/CWE-918/PartialServerSideRequestForgery.ql +ql/python/ql/src/Security/CWE-943/NoSqlInjection.ql +ql/python/ql/src/Summary/LinesOfCode.ql +ql/python/ql/src/Summary/LinesOfUserCode.ql diff --git a/python/ql/integration-tests/query-suite/test.py b/python/ql/integration-tests/query-suite/test.py new file mode 100644 index 000000000000..940d79bc3616 --- /dev/null +++ b/python/ql/integration-tests/query-suite/test.py @@ -0,0 +1,14 @@ +import runs_on +import pytest +from query_suites import * + +well_known_query_suites = ['python-code-quality.qls', 'python-security-and-quality.qls', 'python-security-extended.qls', 'python-code-scanning.qls'] + +@runs_on.posix +@pytest.mark.parametrize("query_suite", well_known_query_suites) +def test(codeql, python, check_query_suite, query_suite): + check_query_suite(query_suite) + +@runs_on.posix +def test_not_included_queries(codeql, python, check_queries_not_included): + check_queries_not_included('python', well_known_query_suites) From e73031c688ce21d610766aae6b275507c96d59c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Vajk?= Date: Mon, 28 Apr 2025 10:42:01 +0200 Subject: [PATCH 127/336] Update cpp/ql/integration-tests/query-suite/not_included_in_qls.expected Co-authored-by: Michael Nebel --- .../integration-tests/query-suite/not_included_in_qls.expected | 2 -- 1 file changed, 2 deletions(-) diff --git a/cpp/ql/integration-tests/query-suite/not_included_in_qls.expected b/cpp/ql/integration-tests/query-suite/not_included_in_qls.expected index 393f35606cbf..68b8c8b0ab46 100644 --- a/cpp/ql/integration-tests/query-suite/not_included_in_qls.expected +++ b/cpp/ql/integration-tests/query-suite/not_included_in_qls.expected @@ -441,8 +441,6 @@ ql/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 213.ql ql/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 214.ql ql/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 215.ql ql/cpp/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql -ql/cpp/ql/src/utils/modelgenerator/CaptureMixedNeutralModels.ql -ql/cpp/ql/src/utils/modelgenerator/CaptureMixedSummaryModels.ql ql/cpp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql ql/cpp/ql/src/utils/modelgenerator/CaptureSinkModels.ql ql/cpp/ql/src/utils/modelgenerator/CaptureSourceModels.ql From eb059969e3f345dba5c9a30d4aec994891a39afa Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 24 Apr 2025 09:12:48 +0200 Subject: [PATCH 128/336] Move getAChildContainer one scope up --- shared/util/codeql/util/FileSystem.qll | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shared/util/codeql/util/FileSystem.qll b/shared/util/codeql/util/FileSystem.qll index 8eb372e0c24a..e4d32e14dbdb 100644 --- a/shared/util/codeql/util/FileSystem.qll +++ b/shared/util/codeql/util/FileSystem.qll @@ -221,6 +221,12 @@ module Make { /** Provides logic related to `Folder`s. */ module Folder { + pragma[nomagic] + private Container getAChildContainer(Container c, string baseName) { + result = c.getAChildContainer() and + baseName = result.getBaseName() + } + /** Holds if `relativePath` needs to be appended to `f`. */ signature predicate shouldAppendSig(Folder f, string relativePath); @@ -239,12 +245,6 @@ module Make { result = 0 } - pragma[nomagic] - private Container getAChildContainer(Container c, string baseName) { - result = c.getAChildContainer() and - baseName = result.getBaseName() - } - pragma[nomagic] private Container appendStep(Folder f, string relativePath, int i) { i = -1 and From 2ce01bfb9a190a69b014d3b0b490ca72d92ff3b8 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 24 Apr 2025 09:23:32 +0200 Subject: [PATCH 129/336] Add Folder::Resolve as a generalisation of Folder::Append --- shared/util/codeql/util/FileSystem.qll | 149 ++++++++++++++++++++----- 1 file changed, 123 insertions(+), 26 deletions(-) diff --git a/shared/util/codeql/util/FileSystem.qll b/shared/util/codeql/util/FileSystem.qll index e4d32e14dbdb..2b120faaacea 100644 --- a/shared/util/codeql/util/FileSystem.qll +++ b/shared/util/codeql/util/FileSystem.qll @@ -232,46 +232,143 @@ module Make { /** Provides the `append` predicate for appending a relative path onto a folder. */ module Append { + private module Config implements ResolveSig { + predicate shouldResolve(Container c, string name) { shouldAppend(c, name) } + } + + predicate append = Resolve::resolve/2; + } + + /** + * Signature for modules to pass to `Resolve`. + */ + signature module ResolveSig { + /** + * Holds if `path` should be resolved to a file or folder, relative to `base`. + */ + predicate shouldResolve(Container base, string path); + + /** + * Gets an additional file or folder to consider a child of `base`. + */ + default Container getAnAdditionalChild(Container base, string name) { none() } + + /** + * Holds if `component` may be treated as `.` if it does not match a child. + */ + default predicate isOptionalPathComponent(string component) { none() } + + /** + * Holds if globs should be interpreted in the paths being resolved. + * + * The following types of globs are supported: + * - `*` (matches any child) + * - `**` (matches any child recursively) + * - Complex patterns like `foo-*.txt` are also supported + */ + default predicate allowGlobs() { none() } + + /** + * Gets an alternative path segment to try if `segment` did not match a child. + * + * The motivating use-case is to map compiler-generated file names back to their sources files, + * for example, `foo.min.js` could be mapped to `foo.ts`. + */ + bindingset[segment] + default string rewritePathSegment(string segment) { none() } + } + + /** + * Provides a mechanism for resolving file paths relative to a given directory. + */ + module Resolve { + private import Config + pragma[nomagic] - private string getComponent(string relativePath, int i) { - shouldAppend(_, relativePath) and - result = relativePath.replaceAll("\\", "/").regexpFind("[^/]+", i, _) + private string getPathSegment(string path, int n) { + shouldResolve(_, path) and + result = path.replaceAll("\\", "/").splitAt("/", n) } - private int getNumberOfComponents(string relativePath) { - result = strictcount(int i | exists(getComponent(relativePath, i)) | i) + pragma[nomagic] + private string getPathSegmentAsGlobRegexp(string segment) { + allowGlobs() and + segment = getPathSegment(_, _) and + segment.matches("%*%") and + not segment = ["*", "**"] and // these are special-cased + result = segment.regexpReplaceAll("[^a-zA-Z0-9*]", "\\\\$0").replaceAll("*", ".*") + } + + pragma[nomagic] + private int getNumPathSegment(string path) { + result = strictcount(int n | exists(getPathSegment(path, n))) + } + + private Container getChild(Container base, string name) { + result = getAChildContainer(base, name) or - relativePath = "" and - result = 0 + result = getAnAdditionalChild(base, name) } pragma[nomagic] - private Container appendStep(Folder f, string relativePath, int i) { - i = -1 and - shouldAppend(f, relativePath) and - result = f + private Container resolve(Container base, string path, int n) { + shouldResolve(base, path) and n = 0 and result = base + or + exists(Container current, string segment | + current = resolve(base, path, n - 1) and + segment = getPathSegment(path, n - 1) + | + result = getChild(current, segment) + or + segment = [".", ""] and + result = current + or + segment = ".." and + result = current.getParentContainer() + or + not exists(getChild(current, segment)) and + ( + isOptionalPathComponent(segment) and + result = current + or + result = getChild(current, rewritePathSegment(segment)) + ) + or + allowGlobs() and + ( + segment = "*" and + result = getChild(current, _) + or + segment = "**" and // allow empty match + result = current + or + exists(string name | + result = getChild(current, name) and + name.regexpMatch(getPathSegmentAsGlobRegexp(segment)) + ) + ) + ) or - exists(Container mid, string comp | - mid = appendStep(f, relativePath, i - 1) and - comp = getComponent(relativePath, i) and - if comp = ".." - then result = mid.getParentContainer() - else - if comp = "." - then result = mid - else result = getAChildContainer(mid, comp) + exists(Container current, string segment | + current = resolve(base, path, n) and + segment = getPathSegment(path, n) + | + // Follow child without advancing 'n' + allowGlobs() and + segment = "**" and + result = getChild(current, _) ) } /** - * Gets the file or folder obtained by appending `relativePath` onto `f`. + * Gets the file or folder that `path` resolves to when resolved from `base`. + * + * Only has results for the `(base, path)` pairs provided by `shouldResolve` + * in the instantiation of this module. */ pragma[nomagic] - Container append(Folder f, string relativePath) { - exists(int last | - last = getNumberOfComponents(relativePath) - 1 and - result = appendStep(f, relativePath, last) - ) + Container resolve(Container base, string path) { + result = resolve(base, path, getNumPathSegment(path)) } } } From ec9d15bb79fdd3d127b9fadba84c6a30d7e83ff5 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 24 Apr 2025 09:05:36 +0200 Subject: [PATCH 130/336] JS: Make shared Folder module visible --- javascript/ql/lib/semmle/javascript/Files.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/Files.qll b/javascript/ql/lib/semmle/javascript/Files.qll index 88513f087ae0..9febb67117d9 100644 --- a/javascript/ql/lib/semmle/javascript/Files.qll +++ b/javascript/ql/lib/semmle/javascript/Files.qll @@ -29,6 +29,8 @@ private module Impl = Make; class Container = Impl::Container; +module Folder = Impl::Folder; + /** A folder. */ class Folder extends Container, Impl::Folder { /** Gets the file or subfolder in this folder that has the given `name`, if any. */ From 89fd9a4dd5b535cbaf1195c885f2a792767cf8c0 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 29 Apr 2025 12:02:37 +0200 Subject: [PATCH 131/336] C#/Java/Rust: Change the tag for the model generator debugging queries. --- .../modelgenerator/debug/CaptureSummaryModelsPartialPath.ql | 2 +- .../src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql | 2 +- .../modelgenerator/debug/CaptureSummaryModelsPartialPath.ql | 2 +- .../src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql | 2 +- .../modelgenerator/debug/CaptureSummaryModelsPartialPath.ql | 2 +- .../src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql b/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql index 2aa2eafe69e1..beb14cd8e627 100644 --- a/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql +++ b/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql @@ -5,7 +5,7 @@ * @precision low * @id csharp/utils/modelgenerator/summary-models-partial-path * @severity info - * @tags modelgenerator + * @tags debugmodelgenerator */ import csharp diff --git a/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql b/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql index d2df7382a514..e3de78767eaa 100644 --- a/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql +++ b/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql @@ -5,7 +5,7 @@ * @precision low * @id csharp/utils/modelgenerator/summary-models-path * @severity warning - * @tags modelgenerator + * @tags debugmodelgenerator */ import csharp diff --git a/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql b/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql index a9dd1d2384ea..8895fdaefbb3 100644 --- a/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql +++ b/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql @@ -5,7 +5,7 @@ * @precision low * @id java/utils/modelgenerator/summary-models-partial-path * @severity info - * @tags modelgenerator + * @tags debugmodelgenerator */ import java diff --git a/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql b/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql index 36de195573ba..8f6bf1c1f531 100644 --- a/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql +++ b/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql @@ -5,7 +5,7 @@ * @precision low * @id java/utils/modelgenerator/summary-models-path * @severity warning - * @tags modelgenerator + * @tags debugmodelgenerator */ import java diff --git a/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql b/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql index fc557c91207b..eb0cd638b534 100644 --- a/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql +++ b/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql @@ -5,7 +5,7 @@ * @precision low * @id rust/utils/modelgenerator/summary-models-partial-path * @severity info - * @tags modelgenerator + * @tags debugmodelgenerator */ private import codeql.rust.dataflow.DataFlow diff --git a/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql b/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql index 38437d0346f8..1ddec1ff618b 100644 --- a/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql +++ b/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql @@ -5,7 +5,7 @@ * @precision low * @id rust/utils/modelgenerator/summary-models-path * @severity warning - * @tags modelgenerator + * @tags debugmodelgenerator */ private import codeql.rust.dataflow.DataFlow From 8c0b0c480010a47a8f8416e7e1c39e565be82352 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 24 Apr 2025 09:03:21 +0200 Subject: [PATCH 132/336] JS: Ensure json files are extracted properly in tests --- .../semmle/js/extractor/JSONExtractor.java | 2 +- .../src/com/semmle/js/extractor/Main.java | 7 +- .../AST/Decorators/printAst.expected | 31 ++- .../MissingTypeRoot/test.expected | 1 + .../TypeRootFile/test.expected | 1 + .../TSConfigReferences/test.expected | 2 + .../TypeScript/Types/printAst.expected | 244 ++++++++++-------- 7 files changed, 176 insertions(+), 112 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/JSONExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/JSONExtractor.java index c2cad57c3c96..1ca4eeb26096 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/JSONExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/JSONExtractor.java @@ -29,7 +29,7 @@ public Context(Label parent, int childIndex) { private final boolean tolerateParseErrors; public JSONExtractor(ExtractorConfig config) { - this.tolerateParseErrors = config.isTolerateParseErrors(); + this.tolerateParseErrors = true; } @Override diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index 45691d1d7f42..d4f377f15476 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -301,9 +301,14 @@ public void setupMatchers(ArgsParser ap) { // only extract HTML and JS by default addIncludesFor(includes, FileType.HTML); addIncludesFor(includes, FileType.JS); + includes.add("**/.babelrc*.json"); + // extract TypeScript if `--typescript` or `--typescript-full` was specified - if (getTypeScriptMode(ap) != TypeScriptMode.NONE) addIncludesFor(includes, FileType.TYPESCRIPT); + if (getTypeScriptMode(ap) != TypeScriptMode.NONE) { + addIncludesFor(includes, FileType.TYPESCRIPT); + includes.add("**/tsconfig*.json"); + } // add explicit include patterns for (String pattern : ap.getZeroOrMore(P_INCLUDE)) diff --git a/javascript/ql/test/library-tests/AST/Decorators/printAst.expected b/javascript/ql/test/library-tests/AST/Decorators/printAst.expected index 5cbec5ec8830..1c426948b1d8 100644 --- a/javascript/ql/test/library-tests/AST/Decorators/printAst.expected +++ b/javascript/ql/test/library-tests/AST/Decorators/printAst.expected @@ -1,8 +1,17 @@ nodes | file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | | file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | +| tsconfig.json:1:1:7:1 | [JsonObject] {compilerOptions: ...} | semmle.label | [JsonObject] {compilerOptions: ...} | +| tsconfig.json:1:1:7:1 | [JsonObject] {compilerOptions: ...} | semmle.order | 1 | +| tsconfig.json:2:24:4:5 | [JsonObject] {experimentalDecorators: ...} | semmle.label | [JsonObject] {experimentalDecorators: ...} | +| tsconfig.json:3:35:3:38 | [JsonBoolean] true | semmle.label | [JsonBoolean] true | +| tsconfig.json:5:16:5:26 | [JsonArray] ["**/*.ts"] | semmle.label | [JsonArray] ["**/*.ts"] | +| tsconfig.json:5:17:5:25 | [JsonString] "**/*.ts" | semmle.label | [JsonString] "**/*.ts" | +| tsconfig.json:6:12:6:28 | [JsonArray] ["es2015", ...] | semmle.label | [JsonArray] ["es2015", ...] | +| tsconfig.json:6:13:6:20 | [JsonString] "es2015" | semmle.label | [JsonString] "es2015" | +| tsconfig.json:6:23:6:27 | [JsonString] "dom" | semmle.label | [JsonString] "dom" | | tst.ts:1:1:1:22 | [DeclStmt] const Dec = ... | semmle.label | [DeclStmt] const Dec = ... | -| tst.ts:1:1:1:22 | [DeclStmt] const Dec = ... | semmle.order | 1 | +| tst.ts:1:1:1:22 | [DeclStmt] const Dec = ... | semmle.order | 2 | | tst.ts:1:7:1:9 | [VarDecl] Dec | semmle.label | [VarDecl] Dec | | tst.ts:1:7:1:21 | [VariableDeclarator] Dec: any = null | semmle.label | [VariableDeclarator] Dec: any = null | | tst.ts:1:12:1:14 | [KeywordTypeExpr] any | semmle.label | [KeywordTypeExpr] any | @@ -11,7 +20,7 @@ nodes | tst.ts:3:2:3:4 | [VarRef] Dec | semmle.label | [VarRef] Dec | | tst.ts:3:2:3:6 | [CallExpr] Dec() | semmle.label | [CallExpr] Dec() | | tst.ts:4:1:8:1 | [ExportDeclaration] export ... id {} } | semmle.label | [ExportDeclaration] export ... id {} } | -| tst.ts:4:1:8:1 | [ExportDeclaration] export ... id {} } | semmle.order | 2 | +| tst.ts:4:1:8:1 | [ExportDeclaration] export ... id {} } | semmle.order | 3 | | tst.ts:4:8:8:1 | [ClassDefinition,TypeDefinition] class O ... id {} } | semmle.label | [ClassDefinition,TypeDefinition] class O ... id {} } | | tst.ts:4:14:4:30 | [VarDecl] OperatorResolvers | semmle.label | [VarDecl] OperatorResolvers | | tst.ts:4:32:4:31 | [BlockStmt] {} | semmle.label | [BlockStmt] {} | @@ -30,7 +39,7 @@ nodes | tst.ts:7:16:7:19 | [KeywordTypeExpr] void | semmle.label | [KeywordTypeExpr] void | | tst.ts:7:21:7:22 | [BlockStmt] {} | semmle.label | [BlockStmt] {} | | tst.ts:10:1:10:41 | [DeclStmt] const createMethodDecorator = ... | semmle.label | [DeclStmt] const createMethodDecorator = ... | -| tst.ts:10:1:10:41 | [DeclStmt] const createMethodDecorator = ... | semmle.order | 3 | +| tst.ts:10:1:10:41 | [DeclStmt] const createMethodDecorator = ... | semmle.order | 4 | | tst.ts:10:7:10:27 | [VarDecl] createMethodDecorator | semmle.label | [VarDecl] createMethodDecorator | | tst.ts:10:7:10:40 | [VariableDeclarator] createM ... = null | semmle.label | [VariableDeclarator] createM ... = null | | tst.ts:10:31:10:33 | [KeywordTypeExpr] any | semmle.label | [KeywordTypeExpr] any | @@ -38,7 +47,7 @@ nodes | tst.ts:12:1:12:21 | [VarRef] createMethodDecorator | semmle.label | [VarRef] createMethodDecorator | | tst.ts:12:1:14:2 | [CallExpr] createM ... { }) | semmle.label | [CallExpr] createM ... { }) | | tst.ts:12:1:14:3 | [ExprStmt] createM ... }); | semmle.label | [ExprStmt] createM ... }); | -| tst.ts:12:1:14:3 | [ExprStmt] createM ... }); | semmle.order | 4 | +| tst.ts:12:1:14:3 | [ExprStmt] createM ... }); | semmle.order | 5 | | tst.ts:12:23:14:1 | [ArrowFunctionExpr] ({ args ... { } | semmle.label | [ArrowFunctionExpr] ({ args ... { } | | tst.ts:12:24:12:40 | [ObjectPattern,Parameter] { args, context } | semmle.label | [ObjectPattern,Parameter] { args, context } | | tst.ts:12:26:12:29 | [Label] args | semmle.label | [Label] args | @@ -56,6 +65,20 @@ edges | file://:0:0:0:0 | (Parameters) | tst.ts:12:24:12:40 | [ObjectPattern,Parameter] { args, context } | semmle.order | 0 | | file://:0:0:0:0 | (Parameters) | tst.ts:12:43:12:46 | [SimpleParameter] next | semmle.label | 1 | | file://:0:0:0:0 | (Parameters) | tst.ts:12:43:12:46 | [SimpleParameter] next | semmle.order | 1 | +| tsconfig.json:1:1:7:1 | [JsonObject] {compilerOptions: ...} | tsconfig.json:2:24:4:5 | [JsonObject] {experimentalDecorators: ...} | semmle.label | 0 | +| tsconfig.json:1:1:7:1 | [JsonObject] {compilerOptions: ...} | tsconfig.json:2:24:4:5 | [JsonObject] {experimentalDecorators: ...} | semmle.order | 0 | +| tsconfig.json:1:1:7:1 | [JsonObject] {compilerOptions: ...} | tsconfig.json:5:16:5:26 | [JsonArray] ["**/*.ts"] | semmle.label | 1 | +| tsconfig.json:1:1:7:1 | [JsonObject] {compilerOptions: ...} | tsconfig.json:5:16:5:26 | [JsonArray] ["**/*.ts"] | semmle.order | 1 | +| tsconfig.json:1:1:7:1 | [JsonObject] {compilerOptions: ...} | tsconfig.json:6:12:6:28 | [JsonArray] ["es2015", ...] | semmle.label | 2 | +| tsconfig.json:1:1:7:1 | [JsonObject] {compilerOptions: ...} | tsconfig.json:6:12:6:28 | [JsonArray] ["es2015", ...] | semmle.order | 2 | +| tsconfig.json:2:24:4:5 | [JsonObject] {experimentalDecorators: ...} | tsconfig.json:3:35:3:38 | [JsonBoolean] true | semmle.label | 0 | +| tsconfig.json:2:24:4:5 | [JsonObject] {experimentalDecorators: ...} | tsconfig.json:3:35:3:38 | [JsonBoolean] true | semmle.order | 0 | +| tsconfig.json:5:16:5:26 | [JsonArray] ["**/*.ts"] | tsconfig.json:5:17:5:25 | [JsonString] "**/*.ts" | semmle.label | 0 | +| tsconfig.json:5:16:5:26 | [JsonArray] ["**/*.ts"] | tsconfig.json:5:17:5:25 | [JsonString] "**/*.ts" | semmle.order | 0 | +| tsconfig.json:6:12:6:28 | [JsonArray] ["es2015", ...] | tsconfig.json:6:13:6:20 | [JsonString] "es2015" | semmle.label | 0 | +| tsconfig.json:6:12:6:28 | [JsonArray] ["es2015", ...] | tsconfig.json:6:13:6:20 | [JsonString] "es2015" | semmle.order | 0 | +| tsconfig.json:6:12:6:28 | [JsonArray] ["es2015", ...] | tsconfig.json:6:23:6:27 | [JsonString] "dom" | semmle.label | 1 | +| tsconfig.json:6:12:6:28 | [JsonArray] ["es2015", ...] | tsconfig.json:6:23:6:27 | [JsonString] "dom" | semmle.order | 1 | | tst.ts:1:1:1:22 | [DeclStmt] const Dec = ... | tst.ts:1:7:1:21 | [VariableDeclarator] Dec: any = null | semmle.label | 1 | | tst.ts:1:1:1:22 | [DeclStmt] const Dec = ... | tst.ts:1:7:1:21 | [VariableDeclarator] Dec: any = null | semmle.order | 1 | | tst.ts:1:7:1:21 | [VariableDeclarator] Dec: any = null | tst.ts:1:7:1:9 | [VarDecl] Dec | semmle.label | 1 | diff --git a/javascript/ql/test/library-tests/TypeScript/RegressionTests/MissingTypeRoot/test.expected b/javascript/ql/test/library-tests/TypeScript/RegressionTests/MissingTypeRoot/test.expected index 51c6bdf27ff0..5f7ccb159cd4 100644 --- a/javascript/ql/test/library-tests/TypeScript/RegressionTests/MissingTypeRoot/test.expected +++ b/javascript/ql/test/library-tests/TypeScript/RegressionTests/MissingTypeRoot/test.expected @@ -1 +1,2 @@ +| tsconfig.json:0:0:0:0 | tsconfig.json | | tst.ts:0:0:0:0 | tst.ts | diff --git a/javascript/ql/test/library-tests/TypeScript/RegressionTests/TypeRootFile/test.expected b/javascript/ql/test/library-tests/TypeScript/RegressionTests/TypeRootFile/test.expected index fc88cb47c18d..840934a14d38 100644 --- a/javascript/ql/test/library-tests/TypeScript/RegressionTests/TypeRootFile/test.expected +++ b/javascript/ql/test/library-tests/TypeScript/RegressionTests/TypeRootFile/test.expected @@ -1,2 +1,3 @@ +| tsconfig.json:0:0:0:0 | tsconfig.json | | tst.ts:0:0:0:0 | tst.ts | | typeroot.d.ts:0:0:0:0 | typeroot.d.ts | diff --git a/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/test.expected b/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/test.expected index 18dbed450ba1..47ea4115ae61 100644 --- a/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/test.expected +++ b/javascript/ql/test/library-tests/TypeScript/TSConfigReferences/test.expected @@ -7,3 +7,5 @@ types | string | | void | jsonFiles +| tsconfig.foo.json:0:0:0:0 | tsconfig.foo.json | +| tsconfig.json:0:0:0:0 | tsconfig.json | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected b/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected index 04d6e6247ff0..3860acf0afb3 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected +++ b/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected @@ -206,50 +206,62 @@ nodes | middle-rest.ts:3:8:3:11 | [Literal] true | semmle.label | [Literal] true | | middle-rest.ts:3:14:3:20 | [Literal] "hello" | semmle.label | [Literal] "hello" | | middle-rest.ts:3:23:3:25 | [Literal] 123 | semmle.label | [Literal] 123 | +| tsconfig.json:1:1:9:1 | [JsonObject] {compilerOptions: ...} | semmle.label | [JsonObject] {compilerOptions: ...} | +| tsconfig.json:1:1:9:1 | [JsonObject] {compilerOptions: ...} | semmle.order | 18 | +| tsconfig.json:2:22:8:3 | [JsonObject] {module: ...} | semmle.label | [JsonObject] {module: ...} | +| tsconfig.json:3:15:3:22 | [JsonString] "esnext" | semmle.label | [JsonString] "esnext" | +| tsconfig.json:4:15:4:22 | [JsonString] "esnext" | semmle.label | [JsonString] "esnext" | +| tsconfig.json:5:12:5:28 | [JsonArray] ["dom", ...] | semmle.label | [JsonArray] ["dom", ...] | +| tsconfig.json:5:13:5:17 | [JsonString] "dom" | semmle.label | [JsonString] "dom" | +| tsconfig.json:5:20:5:27 | [JsonString] "esnext" | semmle.label | [JsonString] "esnext" | +| tsconfig.json:6:26:6:29 | [JsonBoolean] true | semmle.label | [JsonBoolean] true | +| tsconfig.json:7:23:7:34 | [JsonArray] [".ios", ...] | semmle.label | [JsonArray] [".ios", ...] | +| tsconfig.json:7:24:7:29 | [JsonString] ".ios" | semmle.label | [JsonString] ".ios" | +| tsconfig.json:7:32:7:33 | [JsonString] "" | semmle.label | [JsonString] "" | | tst.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; | -| tst.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 18 | +| tst.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 19 | | tst.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy | | tst.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy | | tst.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" | | tst.ts:3:1:3:19 | [DeclStmt] var numVar = ... | semmle.label | [DeclStmt] var numVar = ... | -| tst.ts:3:1:3:19 | [DeclStmt] var numVar = ... | semmle.order | 19 | +| tst.ts:3:1:3:19 | [DeclStmt] var numVar = ... | semmle.order | 20 | | tst.ts:3:5:3:10 | [VarDecl] numVar | semmle.label | [VarDecl] numVar | | tst.ts:3:5:3:18 | [VariableDeclarator] numVar: number | semmle.label | [VariableDeclarator] numVar: number | | tst.ts:3:13:3:18 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | tst.ts:5:1:5:18 | [DeclStmt] var num1 = ... | semmle.label | [DeclStmt] var num1 = ... | -| tst.ts:5:1:5:18 | [DeclStmt] var num1 = ... | semmle.order | 20 | +| tst.ts:5:1:5:18 | [DeclStmt] var num1 = ... | semmle.order | 21 | | tst.ts:5:5:5:8 | [VarDecl] num1 | semmle.label | [VarDecl] num1 | | tst.ts:5:5:5:17 | [VariableDeclarator] num1 = numVar | semmle.label | [VariableDeclarator] num1 = numVar | | tst.ts:5:12:5:17 | [VarRef] numVar | semmle.label | [VarRef] numVar | | tst.ts:6:1:6:13 | [DeclStmt] var num2 = ... | semmle.label | [DeclStmt] var num2 = ... | -| tst.ts:6:1:6:13 | [DeclStmt] var num2 = ... | semmle.order | 21 | +| tst.ts:6:1:6:13 | [DeclStmt] var num2 = ... | semmle.order | 22 | | tst.ts:6:5:6:8 | [VarDecl] num2 | semmle.label | [VarDecl] num2 | | tst.ts:6:5:6:12 | [VariableDeclarator] num2 = 5 | semmle.label | [VariableDeclarator] num2 = 5 | | tst.ts:6:12:6:12 | [Literal] 5 | semmle.label | [Literal] 5 | | tst.ts:7:1:7:23 | [DeclStmt] var num3 = ... | semmle.label | [DeclStmt] var num3 = ... | -| tst.ts:7:1:7:23 | [DeclStmt] var num3 = ... | semmle.order | 22 | +| tst.ts:7:1:7:23 | [DeclStmt] var num3 = ... | semmle.order | 23 | | tst.ts:7:5:7:8 | [VarDecl] num3 | semmle.label | [VarDecl] num3 | | tst.ts:7:5:7:22 | [VariableDeclarator] num3 = num1 + num2 | semmle.label | [VariableDeclarator] num3 = num1 + num2 | | tst.ts:7:12:7:15 | [VarRef] num1 | semmle.label | [VarRef] num1 | | tst.ts:7:12:7:22 | [BinaryExpr] num1 + num2 | semmle.label | [BinaryExpr] num1 + num2 | | tst.ts:7:19:7:22 | [VarRef] num2 | semmle.label | [VarRef] num2 | | tst.ts:9:1:9:19 | [DeclStmt] var strVar = ... | semmle.label | [DeclStmt] var strVar = ... | -| tst.ts:9:1:9:19 | [DeclStmt] var strVar = ... | semmle.order | 23 | +| tst.ts:9:1:9:19 | [DeclStmt] var strVar = ... | semmle.order | 24 | | tst.ts:9:5:9:10 | [VarDecl] strVar | semmle.label | [VarDecl] strVar | | tst.ts:9:5:9:18 | [VariableDeclarator] strVar: string | semmle.label | [VariableDeclarator] strVar: string | | tst.ts:9:13:9:18 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | | tst.ts:10:1:10:20 | [DeclStmt] var hello = ... | semmle.label | [DeclStmt] var hello = ... | -| tst.ts:10:1:10:20 | [DeclStmt] var hello = ... | semmle.order | 24 | +| tst.ts:10:1:10:20 | [DeclStmt] var hello = ... | semmle.order | 25 | | tst.ts:10:5:10:9 | [VarDecl] hello | semmle.label | [VarDecl] hello | | tst.ts:10:5:10:19 | [VariableDeclarator] hello = "hello" | semmle.label | [VariableDeclarator] hello = "hello" | | tst.ts:10:13:10:19 | [Literal] "hello" | semmle.label | [Literal] "hello" | | tst.ts:11:1:11:20 | [DeclStmt] var world = ... | semmle.label | [DeclStmt] var world = ... | -| tst.ts:11:1:11:20 | [DeclStmt] var world = ... | semmle.order | 25 | +| tst.ts:11:1:11:20 | [DeclStmt] var world = ... | semmle.order | 26 | | tst.ts:11:5:11:9 | [VarDecl] world | semmle.label | [VarDecl] world | | tst.ts:11:5:11:19 | [VariableDeclarator] world = "world" | semmle.label | [VariableDeclarator] world = "world" | | tst.ts:11:13:11:19 | [Literal] "world" | semmle.label | [Literal] "world" | | tst.ts:12:1:12:30 | [DeclStmt] var msg = ... | semmle.label | [DeclStmt] var msg = ... | -| tst.ts:12:1:12:30 | [DeclStmt] var msg = ... | semmle.order | 26 | +| tst.ts:12:1:12:30 | [DeclStmt] var msg = ... | semmle.order | 27 | | tst.ts:12:5:12:7 | [VarDecl] msg | semmle.label | [VarDecl] msg | | tst.ts:12:5:12:29 | [VariableDeclarator] msg = h ... + world | semmle.label | [VariableDeclarator] msg = h ... + world | | tst.ts:12:11:12:15 | [VarRef] hello | semmle.label | [VarRef] hello | @@ -258,7 +270,7 @@ nodes | tst.ts:12:19:12:21 | [Literal] " " | semmle.label | [Literal] " " | | tst.ts:12:25:12:29 | [VarRef] world | semmle.label | [VarRef] world | | tst.ts:14:1:14:63 | [FunctionDeclStmt] functio ... + y; } | semmle.label | [FunctionDeclStmt] functio ... + y; } | -| tst.ts:14:1:14:63 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 27 | +| tst.ts:14:1:14:63 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 28 | | tst.ts:14:10:14:15 | [VarDecl] concat | semmle.label | [VarDecl] concat | | tst.ts:14:17:14:17 | [SimpleParameter] x | semmle.label | [SimpleParameter] x | | tst.ts:14:20:14:25 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | @@ -271,7 +283,7 @@ nodes | tst.ts:14:56:14:60 | [BinaryExpr] x + y | semmle.label | [BinaryExpr] x + y | | tst.ts:14:60:14:60 | [VarRef] y | semmle.label | [VarRef] y | | tst.ts:16:1:16:60 | [FunctionDeclStmt] functio ... + y; } | semmle.label | [FunctionDeclStmt] functio ... + y; } | -| tst.ts:16:1:16:60 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 28 | +| tst.ts:16:1:16:60 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 29 | | tst.ts:16:10:16:12 | [VarDecl] add | semmle.label | [VarDecl] add | | tst.ts:16:14:16:14 | [SimpleParameter] x | semmle.label | [SimpleParameter] x | | tst.ts:16:17:16:22 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | @@ -284,7 +296,7 @@ nodes | tst.ts:16:53:16:57 | [BinaryExpr] x + y | semmle.label | [BinaryExpr] x + y | | tst.ts:16:57:16:57 | [VarRef] y | semmle.label | [VarRef] y | | tst.ts:18:1:18:40 | [FunctionDeclStmt] functio ... + y; } | semmle.label | [FunctionDeclStmt] functio ... + y; } | -| tst.ts:18:1:18:40 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 29 | +| tst.ts:18:1:18:40 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 30 | | tst.ts:18:10:18:16 | [VarDecl] untyped | semmle.label | [VarDecl] untyped | | tst.ts:18:18:18:18 | [SimpleParameter] x | semmle.label | [SimpleParameter] x | | tst.ts:18:21:18:21 | [SimpleParameter] y | semmle.label | [SimpleParameter] y | @@ -294,7 +306,7 @@ nodes | tst.ts:18:33:18:37 | [BinaryExpr] x + y | semmle.label | [BinaryExpr] x + y | | tst.ts:18:37:18:37 | [VarRef] y | semmle.label | [VarRef] y | | tst.ts:20:1:20:53 | [FunctionDeclStmt] functio ... + y; } | semmle.label | [FunctionDeclStmt] functio ... + y; } | -| tst.ts:20:1:20:53 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 30 | +| tst.ts:20:1:20:53 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 31 | | tst.ts:20:10:20:21 | [VarDecl] partialTyped | semmle.label | [VarDecl] partialTyped | | tst.ts:20:23:20:23 | [SimpleParameter] x | semmle.label | [SimpleParameter] x | | tst.ts:20:26:20:26 | [SimpleParameter] y | semmle.label | [SimpleParameter] y | @@ -305,7 +317,7 @@ nodes | tst.ts:20:46:20:50 | [BinaryExpr] x + y | semmle.label | [BinaryExpr] x + y | | tst.ts:20:50:20:50 | [VarRef] y | semmle.label | [VarRef] y | | tst.ts:22:1:22:34 | [ForOfStmt] for (le ... 2]) {} | semmle.label | [ForOfStmt] for (le ... 2]) {} | -| tst.ts:22:1:22:34 | [ForOfStmt] for (le ... 2]) {} | semmle.order | 31 | +| tst.ts:22:1:22:34 | [ForOfStmt] for (le ... 2]) {} | semmle.order | 32 | | tst.ts:22:6:22:20 | [DeclStmt] let numFromLoop = ... | semmle.label | [DeclStmt] let numFromLoop = ... | | tst.ts:22:10:22:20 | [VarDecl] numFromLoop | semmle.label | [VarDecl] numFromLoop | | tst.ts:22:10:22:20 | [VariableDeclarator] numFromLoop | semmle.label | [VariableDeclarator] numFromLoop | @@ -314,54 +326,54 @@ nodes | tst.ts:22:29:22:29 | [Literal] 2 | semmle.label | [Literal] 2 | | tst.ts:22:33:22:34 | [BlockStmt] {} | semmle.label | [BlockStmt] {} | | tst.ts:24:1:24:20 | [DeclStmt] let array = ... | semmle.label | [DeclStmt] let array = ... | -| tst.ts:24:1:24:20 | [DeclStmt] let array = ... | semmle.order | 32 | +| tst.ts:24:1:24:20 | [DeclStmt] let array = ... | semmle.order | 33 | | tst.ts:24:5:24:9 | [VarDecl] array | semmle.label | [VarDecl] array | | tst.ts:24:5:24:19 | [VariableDeclarator] array: number[] | semmle.label | [VariableDeclarator] array: number[] | | tst.ts:24:12:24:17 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | tst.ts:24:12:24:19 | [ArrayTypeExpr] number[] | semmle.label | [ArrayTypeExpr] number[] | | tst.ts:26:1:26:25 | [DeclStmt] let voidType = ... | semmle.label | [DeclStmt] let voidType = ... | -| tst.ts:26:1:26:25 | [DeclStmt] let voidType = ... | semmle.order | 33 | +| tst.ts:26:1:26:25 | [DeclStmt] let voidType = ... | semmle.order | 34 | | tst.ts:26:5:26:12 | [VarDecl] voidType | semmle.label | [VarDecl] voidType | | tst.ts:26:5:26:24 | [VariableDeclarator] voidType: () => void | semmle.label | [VariableDeclarator] voidType: () => void | | tst.ts:26:15:26:24 | [FunctionExpr] () => void | semmle.label | [FunctionExpr] () => void | | tst.ts:26:15:26:24 | [FunctionTypeExpr] () => void | semmle.label | [FunctionTypeExpr] () => void | | tst.ts:26:21:26:24 | [KeywordTypeExpr] void | semmle.label | [KeywordTypeExpr] void | | tst.ts:27:1:27:29 | [DeclStmt] let undefinedType = ... | semmle.label | [DeclStmt] let undefinedType = ... | -| tst.ts:27:1:27:29 | [DeclStmt] let undefinedType = ... | semmle.order | 34 | +| tst.ts:27:1:27:29 | [DeclStmt] let undefinedType = ... | semmle.order | 35 | | tst.ts:27:5:27:17 | [VarDecl] undefinedType | semmle.label | [VarDecl] undefinedType | | tst.ts:27:5:27:28 | [VariableDeclarator] undefin ... defined | semmle.label | [VariableDeclarator] undefin ... defined | | tst.ts:27:20:27:28 | [KeywordTypeExpr] undefined | semmle.label | [KeywordTypeExpr] undefined | | tst.ts:28:1:28:26 | [DeclStmt] let nullType = ... | semmle.label | [DeclStmt] let nullType = ... | -| tst.ts:28:1:28:26 | [DeclStmt] let nullType = ... | semmle.order | 35 | +| tst.ts:28:1:28:26 | [DeclStmt] let nullType = ... | semmle.order | 36 | | tst.ts:28:5:28:12 | [VarDecl] nullType | semmle.label | [VarDecl] nullType | | tst.ts:28:5:28:25 | [VariableDeclarator] nullTyp ... = null | semmle.label | [VariableDeclarator] nullTyp ... = null | | tst.ts:28:15:28:18 | [KeywordTypeExpr] null | semmle.label | [KeywordTypeExpr] null | | tst.ts:28:22:28:25 | [Literal] null | semmle.label | [Literal] null | | tst.ts:29:1:29:27 | [DeclStmt] let neverType = ... | semmle.label | [DeclStmt] let neverType = ... | -| tst.ts:29:1:29:27 | [DeclStmt] let neverType = ... | semmle.order | 36 | +| tst.ts:29:1:29:27 | [DeclStmt] let neverType = ... | semmle.order | 37 | | tst.ts:29:5:29:13 | [VarDecl] neverType | semmle.label | [VarDecl] neverType | | tst.ts:29:5:29:26 | [VariableDeclarator] neverTy ... > never | semmle.label | [VariableDeclarator] neverTy ... > never | | tst.ts:29:16:29:26 | [FunctionExpr] () => never | semmle.label | [FunctionExpr] () => never | | tst.ts:29:16:29:26 | [FunctionTypeExpr] () => never | semmle.label | [FunctionTypeExpr] () => never | | tst.ts:29:22:29:26 | [KeywordTypeExpr] never | semmle.label | [KeywordTypeExpr] never | | tst.ts:30:1:30:23 | [DeclStmt] let symbolType = ... | semmle.label | [DeclStmt] let symbolType = ... | -| tst.ts:30:1:30:23 | [DeclStmt] let symbolType = ... | semmle.order | 37 | +| tst.ts:30:1:30:23 | [DeclStmt] let symbolType = ... | semmle.order | 38 | | tst.ts:30:5:30:14 | [VarDecl] symbolType | semmle.label | [VarDecl] symbolType | | tst.ts:30:5:30:22 | [VariableDeclarator] symbolType: symbol | semmle.label | [VariableDeclarator] symbolType: symbol | | tst.ts:30:17:30:22 | [KeywordTypeExpr] symbol | semmle.label | [KeywordTypeExpr] symbol | | tst.ts:31:1:31:45 | [DeclStmt] const uniqueSymbolType = ... | semmle.label | [DeclStmt] const uniqueSymbolType = ... | -| tst.ts:31:1:31:45 | [DeclStmt] const uniqueSymbolType = ... | semmle.order | 38 | +| tst.ts:31:1:31:45 | [DeclStmt] const uniqueSymbolType = ... | semmle.order | 39 | | tst.ts:31:7:31:22 | [VarDecl] uniqueSymbolType | semmle.label | [VarDecl] uniqueSymbolType | | tst.ts:31:7:31:44 | [VariableDeclarator] uniqueS ... = null | semmle.label | [VariableDeclarator] uniqueS ... = null | | tst.ts:31:25:31:37 | [KeywordTypeExpr] unique symbol | semmle.label | [KeywordTypeExpr] unique symbol | | tst.ts:31:41:31:44 | [Literal] null | semmle.label | [Literal] null | | tst.ts:32:1:32:23 | [DeclStmt] let objectType = ... | semmle.label | [DeclStmt] let objectType = ... | -| tst.ts:32:1:32:23 | [DeclStmt] let objectType = ... | semmle.order | 39 | +| tst.ts:32:1:32:23 | [DeclStmt] let objectType = ... | semmle.order | 40 | | tst.ts:32:5:32:14 | [VarDecl] objectType | semmle.label | [VarDecl] objectType | | tst.ts:32:5:32:22 | [VariableDeclarator] objectType: object | semmle.label | [VariableDeclarator] objectType: object | | tst.ts:32:17:32:22 | [KeywordTypeExpr] object | semmle.label | [KeywordTypeExpr] object | | tst.ts:33:1:33:39 | [DeclStmt] let intersection = ... | semmle.label | [DeclStmt] let intersection = ... | -| tst.ts:33:1:33:39 | [DeclStmt] let intersection = ... | semmle.order | 40 | +| tst.ts:33:1:33:39 | [DeclStmt] let intersection = ... | semmle.order | 41 | | tst.ts:33:5:33:16 | [VarDecl] intersection | semmle.label | [VarDecl] intersection | | tst.ts:33:5:33:38 | [VariableDeclarator] interse ... string} | semmle.label | [VariableDeclarator] interse ... string} | | tst.ts:33:19:33:24 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | @@ -371,14 +383,14 @@ nodes | tst.ts:33:29:33:37 | [FieldDeclaration] x: string | semmle.label | [FieldDeclaration] x: string | | tst.ts:33:32:33:37 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | | tst.ts:34:1:34:28 | [DeclStmt] let tuple = ... | semmle.label | [DeclStmt] let tuple = ... | -| tst.ts:34:1:34:28 | [DeclStmt] let tuple = ... | semmle.order | 41 | +| tst.ts:34:1:34:28 | [DeclStmt] let tuple = ... | semmle.order | 42 | | tst.ts:34:5:34:9 | [VarDecl] tuple | semmle.label | [VarDecl] tuple | | tst.ts:34:5:34:27 | [VariableDeclarator] tuple: ... string] | semmle.label | [VariableDeclarator] tuple: ... string] | | tst.ts:34:12:34:27 | [TupleTypeExpr] [number, string] | semmle.label | [TupleTypeExpr] [number, string] | | tst.ts:34:13:34:18 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | tst.ts:34:21:34:26 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | | tst.ts:36:1:36:56 | [DeclStmt] let tupleWithOptionalElement = ... | semmle.label | [DeclStmt] let tupleWithOptionalElement = ... | -| tst.ts:36:1:36:56 | [DeclStmt] let tupleWithOptionalElement = ... | semmle.order | 42 | +| tst.ts:36:1:36:56 | [DeclStmt] let tupleWithOptionalElement = ... | semmle.order | 43 | | tst.ts:36:5:36:28 | [VarDecl] tupleWithOptionalElement | semmle.label | [VarDecl] tupleWithOptionalElement | | tst.ts:36:5:36:55 | [VariableDeclarator] tupleWi ... umber?] | semmle.label | [VariableDeclarator] tupleWi ... umber?] | | tst.ts:36:31:36:55 | [TupleTypeExpr] [number ... umber?] | semmle.label | [TupleTypeExpr] [number ... umber?] | @@ -387,12 +399,12 @@ nodes | tst.ts:36:48:36:53 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | tst.ts:36:48:36:54 | [OptionalTypeExpr] number? | semmle.label | [OptionalTypeExpr] number? | | tst.ts:37:1:37:19 | [DeclStmt] let emptyTuple = ... | semmle.label | [DeclStmt] let emptyTuple = ... | -| tst.ts:37:1:37:19 | [DeclStmt] let emptyTuple = ... | semmle.order | 43 | +| tst.ts:37:1:37:19 | [DeclStmt] let emptyTuple = ... | semmle.order | 44 | | tst.ts:37:5:37:14 | [VarDecl] emptyTuple | semmle.label | [VarDecl] emptyTuple | | tst.ts:37:5:37:18 | [VariableDeclarator] emptyTuple: [] | semmle.label | [VariableDeclarator] emptyTuple: [] | | tst.ts:37:17:37:18 | [TupleTypeExpr] [] | semmle.label | [TupleTypeExpr] [] | | tst.ts:38:1:38:48 | [DeclStmt] let tupleWithRestElement = ... | semmle.label | [DeclStmt] let tupleWithRestElement = ... | -| tst.ts:38:1:38:48 | [DeclStmt] let tupleWithRestElement = ... | semmle.order | 44 | +| tst.ts:38:1:38:48 | [DeclStmt] let tupleWithRestElement = ... | semmle.order | 45 | | tst.ts:38:5:38:24 | [VarDecl] tupleWithRestElement | semmle.label | [VarDecl] tupleWithRestElement | | tst.ts:38:5:38:47 | [VariableDeclarator] tupleWi ... ring[]] | semmle.label | [VariableDeclarator] tupleWi ... ring[]] | | tst.ts:38:27:38:47 | [TupleTypeExpr] [number ... ring[]] | semmle.label | [TupleTypeExpr] [number ... ring[]] | @@ -401,7 +413,7 @@ nodes | tst.ts:38:39:38:44 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | | tst.ts:38:39:38:46 | [ArrayTypeExpr] string[] | semmle.label | [ArrayTypeExpr] string[] | | tst.ts:39:1:39:69 | [DeclStmt] let tupleWithOptionalAndRestElements = ... | semmle.label | [DeclStmt] let tupleWithOptionalAndRestElements = ... | -| tst.ts:39:1:39:69 | [DeclStmt] let tupleWithOptionalAndRestElements = ... | semmle.order | 45 | +| tst.ts:39:1:39:69 | [DeclStmt] let tupleWithOptionalAndRestElements = ... | semmle.order | 46 | | tst.ts:39:5:39:36 | [VarDecl] tupleWithOptionalAndRestElements | semmle.label | [VarDecl] tupleWithOptionalAndRestElements | | tst.ts:39:5:39:68 | [VariableDeclarator] tupleWi ... mber[]] | semmle.label | [VariableDeclarator] tupleWi ... mber[]] | | tst.ts:39:39:39:68 | [TupleTypeExpr] [number ... mber[]] | semmle.label | [TupleTypeExpr] [number ... mber[]] | @@ -412,12 +424,12 @@ nodes | tst.ts:39:60:39:65 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | tst.ts:39:60:39:67 | [ArrayTypeExpr] number[] | semmle.label | [ArrayTypeExpr] number[] | | tst.ts:40:1:40:25 | [DeclStmt] let unknownType = ... | semmle.label | [DeclStmt] let unknownType = ... | -| tst.ts:40:1:40:25 | [DeclStmt] let unknownType = ... | semmle.order | 46 | +| tst.ts:40:1:40:25 | [DeclStmt] let unknownType = ... | semmle.order | 47 | | tst.ts:40:5:40:15 | [VarDecl] unknownType | semmle.label | [VarDecl] unknownType | | tst.ts:40:5:40:24 | [VariableDeclarator] unknownType: unknown | semmle.label | [VariableDeclarator] unknownType: unknown | | tst.ts:40:18:40:24 | [KeywordTypeExpr] unknown | semmle.label | [KeywordTypeExpr] unknown | | tst.ts:42:1:42:40 | [DeclStmt] let constArrayLiteral = ... | semmle.label | [DeclStmt] let constArrayLiteral = ... | -| tst.ts:42:1:42:40 | [DeclStmt] let constArrayLiteral = ... | semmle.order | 47 | +| tst.ts:42:1:42:40 | [DeclStmt] let constArrayLiteral = ... | semmle.order | 48 | | tst.ts:42:5:42:21 | [VarDecl] constArrayLiteral | semmle.label | [VarDecl] constArrayLiteral | | tst.ts:42:5:42:39 | [VariableDeclarator] constAr ... s const | semmle.label | [VariableDeclarator] constAr ... s const | | tst.ts:42:25:42:30 | [ArrayExpr] [1, 2] | semmle.label | [ArrayExpr] [1, 2] | @@ -426,7 +438,7 @@ nodes | tst.ts:42:29:42:29 | [Literal] 2 | semmle.label | [Literal] 2 | | tst.ts:42:35:42:39 | [KeywordTypeExpr] const | semmle.label | [KeywordTypeExpr] const | | tst.ts:43:1:43:49 | [DeclStmt] let constObjectLiteral = ... | semmle.label | [DeclStmt] let constObjectLiteral = ... | -| tst.ts:43:1:43:49 | [DeclStmt] let constObjectLiteral = ... | semmle.order | 48 | +| tst.ts:43:1:43:49 | [DeclStmt] let constObjectLiteral = ... | semmle.order | 49 | | tst.ts:43:5:43:22 | [VarDecl] constObjectLiteral | semmle.label | [VarDecl] constObjectLiteral | | tst.ts:43:5:43:48 | [VariableDeclarator] constOb ... s const | semmle.label | [VariableDeclarator] constOb ... s const | | tst.ts:43:26:43:39 | [ObjectExpr] {foo: ...} | semmle.label | [ObjectExpr] {foo: ...} | @@ -436,7 +448,7 @@ nodes | tst.ts:43:33:43:37 | [Literal] "foo" | semmle.label | [Literal] "foo" | | tst.ts:43:44:43:48 | [KeywordTypeExpr] const | semmle.label | [KeywordTypeExpr] const | | tst.ts:46:1:51:1 | [TryStmt] try { } ... ; } } | semmle.label | [TryStmt] try { } ... ; } } | -| tst.ts:46:1:51:1 | [TryStmt] try { } ... ; } } | semmle.order | 49 | +| tst.ts:46:1:51:1 | [TryStmt] try { } ... ; } } | semmle.order | 50 | | tst.ts:46:5:46:7 | [BlockStmt] { } | semmle.label | [BlockStmt] { } | | tst.ts:47:1:51:1 | [CatchClause] catch ( ... ; } } | semmle.label | [CatchClause] catch ( ... ; } } | | tst.ts:47:8:47:8 | [SimpleParameter] e | semmle.label | [SimpleParameter] e | @@ -453,21 +465,21 @@ nodes | tst.ts:49:15:49:20 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | | tst.ts:49:24:49:24 | [VarRef] e | semmle.label | [VarRef] e | | tst.ts:54:1:56:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | -| tst.ts:54:1:56:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.order | 50 | +| tst.ts:54:1:56:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.order | 51 | | tst.ts:54:11:54:26 | [Identifier] NonAbstractDummy | semmle.label | [Identifier] NonAbstractDummy | | tst.ts:55:3:55:9 | [Label] getArea | semmle.label | [Label] getArea | | tst.ts:55:3:55:20 | [FunctionExpr] getArea(): number; | semmle.label | [FunctionExpr] getArea(): number; | | tst.ts:55:3:55:20 | [MethodSignature] getArea(): number; | semmle.label | [MethodSignature] getArea(): number; | | tst.ts:55:14:55:19 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | tst.ts:58:1:60:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | -| tst.ts:58:1:60:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.order | 51 | +| tst.ts:58:1:60:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.order | 52 | | tst.ts:58:11:58:17 | [Identifier] HasArea | semmle.label | [Identifier] HasArea | | tst.ts:59:3:59:9 | [Label] getArea | semmle.label | [Label] getArea | | tst.ts:59:3:59:20 | [FunctionExpr] getArea(): number; | semmle.label | [FunctionExpr] getArea(): number; | | tst.ts:59:3:59:20 | [MethodSignature] getArea(): number; | semmle.label | [MethodSignature] getArea(): number; | | tst.ts:59:14:59:19 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | tst.ts:63:1:63:45 | [DeclStmt] let Ctor = ... | semmle.label | [DeclStmt] let Ctor = ... | -| tst.ts:63:1:63:45 | [DeclStmt] let Ctor = ... | semmle.order | 52 | +| tst.ts:63:1:63:45 | [DeclStmt] let Ctor = ... | semmle.order | 53 | | tst.ts:63:5:63:8 | [VarDecl] Ctor | semmle.label | [VarDecl] Ctor | | tst.ts:63:5:63:44 | [VariableDeclarator] Ctor: a ... = Shape | semmle.label | [VariableDeclarator] Ctor: a ... = Shape | | tst.ts:63:11:63:36 | [FunctionExpr] abstrac ... HasArea | semmle.label | [FunctionExpr] abstrac ... HasArea | @@ -475,7 +487,7 @@ nodes | tst.ts:63:30:63:36 | [LocalTypeAccess] HasArea | semmle.label | [LocalTypeAccess] HasArea | | tst.ts:63:40:63:44 | [VarRef] Shape | semmle.label | [VarRef] Shape | | tst.ts:65:1:65:54 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | -| tst.ts:65:1:65:54 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.order | 53 | +| tst.ts:65:1:65:54 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.order | 54 | | tst.ts:65:6:65:12 | [Identifier] MyUnion | semmle.label | [Identifier] MyUnion | | tst.ts:65:16:65:30 | [InterfaceTypeExpr] {myUnion: true} | semmle.label | [InterfaceTypeExpr] {myUnion: true} | | tst.ts:65:16:65:53 | [UnionTypeExpr] {myUnio ... : true} | semmle.label | [UnionTypeExpr] {myUnio ... : true} | @@ -487,7 +499,7 @@ nodes | tst.ts:65:35:65:52 | [FieldDeclaration] stillMyUnion: true | semmle.label | [FieldDeclaration] stillMyUnion: true | | tst.ts:65:49:65:52 | [LiteralTypeExpr] true | semmle.label | [LiteralTypeExpr] true | | tst.ts:66:1:66:38 | [DeclStmt] let union1 = ... | semmle.label | [DeclStmt] let union1 = ... | -| tst.ts:66:1:66:38 | [DeclStmt] let union1 = ... | semmle.order | 54 | +| tst.ts:66:1:66:38 | [DeclStmt] let union1 = ... | semmle.order | 55 | | tst.ts:66:5:66:10 | [VarDecl] union1 | semmle.label | [VarDecl] union1 | | tst.ts:66:5:66:37 | [VariableDeclarator] union1: ... : true} | semmle.label | [VariableDeclarator] union1: ... : true} | | tst.ts:66:13:66:19 | [LocalTypeAccess] MyUnion | semmle.label | [LocalTypeAccess] MyUnion | @@ -496,7 +508,7 @@ nodes | tst.ts:66:24:66:36 | [Property] myUnion: true | semmle.label | [Property] myUnion: true | | tst.ts:66:33:66:36 | [Literal] true | semmle.label | [Literal] true | | tst.ts:68:1:68:49 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | -| tst.ts:68:1:68:49 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.order | 55 | +| tst.ts:68:1:68:49 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.order | 56 | | tst.ts:68:6:68:13 | [Identifier] MyUnion2 | semmle.label | [Identifier] MyUnion2 | | tst.ts:68:17:68:23 | [LocalTypeAccess] MyUnion | semmle.label | [LocalTypeAccess] MyUnion | | tst.ts:68:17:68:48 | [UnionTypeExpr] MyUnion ... : true} | semmle.label | [UnionTypeExpr] MyUnion ... : true} | @@ -505,7 +517,7 @@ nodes | tst.ts:68:28:68:47 | [FieldDeclaration] yetAnotherType: true | semmle.label | [FieldDeclaration] yetAnotherType: true | | tst.ts:68:44:68:47 | [LiteralTypeExpr] true | semmle.label | [LiteralTypeExpr] true | | tst.ts:69:1:69:46 | [DeclStmt] let union2 = ... | semmle.label | [DeclStmt] let union2 = ... | -| tst.ts:69:1:69:46 | [DeclStmt] let union2 = ... | semmle.order | 56 | +| tst.ts:69:1:69:46 | [DeclStmt] let union2 = ... | semmle.order | 57 | | tst.ts:69:5:69:10 | [VarDecl] union2 | semmle.label | [VarDecl] union2 | | tst.ts:69:5:69:45 | [VariableDeclarator] union2: ... : true} | semmle.label | [VariableDeclarator] union2: ... : true} | | tst.ts:69:13:69:20 | [LocalTypeAccess] MyUnion2 | semmle.label | [LocalTypeAccess] MyUnion2 | @@ -514,7 +526,7 @@ nodes | tst.ts:69:25:69:44 | [Property] yetAnotherType: true | semmle.label | [Property] yetAnotherType: true | | tst.ts:69:41:69:44 | [Literal] true | semmle.label | [Literal] true | | tst.ts:71:1:130:1 | [NamespaceDeclaration] module ... } } | semmle.label | [NamespaceDeclaration] module ... } } | -| tst.ts:71:1:130:1 | [NamespaceDeclaration] module ... } } | semmle.order | 57 | +| tst.ts:71:1:130:1 | [NamespaceDeclaration] module ... } } | semmle.order | 58 | | tst.ts:71:8:71:11 | [VarDecl] TS43 | semmle.label | [VarDecl] TS43 | | tst.ts:73:3:76:3 | [InterfaceDeclaration,TypeDefinition] interfa ... n); } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... n); } | | tst.ts:73:13:73:18 | [Identifier] ThingI | semmle.label | [Identifier] ThingI | @@ -679,7 +691,7 @@ nodes | tst.ts:127:14:127:28 | [DotExpr] this.#someValue | semmle.label | [DotExpr] this.#someValue | | tst.ts:127:19:127:28 | [Label] #someValue | semmle.label | [Label] #someValue | | tst.ts:132:1:193:1 | [NamespaceDeclaration] module ... } } | semmle.label | [NamespaceDeclaration] module ... } } | -| tst.ts:132:1:193:1 | [NamespaceDeclaration] module ... } } | semmle.order | 58 | +| tst.ts:132:1:193:1 | [NamespaceDeclaration] module ... } } | semmle.order | 59 | | tst.ts:132:8:132:11 | [VarDecl] TS44 | semmle.label | [VarDecl] TS44 | | tst.ts:133:3:138:3 | [FunctionDeclStmt] functio ... } } | semmle.label | [FunctionDeclStmt] functio ... } } | | tst.ts:133:12:133:14 | [VarDecl] foo | semmle.label | [VarDecl] foo | @@ -870,7 +882,7 @@ nodes | tst.ts:189:19:189:28 | [DotExpr] Foo.#count | semmle.label | [DotExpr] Foo.#count | | tst.ts:189:23:189:28 | [Label] #count | semmle.label | [Label] #count | | tst.ts:195:1:235:1 | [NamespaceDeclaration] module ... } } } | semmle.label | [NamespaceDeclaration] module ... } } } | -| tst.ts:195:1:235:1 | [NamespaceDeclaration] module ... } } } | semmle.order | 59 | +| tst.ts:195:1:235:1 | [NamespaceDeclaration] module ... } } } | semmle.order | 60 | | tst.ts:195:8:195:11 | [VarDecl] TS45 | semmle.label | [VarDecl] TS45 | | tst.ts:197:3:197:36 | [TypeAliasDeclaration,TypeDefinition] type A ... ring>>; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type A ... ring>>; | | tst.ts:197:8:197:8 | [Identifier] A | semmle.label | [Identifier] A | @@ -983,21 +995,21 @@ nodes | tst.ts:232:28:232:38 | [DotExpr] other.#name | semmle.label | [DotExpr] other.#name | | tst.ts:232:34:232:38 | [Label] #name | semmle.label | [Label] #name | | tst.ts:237:1:237:63 | [ImportDeclaration] import ... son" }; | semmle.label | [ImportDeclaration] import ... son" }; | -| tst.ts:237:1:237:63 | [ImportDeclaration] import ... son" }; | semmle.order | 60 | +| tst.ts:237:1:237:63 | [ImportDeclaration] import ... son" }; | semmle.order | 61 | | tst.ts:237:8:237:16 | [ImportSpecifier] * as Foo3 | semmle.label | [ImportSpecifier] * as Foo3 | | tst.ts:237:13:237:16 | [VarDecl] Foo3 | semmle.label | [VarDecl] Foo3 | | tst.ts:237:23:237:40 | [Literal] "./something.json" | semmle.label | [Literal] "./something.json" | | tst.ts:237:47:237:62 | [ObjectExpr] { type: "json" } | semmle.label | [ObjectExpr] { type: "json" } | | tst.ts:237:49:237:60 | [Property] type: "json" | semmle.label | [Property] type: "json" | | tst.ts:238:1:238:19 | [DeclStmt] var foo = ... | semmle.label | [DeclStmt] var foo = ... | -| tst.ts:238:1:238:19 | [DeclStmt] var foo = ... | semmle.order | 61 | +| tst.ts:238:1:238:19 | [DeclStmt] var foo = ... | semmle.order | 62 | | tst.ts:238:5:238:7 | [VarDecl] foo | semmle.label | [VarDecl] foo | | tst.ts:238:5:238:18 | [VariableDeclarator] foo = Foo3.foo | semmle.label | [VariableDeclarator] foo = Foo3.foo | | tst.ts:238:11:238:14 | [VarRef] Foo3 | semmle.label | [VarRef] Foo3 | | tst.ts:238:11:238:18 | [DotExpr] Foo3.foo | semmle.label | [DotExpr] Foo3.foo | | tst.ts:238:16:238:18 | [Label] foo | semmle.label | [Label] foo | | tst.ts:240:1:296:1 | [NamespaceDeclaration] module ... }; } | semmle.label | [NamespaceDeclaration] module ... }; } | -| tst.ts:240:1:296:1 | [NamespaceDeclaration] module ... }; } | semmle.order | 62 | +| tst.ts:240:1:296:1 | [NamespaceDeclaration] module ... }; } | semmle.order | 63 | | tst.ts:240:8:240:11 | [VarDecl] TS46 | semmle.label | [VarDecl] TS46 | | tst.ts:241:3:241:15 | [ClassDefinition,TypeDefinition] class Base {} | semmle.label | [ClassDefinition,TypeDefinition] class Base {} | | tst.ts:241:9:241:12 | [VarDecl] Base | semmle.label | [VarDecl] Base | @@ -1192,13 +1204,13 @@ nodes | tst.ts:293:7:293:24 | [ExprStmt] payload.toFixed(); | semmle.label | [ExprStmt] payload.toFixed(); | | tst.ts:293:15:293:21 | [Label] toFixed | semmle.label | [Label] toFixed | | tst.ts:298:1:298:21 | [DeclStmt] const key = ... | semmle.label | [DeclStmt] const key = ... | -| tst.ts:298:1:298:21 | [DeclStmt] const key = ... | semmle.order | 63 | +| tst.ts:298:1:298:21 | [DeclStmt] const key = ... | semmle.order | 64 | | tst.ts:298:7:298:9 | [VarDecl] key | semmle.label | [VarDecl] key | | tst.ts:298:7:298:20 | [VariableDeclarator] key = Symbol() | semmle.label | [VariableDeclarator] key = Symbol() | | tst.ts:298:13:298:18 | [VarRef] Symbol | semmle.label | [VarRef] Symbol | | tst.ts:298:13:298:20 | [CallExpr] Symbol() | semmle.label | [CallExpr] Symbol() | | tst.ts:300:1:300:58 | [DeclStmt] const numberOrString = ... | semmle.label | [DeclStmt] const numberOrString = ... | -| tst.ts:300:1:300:58 | [DeclStmt] const numberOrString = ... | semmle.order | 64 | +| tst.ts:300:1:300:58 | [DeclStmt] const numberOrString = ... | semmle.order | 65 | | tst.ts:300:7:300:20 | [VarDecl] numberOrString | semmle.label | [VarDecl] numberOrString | | tst.ts:300:7:300:57 | [VariableDeclarator] numberO ... "hello" | semmle.label | [VariableDeclarator] numberO ... "hello" | | tst.ts:300:24:300:27 | [VarRef] Math | semmle.label | [VarRef] Math | @@ -1211,7 +1223,7 @@ nodes | tst.ts:300:46:300:47 | [Literal] 42 | semmle.label | [Literal] 42 | | tst.ts:300:51:300:57 | [Literal] "hello" | semmle.label | [Literal] "hello" | | tst.ts:302:1:304:2 | [DeclStmt] let obj = ... | semmle.label | [DeclStmt] let obj = ... | -| tst.ts:302:1:304:2 | [DeclStmt] let obj = ... | semmle.order | 65 | +| tst.ts:302:1:304:2 | [DeclStmt] let obj = ... | semmle.order | 66 | | tst.ts:302:5:302:7 | [VarDecl] obj | semmle.label | [VarDecl] obj | | tst.ts:302:5:304:1 | [VariableDeclarator] obj = { ... ring, } | semmle.label | [VariableDeclarator] obj = { ... ring, } | | tst.ts:302:11:304:1 | [ObjectExpr] { [ke ... ring, } | semmle.label | [ObjectExpr] { [ke ... ring, } | @@ -1219,7 +1231,7 @@ nodes | tst.ts:303:4:303:6 | [VarRef] key | semmle.label | [VarRef] key | | tst.ts:303:10:303:23 | [VarRef] numberOrString | semmle.label | [VarRef] numberOrString | | tst.ts:306:1:309:1 | [IfStmt] if (typ ... se(); } | semmle.label | [IfStmt] if (typ ... se(); } | -| tst.ts:306:1:309:1 | [IfStmt] if (typ ... se(); } | semmle.order | 66 | +| tst.ts:306:1:309:1 | [IfStmt] if (typ ... se(); } | semmle.order | 67 | | tst.ts:306:5:306:19 | [UnaryExpr] typeof obj[key] | semmle.label | [UnaryExpr] typeof obj[key] | | tst.ts:306:5:306:32 | [BinaryExpr] typeof ... string" | semmle.label | [BinaryExpr] typeof ... string" | | tst.ts:306:12:306:14 | [VarRef] obj | semmle.label | [VarRef] obj | @@ -1239,7 +1251,7 @@ nodes | tst.ts:308:3:308:20 | [ExprStmt] str.toUpperCase(); | semmle.label | [ExprStmt] str.toUpperCase(); | | tst.ts:308:7:308:17 | [Label] toUpperCase | semmle.label | [Label] toUpperCase | | tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | semmle.label | [FunctionDeclStmt] functio ... void {} | -| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | semmle.order | 67 | +| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | semmle.order | 68 | | tst.ts:313:10:313:10 | [VarDecl] f | semmle.label | [VarDecl] f | | tst.ts:313:12:313:12 | [Identifier] T | semmle.label | [Identifier] T | | tst.ts:313:12:313:12 | [TypeParameter] T | semmle.label | [TypeParameter] T | @@ -1262,11 +1274,11 @@ nodes | tst.ts:316:4:316:7 | [KeywordTypeExpr] void | semmle.label | [KeywordTypeExpr] void | | tst.ts:316:9:316:10 | [BlockStmt] {} | semmle.label | [BlockStmt] {} | | tst.ts:316:11:316:11 | [EmptyStmt] ; | semmle.label | [EmptyStmt] ; | -| tst.ts:316:11:316:11 | [EmptyStmt] ; | semmle.order | 68 | +| tst.ts:316:11:316:11 | [EmptyStmt] ; | semmle.order | 69 | | tst.ts:318:1:318:1 | [VarRef] f | semmle.label | [VarRef] f | | tst.ts:318:1:321:2 | [CallExpr] f({ p ... se() }) | semmle.label | [CallExpr] f({ p ... se() }) | | tst.ts:318:1:321:3 | [ExprStmt] f({ p ... e() }); | semmle.label | [ExprStmt] f({ p ... e() }); | -| tst.ts:318:1:321:3 | [ExprStmt] f({ p ... e() }); | semmle.order | 69 | +| tst.ts:318:1:321:3 | [ExprStmt] f({ p ... e() }); | semmle.order | 70 | | tst.ts:318:3:321:1 | [ObjectExpr] {produce: ...} | semmle.label | [ObjectExpr] {produce: ...} | | tst.ts:319:3:319:9 | [Label] produce | semmle.label | [Label] produce | | tst.ts:319:3:319:17 | [Property] produce: n => n | semmle.label | [Property] produce: n => n | @@ -1282,7 +1294,7 @@ nodes | tst.ts:320:17:320:31 | [MethodCallExpr] x.toLowerCase() | semmle.label | [MethodCallExpr] x.toLowerCase() | | tst.ts:320:19:320:29 | [Label] toLowerCase | semmle.label | [Label] toLowerCase | | tst.ts:325:1:325:36 | [DeclStmt] const ErrorMap = ... | semmle.label | [DeclStmt] const ErrorMap = ... | -| tst.ts:325:1:325:36 | [DeclStmt] const ErrorMap = ... | semmle.order | 70 | +| tst.ts:325:1:325:36 | [DeclStmt] const ErrorMap = ... | semmle.order | 71 | | tst.ts:325:7:325:14 | [VarDecl] ErrorMap | semmle.label | [VarDecl] ErrorMap | | tst.ts:325:7:325:35 | [VariableDeclarator] ErrorMa ... Error> | semmle.label | [VariableDeclarator] ErrorMa ... Error> | | tst.ts:325:18:325:20 | [VarRef] Map | semmle.label | [VarRef] Map | @@ -1290,13 +1302,13 @@ nodes | tst.ts:325:22:325:27 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | | tst.ts:325:30:325:34 | [LocalTypeAccess] Error | semmle.label | [LocalTypeAccess] Error | | tst.ts:327:1:327:32 | [DeclStmt] const errorMap = ... | semmle.label | [DeclStmt] const errorMap = ... | -| tst.ts:327:1:327:32 | [DeclStmt] const errorMap = ... | semmle.order | 71 | +| tst.ts:327:1:327:32 | [DeclStmt] const errorMap = ... | semmle.order | 72 | | tst.ts:327:7:327:14 | [VarDecl] errorMap | semmle.label | [VarDecl] errorMap | | tst.ts:327:7:327:31 | [VariableDeclarator] errorMa ... orMap() | semmle.label | [VariableDeclarator] errorMa ... orMap() | | tst.ts:327:18:327:31 | [NewExpr] new ErrorMap() | semmle.label | [NewExpr] new ErrorMap() | | tst.ts:327:22:327:29 | [VarRef] ErrorMap | semmle.label | [VarRef] ErrorMap | | tst.ts:331:1:334:14 | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; | -| tst.ts:331:1:334:14 | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; | semmle.order | 72 | +| tst.ts:331:1:334:14 | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; | semmle.order | 73 | | tst.ts:331:6:331:16 | [Identifier] FirstString | semmle.label | [Identifier] FirstString | | tst.ts:331:18:331:18 | [Identifier] T | semmle.label | [Identifier] T | | tst.ts:331:18:331:18 | [TypeParameter] T | semmle.label | [TypeParameter] T | @@ -1313,7 +1325,7 @@ nodes | tst.ts:333:9:333:9 | [LocalTypeAccess] S | semmle.label | [LocalTypeAccess] S | | tst.ts:334:9:334:13 | [KeywordTypeExpr] never | semmle.label | [KeywordTypeExpr] never | | tst.ts:336:1:336:51 | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; | -| tst.ts:336:1:336:51 | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; | semmle.order | 73 | +| tst.ts:336:1:336:51 | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; | semmle.order | 74 | | tst.ts:336:6:336:6 | [Identifier] F | semmle.label | [Identifier] F | | tst.ts:336:10:336:20 | [LocalTypeAccess] FirstString | semmle.label | [LocalTypeAccess] FirstString | | tst.ts:336:10:336:50 | [GenericTypeExpr] FirstSt ... olean]> | semmle.label | [GenericTypeExpr] FirstSt ... olean]> | @@ -1324,13 +1336,13 @@ nodes | tst.ts:336:34:336:39 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | tst.ts:336:42:336:48 | [KeywordTypeExpr] boolean | semmle.label | [KeywordTypeExpr] boolean | | tst.ts:338:1:338:17 | [DeclStmt] const a = ... | semmle.label | [DeclStmt] const a = ... | -| tst.ts:338:1:338:17 | [DeclStmt] const a = ... | semmle.order | 74 | +| tst.ts:338:1:338:17 | [DeclStmt] const a = ... | semmle.order | 75 | | tst.ts:338:7:338:7 | [VarDecl] a | semmle.label | [VarDecl] a | | tst.ts:338:7:338:16 | [VariableDeclarator] a: F = 'a' | semmle.label | [VariableDeclarator] a: F = 'a' | | tst.ts:338:10:338:10 | [LocalTypeAccess] F | semmle.label | [LocalTypeAccess] F | | tst.ts:338:14:338:16 | [Literal] 'a' | semmle.label | [Literal] 'a' | | tst.ts:342:1:345:1 | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | -| tst.ts:342:1:345:1 | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | semmle.order | 75 | +| tst.ts:342:1:345:1 | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | semmle.order | 76 | | tst.ts:342:11:342:15 | [Identifier] State | semmle.label | [Identifier] State | | tst.ts:342:17:342:24 | [TypeParameter] in out T | semmle.label | [TypeParameter] in out T | | tst.ts:342:24:342:24 | [Identifier] T | semmle.label | [Identifier] T | @@ -1347,7 +1359,7 @@ nodes | tst.ts:344:16:344:16 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | | tst.ts:344:22:344:25 | [KeywordTypeExpr] void | semmle.label | [KeywordTypeExpr] void | | tst.ts:347:1:350:1 | [DeclStmt] const state = ... | semmle.label | [DeclStmt] const state = ... | -| tst.ts:347:1:350:1 | [DeclStmt] const state = ... | semmle.order | 76 | +| tst.ts:347:1:350:1 | [DeclStmt] const state = ... | semmle.order | 77 | | tst.ts:347:7:347:11 | [VarDecl] state | semmle.label | [VarDecl] state | | tst.ts:347:7:350:1 | [VariableDeclarator] state: ... > { } } | semmle.label | [VariableDeclarator] state: ... > { } } | | tst.ts:347:14:347:18 | [LocalTypeAccess] State | semmle.label | [LocalTypeAccess] State | @@ -1364,7 +1376,7 @@ nodes | tst.ts:349:9:349:13 | [SimpleParameter] value | semmle.label | [SimpleParameter] value | | tst.ts:349:19:349:21 | [BlockStmt] { } | semmle.label | [BlockStmt] { } | | tst.ts:352:1:352:29 | [DeclStmt] const fortyTwo = ... | semmle.label | [DeclStmt] const fortyTwo = ... | -| tst.ts:352:1:352:29 | [DeclStmt] const fortyTwo = ... | semmle.order | 77 | +| tst.ts:352:1:352:29 | [DeclStmt] const fortyTwo = ... | semmle.order | 78 | | tst.ts:352:7:352:14 | [VarDecl] fortyTwo | semmle.label | [VarDecl] fortyTwo | | tst.ts:352:7:352:28 | [VariableDeclarator] fortyTw ... e.get() | semmle.label | [VariableDeclarator] fortyTw ... e.get() | | tst.ts:352:18:352:22 | [VarRef] state | semmle.label | [VarRef] state | @@ -1372,7 +1384,7 @@ nodes | tst.ts:352:18:352:28 | [MethodCallExpr] state.get() | semmle.label | [MethodCallExpr] state.get() | | tst.ts:352:24:352:26 | [Label] get | semmle.label | [Label] get | | tst.ts:356:1:356:44 | [ImportDeclaration] import ... S.mjs'; | semmle.label | [ImportDeclaration] import ... S.mjs'; | -| tst.ts:356:1:356:44 | [ImportDeclaration] import ... S.mjs'; | semmle.order | 78 | +| tst.ts:356:1:356:44 | [ImportDeclaration] import ... S.mjs'; | semmle.order | 79 | | tst.ts:356:8:356:18 | [ImportSpecifier] tstModuleES | semmle.label | [ImportSpecifier] tstModuleES | | tst.ts:356:8:356:18 | [VarDecl] tstModuleES | semmle.label | [VarDecl] tstModuleES | | tst.ts:356:25:356:43 | [Literal] './tstModuleES.mjs' | semmle.label | [Literal] './tstModuleES.mjs' | @@ -1380,12 +1392,12 @@ nodes | tst.ts:358:1:358:11 | [DotExpr] console.log | semmle.label | [DotExpr] console.log | | tst.ts:358:1:358:26 | [MethodCallExpr] console ... leES()) | semmle.label | [MethodCallExpr] console ... leES()) | | tst.ts:358:1:358:27 | [ExprStmt] console ... eES()); | semmle.label | [ExprStmt] console ... eES()); | -| tst.ts:358:1:358:27 | [ExprStmt] console ... eES()); | semmle.order | 79 | +| tst.ts:358:1:358:27 | [ExprStmt] console ... eES()); | semmle.order | 80 | | tst.ts:358:9:358:11 | [Label] log | semmle.label | [Label] log | | tst.ts:358:13:358:23 | [VarRef] tstModuleES | semmle.label | [VarRef] tstModuleES | | tst.ts:358:13:358:25 | [CallExpr] tstModuleES() | semmle.label | [CallExpr] tstModuleES() | | tst.ts:360:1:360:50 | [ImportDeclaration] import ... S.cjs'; | semmle.label | [ImportDeclaration] import ... S.cjs'; | -| tst.ts:360:1:360:50 | [ImportDeclaration] import ... S.cjs'; | semmle.order | 80 | +| tst.ts:360:1:360:50 | [ImportDeclaration] import ... S.cjs'; | semmle.order | 81 | | tst.ts:360:10:360:21 | [ImportSpecifier] tstModuleCJS | semmle.label | [ImportSpecifier] tstModuleCJS | | tst.ts:360:10:360:21 | [Label] tstModuleCJS | semmle.label | [Label] tstModuleCJS | | tst.ts:360:10:360:21 | [VarDecl] tstModuleCJS | semmle.label | [VarDecl] tstModuleCJS | @@ -1394,12 +1406,12 @@ nodes | tst.ts:362:1:362:11 | [DotExpr] console.log | semmle.label | [DotExpr] console.log | | tst.ts:362:1:362:27 | [MethodCallExpr] console ... eCJS()) | semmle.label | [MethodCallExpr] console ... eCJS()) | | tst.ts:362:1:362:28 | [ExprStmt] console ... CJS()); | semmle.label | [ExprStmt] console ... CJS()); | -| tst.ts:362:1:362:28 | [ExprStmt] console ... CJS()); | semmle.order | 81 | +| tst.ts:362:1:362:28 | [ExprStmt] console ... CJS()); | semmle.order | 82 | | tst.ts:362:9:362:11 | [Label] log | semmle.label | [Label] log | | tst.ts:362:13:362:24 | [VarRef] tstModuleCJS | semmle.label | [VarRef] tstModuleCJS | | tst.ts:362:13:362:26 | [CallExpr] tstModuleCJS() | semmle.label | [CallExpr] tstModuleCJS() | | tst.ts:368:1:368:34 | [ImportDeclaration] import ... ffixA'; | semmle.label | [ImportDeclaration] import ... ffixA'; | -| tst.ts:368:1:368:34 | [ImportDeclaration] import ... ffixA'; | semmle.order | 82 | +| tst.ts:368:1:368:34 | [ImportDeclaration] import ... ffixA'; | semmle.order | 83 | | tst.ts:368:8:368:13 | [ImportSpecifier] * as A | semmle.label | [ImportSpecifier] * as A | | tst.ts:368:13:368:13 | [VarDecl] A | semmle.label | [VarDecl] A | | tst.ts:368:20:368:33 | [Literal] './tstSuffixA' | semmle.label | [Literal] './tstSuffixA' | @@ -1407,14 +1419,14 @@ nodes | tst.ts:370:1:370:11 | [DotExpr] console.log | semmle.label | [DotExpr] console.log | | tst.ts:370:1:370:29 | [MethodCallExpr] console ... File()) | semmle.label | [MethodCallExpr] console ... File()) | | tst.ts:370:1:370:30 | [ExprStmt] console ... ile()); | semmle.label | [ExprStmt] console ... ile()); | -| tst.ts:370:1:370:30 | [ExprStmt] console ... ile()); | semmle.order | 83 | +| tst.ts:370:1:370:30 | [ExprStmt] console ... ile()); | semmle.order | 84 | | tst.ts:370:9:370:11 | [Label] log | semmle.label | [Label] log | | tst.ts:370:13:370:13 | [VarRef] A | semmle.label | [VarRef] A | | tst.ts:370:13:370:26 | [DotExpr] A.resolvedFile | semmle.label | [DotExpr] A.resolvedFile | | tst.ts:370:13:370:28 | [MethodCallExpr] A.resolvedFile() | semmle.label | [MethodCallExpr] A.resolvedFile() | | tst.ts:370:15:370:26 | [Label] resolvedFile | semmle.label | [Label] resolvedFile | | tst.ts:372:1:372:34 | [ImportDeclaration] import ... ffixB'; | semmle.label | [ImportDeclaration] import ... ffixB'; | -| tst.ts:372:1:372:34 | [ImportDeclaration] import ... ffixB'; | semmle.order | 84 | +| tst.ts:372:1:372:34 | [ImportDeclaration] import ... ffixB'; | semmle.order | 85 | | tst.ts:372:8:372:13 | [ImportSpecifier] * as B | semmle.label | [ImportSpecifier] * as B | | tst.ts:372:13:372:13 | [VarDecl] B | semmle.label | [VarDecl] B | | tst.ts:372:20:372:33 | [Literal] './tstSuffixB' | semmle.label | [Literal] './tstSuffixB' | @@ -1422,14 +1434,14 @@ nodes | tst.ts:374:1:374:11 | [DotExpr] console.log | semmle.label | [DotExpr] console.log | | tst.ts:374:1:374:29 | [MethodCallExpr] console ... File()) | semmle.label | [MethodCallExpr] console ... File()) | | tst.ts:374:1:374:30 | [ExprStmt] console ... ile()); | semmle.label | [ExprStmt] console ... ile()); | -| tst.ts:374:1:374:30 | [ExprStmt] console ... ile()); | semmle.order | 85 | +| tst.ts:374:1:374:30 | [ExprStmt] console ... ile()); | semmle.order | 86 | | tst.ts:374:9:374:11 | [Label] log | semmle.label | [Label] log | | tst.ts:374:13:374:13 | [VarRef] B | semmle.label | [VarRef] B | | tst.ts:374:13:374:26 | [DotExpr] B.resolvedFile | semmle.label | [DotExpr] B.resolvedFile | | tst.ts:374:13:374:28 | [MethodCallExpr] B.resolvedFile() | semmle.label | [MethodCallExpr] B.resolvedFile() | | tst.ts:374:15:374:26 | [Label] resolvedFile | semmle.label | [Label] resolvedFile | | tst.ts:379:1:386:1 | [NamespaceDeclaration] module ... ; } | semmle.label | [NamespaceDeclaration] module ... ; } | -| tst.ts:379:1:386:1 | [NamespaceDeclaration] module ... ; } | semmle.order | 86 | +| tst.ts:379:1:386:1 | [NamespaceDeclaration] module ... ; } | semmle.order | 87 | | tst.ts:379:8:379:11 | [VarDecl] TS48 | semmle.label | [VarDecl] TS48 | | tst.ts:381:5:381:73 | [TypeAliasDeclaration,TypeDefinition] type So ... never; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type So ... never; | | tst.ts:381:10:381:16 | [Identifier] SomeNum | semmle.label | [Identifier] SomeNum | @@ -1468,7 +1480,7 @@ nodes | tst.ts:385:59:385:63 | [Literal] false | semmle.label | [Literal] false | | tst.ts:385:66:385:71 | [Literal] "bye!" | semmle.label | [Literal] "bye!" | | tst.ts:390:1:426:1 | [NamespaceDeclaration] module ... } } } | semmle.label | [NamespaceDeclaration] module ... } } } | -| tst.ts:390:1:426:1 | [NamespaceDeclaration] module ... } } } | semmle.order | 87 | +| tst.ts:390:1:426:1 | [NamespaceDeclaration] module ... } } } | semmle.order | 88 | | tst.ts:390:8:390:11 | [VarDecl] TS49 | semmle.label | [VarDecl] TS49 | | tst.ts:391:3:391:41 | [TypeAliasDeclaration,TypeDefinition] type Co ... "blue"; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Co ... "blue"; | | tst.ts:391:8:391:13 | [Identifier] Colors | semmle.label | [Identifier] Colors | @@ -1565,7 +1577,7 @@ nodes | tst.ts:423:12:423:15 | [Label] name | semmle.label | [Label] name | | tst.ts:423:19:423:22 | [VarRef] name | semmle.label | [VarRef] name | | tst.ts:430:1:468:1 | [NamespaceDeclaration] module ... - "b" } | semmle.label | [NamespaceDeclaration] module ... - "b" } | -| tst.ts:430:1:468:1 | [NamespaceDeclaration] module ... - "b" } | semmle.order | 88 | +| tst.ts:430:1:468:1 | [NamespaceDeclaration] module ... - "b" } | semmle.order | 89 | | tst.ts:430:8:430:11 | [VarDecl] TS50 | semmle.label | [VarDecl] TS50 | | tst.ts:431:5:445:5 | [FunctionDeclStmt] functio ... ; } | semmle.label | [FunctionDeclStmt] functio ... ; } | | tst.ts:431:14:431:25 | [VarDecl] loggedMethod | semmle.label | [VarDecl] loggedMethod | @@ -1715,7 +1727,7 @@ nodes | tst.ts:467:15:467:20 | [IndexExpr] foo[1] | semmle.label | [IndexExpr] foo[1] | | tst.ts:467:19:467:19 | [Literal] 1 | semmle.label | [Literal] 1 | | tst.ts:472:1:484:1 | [NamespaceDeclaration] module ... ng>); } | semmle.label | [NamespaceDeclaration] module ... ng>); } | -| tst.ts:472:1:484:1 | [NamespaceDeclaration] module ... ng>); } | semmle.order | 89 | +| tst.ts:472:1:484:1 | [NamespaceDeclaration] module ... ng>); } | semmle.order | 90 | | tst.ts:472:8:472:11 | [VarDecl] TS52 | semmle.label | [VarDecl] TS52 | | tst.ts:473:5:476:5 | [ClassDefinition,TypeDefinition] class S ... ; } | semmle.label | [ClassDefinition,TypeDefinition] class S ... ; } | | tst.ts:473:11:473:19 | [VarDecl] SomeClass | semmle.label | [VarDecl] SomeClass | @@ -1763,7 +1775,7 @@ nodes | tst.ts:483:46:483:58 | [GenericTypeExpr] Pair3 | semmle.label | [GenericTypeExpr] Pair3 | | tst.ts:483:52:483:57 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | | tst.ts:486:1:496:1 | [NamespaceDeclaration] module ... }); } | semmle.label | [NamespaceDeclaration] module ... }); } | -| tst.ts:486:1:496:1 | [NamespaceDeclaration] module ... }); } | semmle.order | 90 | +| tst.ts:486:1:496:1 | [NamespaceDeclaration] module ... }); } | semmle.order | 91 | | tst.ts:486:8:486:11 | [VarDecl] TS54 | semmle.label | [VarDecl] TS54 | | tst.ts:487:3:489:3 | [FunctionDeclStmt] functio ... 0]; } | semmle.label | [FunctionDeclStmt] functio ... 0]; } | | tst.ts:487:12:487:28 | [VarDecl] createStreetLight | semmle.label | [VarDecl] createStreetLight | @@ -1818,7 +1830,7 @@ nodes | tst.ts:494:28:494:33 | [Literal] "even" | semmle.label | [Literal] "even" | | tst.ts:494:36:494:40 | [Literal] "odd" | semmle.label | [Literal] "odd" | | tst.ts:498:1:511:1 | [NamespaceDeclaration] module ... } } } | semmle.label | [NamespaceDeclaration] module ... } } } | -| tst.ts:498:1:511:1 | [NamespaceDeclaration] module ... } } } | semmle.order | 91 | +| tst.ts:498:1:511:1 | [NamespaceDeclaration] module ... } } } | semmle.order | 92 | | tst.ts:498:8:498:11 | [VarDecl] TS55 | semmle.label | [VarDecl] TS55 | | tst.ts:499:3:500:40 | [DeclStmt] const strings = ... | semmle.label | [DeclStmt] const strings = ... | | tst.ts:499:9:499:15 | [VarDecl] strings | semmle.label | [VarDecl] strings | @@ -1875,7 +1887,7 @@ nodes | tst.ts:508:21:508:23 | [VarRef] key | semmle.label | [VarRef] key | | tst.ts:508:26:508:36 | [Label] toUpperCase | semmle.label | [Label] toUpperCase | | tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | semmle.label | [NamespaceDeclaration] namespa ... type. } | -| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | semmle.order | 92 | +| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | semmle.order | 93 | | tst.ts:513:11:513:14 | [VarDecl] TS57 | semmle.label | [VarDecl] TS57 | | tst.ts:514:3:514:26 | [DeclStmt] const a = ... | semmle.label | [DeclStmt] const a = ... | | tst.ts:514:17:514:17 | [VarDecl] a | semmle.label | [VarDecl] a | @@ -1902,7 +1914,7 @@ nodes | tst.ts:519:23:519:30 | [TypeofTypeExpr] typeof a | semmle.label | [TypeofTypeExpr] typeof a | | tst.ts:519:30:519:30 | [LocalVarTypeAccess] a | semmle.label | [LocalVarTypeAccess] a | | tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.label | [ExportDeclaration] export ... 'b'; } | -| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 93 | +| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 94 | | tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | [FunctionDeclStmt] functio ... 'b'; } | | tstModuleCJS.cts:1:17:1:28 | [VarDecl] tstModuleCJS | semmle.label | [VarDecl] tstModuleCJS | | tstModuleCJS.cts:1:33:1:35 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' | @@ -1920,7 +1932,7 @@ nodes | tstModuleCJS.cts:2:34:2:36 | [Literal] 'a' | semmle.label | [Literal] 'a' | | tstModuleCJS.cts:2:40:2:42 | [Literal] 'b' | semmle.label | [Literal] 'b' | | tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.label | [ExportDeclaration] export ... 'b'; } | -| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 94 | +| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 95 | | tstModuleES.mts:1:16:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | [FunctionDeclStmt] functio ... 'b'; } | | tstModuleES.mts:1:25:1:35 | [VarDecl] tstModuleES | semmle.label | [VarDecl] tstModuleES | | tstModuleES.mts:1:40:1:42 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' | @@ -1938,7 +1950,7 @@ nodes | tstModuleES.mts:2:34:2:36 | [Literal] 'a' | semmle.label | [Literal] 'a' | | tstModuleES.mts:2:40:2:42 | [Literal] 'b' | semmle.label | [Literal] 'b' | | tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } | -| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 95 | +| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 96 | | tstSuffixA.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } | | tstSuffixA.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile | | tstSuffixA.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixA.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixA.ts' | @@ -1946,7 +1958,7 @@ nodes | tstSuffixA.ts:2:5:2:27 | [ReturnStmt] return ... xA.ts'; | semmle.label | [ReturnStmt] return ... xA.ts'; | | tstSuffixA.ts:2:12:2:26 | [Literal] 'tstSuffixA.ts' | semmle.label | [Literal] 'tstSuffixA.ts' | | tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } | -| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 96 | +| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 97 | | tstSuffixB.ios.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } | | tstSuffixB.ios.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile | | tstSuffixB.ios.ts:1:33:1:51 | [LiteralTypeExpr] 'tstSuffixB.ios.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixB.ios.ts' | @@ -1954,7 +1966,7 @@ nodes | tstSuffixB.ios.ts:2:5:2:31 | [ReturnStmt] return ... os.ts'; | semmle.label | [ReturnStmt] return ... os.ts'; | | tstSuffixB.ios.ts:2:12:2:30 | [Literal] 'tstSuffixB.ios.ts' | semmle.label | [Literal] 'tstSuffixB.ios.ts' | | tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } | -| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 97 | +| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 98 | | tstSuffixB.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } | | tstSuffixB.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile | | tstSuffixB.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixB.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixB.ts' | @@ -1962,16 +1974,16 @@ nodes | tstSuffixB.ts:2:5:2:27 | [ReturnStmt] return ... xB.ts'; | semmle.label | [ReturnStmt] return ... xB.ts'; | | tstSuffixB.ts:2:12:2:26 | [Literal] 'tstSuffixB.ts' | semmle.label | [Literal] 'tstSuffixB.ts' | | type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | -| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 98 | +| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 99 | | type_alias.ts:1:6:1:6 | [Identifier] B | semmle.label | [Identifier] B | | type_alias.ts:1:10:1:16 | [KeywordTypeExpr] boolean | semmle.label | [KeywordTypeExpr] boolean | | type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.label | [DeclStmt] var b = ... | -| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 99 | +| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 100 | | type_alias.ts:3:5:3:5 | [VarDecl] b | semmle.label | [VarDecl] b | | type_alias.ts:3:5:3:8 | [VariableDeclarator] b: B | semmle.label | [VariableDeclarator] b: B | | type_alias.ts:3:8:3:8 | [LocalTypeAccess] B | semmle.label | [LocalTypeAccess] B | | type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | -| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.order | 100 | +| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.order | 101 | | type_alias.ts:5:6:5:17 | [Identifier] ValueOrArray | semmle.label | [Identifier] ValueOrArray | | type_alias.ts:5:19:5:19 | [Identifier] T | semmle.label | [Identifier] T | | type_alias.ts:5:19:5:19 | [TypeParameter] T | semmle.label | [TypeParameter] T | @@ -1983,14 +1995,14 @@ nodes | type_alias.ts:5:34:5:48 | [GenericTypeExpr] ValueOrArray | semmle.label | [GenericTypeExpr] ValueOrArray | | type_alias.ts:5:47:5:47 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | | type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.label | [DeclStmt] var c = ... | -| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 101 | +| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 102 | | type_alias.ts:7:5:7:5 | [VarDecl] c | semmle.label | [VarDecl] c | | type_alias.ts:7:5:7:27 | [VariableDeclarator] c: Valu ... number> | semmle.label | [VariableDeclarator] c: Valu ... number> | | type_alias.ts:7:8:7:19 | [LocalTypeAccess] ValueOrArray | semmle.label | [LocalTypeAccess] ValueOrArray | | type_alias.ts:7:8:7:27 | [GenericTypeExpr] ValueOrArray | semmle.label | [GenericTypeExpr] ValueOrArray | | type_alias.ts:7:21:7:26 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | -| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 102 | +| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 103 | | type_alias.ts:9:6:9:9 | [Identifier] Json | semmle.label | [Identifier] Json | | type_alias.ts:10:5:15:12 | [UnionTypeExpr] \| strin ... Json[] | semmle.label | [UnionTypeExpr] \| strin ... Json[] | | type_alias.ts:10:7:10:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | @@ -2006,12 +2018,12 @@ nodes | type_alias.ts:15:7:15:10 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json | | type_alias.ts:15:7:15:12 | [ArrayTypeExpr] Json[] | semmle.label | [ArrayTypeExpr] Json[] | | type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.label | [DeclStmt] var json = ... | -| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 103 | +| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 104 | | type_alias.ts:17:5:17:8 | [VarDecl] json | semmle.label | [VarDecl] json | | type_alias.ts:17:5:17:14 | [VariableDeclarator] json: Json | semmle.label | [VariableDeclarator] json: Json | | type_alias.ts:17:11:17:14 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json | | type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | -| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 104 | +| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 105 | | type_alias.ts:19:6:19:16 | [Identifier] VirtualNode | semmle.label | [Identifier] VirtualNode | | type_alias.ts:20:5:21:56 | [UnionTypeExpr] \| strin ... Node[]] | semmle.label | [UnionTypeExpr] \| strin ... Node[]] | | type_alias.ts:20:7:20:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | @@ -2027,7 +2039,7 @@ nodes | type_alias.ts:21:43:21:53 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode | | type_alias.ts:21:43:21:55 | [ArrayTypeExpr] VirtualNode[] | semmle.label | [ArrayTypeExpr] VirtualNode[] | | type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.label | [DeclStmt] const myNode = ... | -| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 105 | +| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 106 | | type_alias.ts:23:7:23:12 | [VarDecl] myNode | semmle.label | [VarDecl] myNode | | type_alias.ts:23:7:27:5 | [VariableDeclarator] myNode: ... ] ] | semmle.label | [VariableDeclarator] myNode: ... ] ] | | type_alias.ts:23:15:23:25 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode | @@ -2052,12 +2064,12 @@ nodes | type_alias.ts:26:23:26:36 | [Literal] "second-child" | semmle.label | [Literal] "second-child" | | type_alias.ts:26:41:26:62 | [Literal] "I'm the second child" | semmle.label | [Literal] "I'm the second child" | | type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; | -| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 106 | +| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 107 | | type_definition_objects.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy | | type_definition_objects.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy | | type_definition_objects.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" | | type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.label | [ExportDeclaration] export class C {} | -| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 107 | +| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 108 | | type_definition_objects.ts:3:8:3:17 | [ClassDefinition,TypeDefinition] class C {} | semmle.label | [ClassDefinition,TypeDefinition] class C {} | | type_definition_objects.ts:3:14:3:14 | [VarDecl] C | semmle.label | [VarDecl] C | | type_definition_objects.ts:3:16:3:15 | [BlockStmt] {} | semmle.label | [BlockStmt] {} | @@ -2065,36 +2077,36 @@ nodes | type_definition_objects.ts:3:16:3:15 | [FunctionExpr] () {} | semmle.label | [FunctionExpr] () {} | | type_definition_objects.ts:3:16:3:15 | [Label] constructor | semmle.label | [Label] constructor | | type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.label | [DeclStmt] let classObj = ... | -| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 108 | +| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 109 | | type_definition_objects.ts:4:5:4:12 | [VarDecl] classObj | semmle.label | [VarDecl] classObj | | type_definition_objects.ts:4:5:4:16 | [VariableDeclarator] classObj = C | semmle.label | [VariableDeclarator] classObj = C | | type_definition_objects.ts:4:16:4:16 | [VarRef] C | semmle.label | [VarRef] C | | type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.label | [ExportDeclaration] export enum E {} | -| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 109 | +| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 110 | | type_definition_objects.ts:6:8:6:16 | [EnumDeclaration,TypeDefinition] enum E {} | semmle.label | [EnumDeclaration,TypeDefinition] enum E {} | | type_definition_objects.ts:6:13:6:13 | [VarDecl] E | semmle.label | [VarDecl] E | | type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.label | [DeclStmt] let enumObj = ... | -| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 110 | +| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 111 | | type_definition_objects.ts:7:5:7:11 | [VarDecl] enumObj | semmle.label | [VarDecl] enumObj | | type_definition_objects.ts:7:5:7:15 | [VariableDeclarator] enumObj = E | semmle.label | [VariableDeclarator] enumObj = E | | type_definition_objects.ts:7:15:7:15 | [VarRef] E | semmle.label | [VarRef] E | | type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.label | [ExportDeclaration] export ... e N {;} | -| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 111 | +| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 112 | | type_definition_objects.ts:9:8:9:22 | [NamespaceDeclaration] namespace N {;} | semmle.label | [NamespaceDeclaration] namespace N {;} | | type_definition_objects.ts:9:18:9:18 | [VarDecl] N | semmle.label | [VarDecl] N | | type_definition_objects.ts:9:21:9:21 | [EmptyStmt] ; | semmle.label | [EmptyStmt] ; | | type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.label | [DeclStmt] let namespaceObj = ... | -| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 112 | +| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 113 | | type_definition_objects.ts:10:5:10:16 | [VarDecl] namespaceObj | semmle.label | [VarDecl] namespaceObj | | type_definition_objects.ts:10:5:10:20 | [VariableDeclarator] namespaceObj = N | semmle.label | [VariableDeclarator] namespaceObj = N | | type_definition_objects.ts:10:20:10:20 | [VarRef] N | semmle.label | [VarRef] N | | type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; | -| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 113 | +| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 114 | | type_definitions.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy | | type_definitions.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy | | type_definitions.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" | | type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | -| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 114 | +| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 115 | | type_definitions.ts:3:11:3:11 | [Identifier] I | semmle.label | [Identifier] I | | type_definitions.ts:3:13:3:13 | [Identifier] S | semmle.label | [Identifier] S | | type_definitions.ts:3:13:3:13 | [TypeParameter] S | semmle.label | [TypeParameter] S | @@ -2102,14 +2114,14 @@ nodes | type_definitions.ts:4:3:4:7 | [FieldDeclaration] x: S; | semmle.label | [FieldDeclaration] x: S; | | type_definitions.ts:4:6:4:6 | [LocalTypeAccess] S | semmle.label | [LocalTypeAccess] S | | type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.label | [DeclStmt] let i = ... | -| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 115 | +| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 116 | | type_definitions.ts:6:5:6:5 | [VarDecl] i | semmle.label | [VarDecl] i | | type_definitions.ts:6:5:6:16 | [VariableDeclarator] i: I | semmle.label | [VariableDeclarator] i: I | | type_definitions.ts:6:8:6:8 | [LocalTypeAccess] I | semmle.label | [LocalTypeAccess] I | | type_definitions.ts:6:8:6:16 | [GenericTypeExpr] I | semmle.label | [GenericTypeExpr] I | | type_definitions.ts:6:10:6:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.label | [ClassDefinition,TypeDefinition] class C ... x: T } | -| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 116 | +| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 117 | | type_definitions.ts:8:7:8:7 | [VarDecl] C | semmle.label | [VarDecl] C | | type_definitions.ts:8:8:8:7 | [BlockStmt] {} | semmle.label | [BlockStmt] {} | | type_definitions.ts:8:8:8:7 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | semmle.label | [ClassInitializedMember,ConstructorDefinition] constructor() {} | @@ -2121,14 +2133,14 @@ nodes | type_definitions.ts:9:3:9:6 | [FieldDeclaration] x: T | semmle.label | [FieldDeclaration] x: T | | type_definitions.ts:9:6:9:6 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | | type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.label | [DeclStmt] let c = ... | -| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 117 | +| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 118 | | type_definitions.ts:11:5:11:5 | [VarDecl] c | semmle.label | [VarDecl] c | | type_definitions.ts:11:5:11:16 | [VariableDeclarator] c: C | semmle.label | [VariableDeclarator] c: C | | type_definitions.ts:11:8:11:8 | [LocalTypeAccess] C | semmle.label | [LocalTypeAccess] C | | type_definitions.ts:11:8:11:16 | [GenericTypeExpr] C | semmle.label | [GenericTypeExpr] C | | type_definitions.ts:11:10:11:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.label | [EnumDeclaration,TypeDefinition] enum Co ... blue } | -| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 118 | +| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 119 | | type_definitions.ts:13:6:13:10 | [VarDecl] Color | semmle.label | [VarDecl] Color | | type_definitions.ts:14:3:14:5 | [EnumMember,TypeDefinition] red | semmle.label | [EnumMember,TypeDefinition] red | | type_definitions.ts:14:3:14:5 | [VarDecl] red | semmle.label | [VarDecl] red | @@ -2137,29 +2149,29 @@ nodes | type_definitions.ts:14:15:14:18 | [EnumMember,TypeDefinition] blue | semmle.label | [EnumMember,TypeDefinition] blue | | type_definitions.ts:14:15:14:18 | [VarDecl] blue | semmle.label | [VarDecl] blue | | type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.label | [DeclStmt] let color = ... | -| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 119 | +| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 120 | | type_definitions.ts:16:5:16:9 | [VarDecl] color | semmle.label | [VarDecl] color | | type_definitions.ts:16:5:16:16 | [VariableDeclarator] color: Color | semmle.label | [VariableDeclarator] color: Color | | type_definitions.ts:16:12:16:16 | [LocalTypeAccess] Color | semmle.label | [LocalTypeAccess] Color | | type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.label | [EnumDeclaration,TypeDefinition] enum En ... ember } | -| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 120 | +| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 121 | | type_definitions.ts:18:6:18:22 | [VarDecl] EnumWithOneMember | semmle.label | [VarDecl] EnumWithOneMember | | type_definitions.ts:18:26:18:31 | [EnumMember,TypeDefinition] member | semmle.label | [EnumMember,TypeDefinition] member | | type_definitions.ts:18:26:18:31 | [VarDecl] member | semmle.label | [VarDecl] member | | type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.label | [DeclStmt] let e = ... | -| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 121 | +| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 122 | | type_definitions.ts:19:5:19:5 | [VarDecl] e | semmle.label | [VarDecl] e | | type_definitions.ts:19:5:19:24 | [VariableDeclarator] e: EnumWithOneMember | semmle.label | [VariableDeclarator] e: EnumWithOneMember | | type_definitions.ts:19:8:19:24 | [LocalTypeAccess] EnumWithOneMember | semmle.label | [LocalTypeAccess] EnumWithOneMember | | type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | -| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.order | 122 | +| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.order | 123 | | type_definitions.ts:21:6:21:10 | [Identifier] Alias | semmle.label | [Identifier] Alias | | type_definitions.ts:21:12:21:12 | [Identifier] T | semmle.label | [Identifier] T | | type_definitions.ts:21:12:21:12 | [TypeParameter] T | semmle.label | [TypeParameter] T | | type_definitions.ts:21:17:21:17 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | | type_definitions.ts:21:17:21:19 | [ArrayTypeExpr] T[] | semmle.label | [ArrayTypeExpr] T[] | | type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.label | [DeclStmt] let aliasForNumberArray = ... | -| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 123 | +| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 124 | | type_definitions.ts:22:5:22:23 | [VarDecl] aliasForNumberArray | semmle.label | [VarDecl] aliasForNumberArray | | type_definitions.ts:22:5:22:38 | [VariableDeclarator] aliasFo ... number> | semmle.label | [VariableDeclarator] aliasFo ... number> | | type_definitions.ts:22:26:22:30 | [LocalTypeAccess] Alias | semmle.label | [LocalTypeAccess] Alias | @@ -2546,6 +2558,26 @@ edges | middle-rest.ts:3:7:3:26 | [ArrayExpr] [true, "hello", 123] | middle-rest.ts:3:14:3:20 | [Literal] "hello" | semmle.order | 2 | | middle-rest.ts:3:7:3:26 | [ArrayExpr] [true, "hello", 123] | middle-rest.ts:3:23:3:25 | [Literal] 123 | semmle.label | 3 | | middle-rest.ts:3:7:3:26 | [ArrayExpr] [true, "hello", 123] | middle-rest.ts:3:23:3:25 | [Literal] 123 | semmle.order | 3 | +| tsconfig.json:1:1:9:1 | [JsonObject] {compilerOptions: ...} | tsconfig.json:2:22:8:3 | [JsonObject] {module: ...} | semmle.label | 0 | +| tsconfig.json:1:1:9:1 | [JsonObject] {compilerOptions: ...} | tsconfig.json:2:22:8:3 | [JsonObject] {module: ...} | semmle.order | 0 | +| tsconfig.json:2:22:8:3 | [JsonObject] {module: ...} | tsconfig.json:3:15:3:22 | [JsonString] "esnext" | semmle.label | 0 | +| tsconfig.json:2:22:8:3 | [JsonObject] {module: ...} | tsconfig.json:3:15:3:22 | [JsonString] "esnext" | semmle.order | 0 | +| tsconfig.json:2:22:8:3 | [JsonObject] {module: ...} | tsconfig.json:4:15:4:22 | [JsonString] "esnext" | semmle.label | 1 | +| tsconfig.json:2:22:8:3 | [JsonObject] {module: ...} | tsconfig.json:4:15:4:22 | [JsonString] "esnext" | semmle.order | 1 | +| tsconfig.json:2:22:8:3 | [JsonObject] {module: ...} | tsconfig.json:5:12:5:28 | [JsonArray] ["dom", ...] | semmle.label | 2 | +| tsconfig.json:2:22:8:3 | [JsonObject] {module: ...} | tsconfig.json:5:12:5:28 | [JsonArray] ["dom", ...] | semmle.order | 2 | +| tsconfig.json:2:22:8:3 | [JsonObject] {module: ...} | tsconfig.json:6:26:6:29 | [JsonBoolean] true | semmle.label | 3 | +| tsconfig.json:2:22:8:3 | [JsonObject] {module: ...} | tsconfig.json:6:26:6:29 | [JsonBoolean] true | semmle.order | 3 | +| tsconfig.json:2:22:8:3 | [JsonObject] {module: ...} | tsconfig.json:7:23:7:34 | [JsonArray] [".ios", ...] | semmle.label | 4 | +| tsconfig.json:2:22:8:3 | [JsonObject] {module: ...} | tsconfig.json:7:23:7:34 | [JsonArray] [".ios", ...] | semmle.order | 4 | +| tsconfig.json:5:12:5:28 | [JsonArray] ["dom", ...] | tsconfig.json:5:13:5:17 | [JsonString] "dom" | semmle.label | 0 | +| tsconfig.json:5:12:5:28 | [JsonArray] ["dom", ...] | tsconfig.json:5:13:5:17 | [JsonString] "dom" | semmle.order | 0 | +| tsconfig.json:5:12:5:28 | [JsonArray] ["dom", ...] | tsconfig.json:5:20:5:27 | [JsonString] "esnext" | semmle.label | 1 | +| tsconfig.json:5:12:5:28 | [JsonArray] ["dom", ...] | tsconfig.json:5:20:5:27 | [JsonString] "esnext" | semmle.order | 1 | +| tsconfig.json:7:23:7:34 | [JsonArray] [".ios", ...] | tsconfig.json:7:24:7:29 | [JsonString] ".ios" | semmle.label | 0 | +| tsconfig.json:7:23:7:34 | [JsonArray] [".ios", ...] | tsconfig.json:7:24:7:29 | [JsonString] ".ios" | semmle.order | 0 | +| tsconfig.json:7:23:7:34 | [JsonArray] [".ios", ...] | tsconfig.json:7:32:7:33 | [JsonString] "" | semmle.label | 1 | +| tsconfig.json:7:23:7:34 | [JsonArray] [".ios", ...] | tsconfig.json:7:32:7:33 | [JsonString] "" | semmle.order | 1 | | tst.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | tst.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | 1 | | tst.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | tst.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.order | 1 | | tst.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | tst.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | 2 | From 359525b65a6d31e56637651080bbdf42a25c1710 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Apr 2025 09:41:38 +0200 Subject: [PATCH 133/336] JS: Extract more tsconfig.json patterns --- javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java | 2 +- javascript/extractor/src/com/semmle/js/extractor/Main.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index 49b22ddcd2d4..22d008637c9a 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -404,7 +404,7 @@ private void setupFilters() { patterns.add("**/*.view.json"); // SAP UI5 patterns.add("**/manifest.json"); patterns.add("**/package.json"); - patterns.add("**/tsconfig*.json"); + patterns.add("**/*tsconfig*.json"); patterns.add("**/codeql-javascript-*.json"); // include any explicitly specified extensions diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index d4f377f15476..59be61388e38 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -307,7 +307,7 @@ public void setupMatchers(ArgsParser ap) { // extract TypeScript if `--typescript` or `--typescript-full` was specified if (getTypeScriptMode(ap) != TypeScriptMode.NONE) { addIncludesFor(includes, FileType.TYPESCRIPT); - includes.add("**/tsconfig*.json"); + includes.add("**/*tsconfig*.json"); } // add explicit include patterns From 565cb434fc3c46a207afa23fb09fe59ac62ac8f0 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 24 Apr 2025 09:03:55 +0200 Subject: [PATCH 134/336] JS: Add test --- .../PathResolution/BaseUrl/base/lib/file.ts | 1 + .../PathResolution/BaseUrl/base/lib/index.ts | 1 + .../PathResolution/BaseUrl/base/lib/nostar.ts | 1 + .../PathResolution/BaseUrl/base/lib2/file.ts | 1 + .../PathResolution/BaseUrl/src/main.ts | 47 ++++++++ .../PathResolution/BaseUrl/tsconfig.json | 14 +++ .../PathResolution/Basic/Subdir/sub.ts | 4 + .../PathResolution/Basic/index.ts | 1 + .../DeclarationFiles/lib/split.d.ts | 5 + .../DeclarationFiles/lib/split.js | 4 + .../DeclarationFiles/lib/typescript.d.ts | 1 + .../DeclarationFiles/lib/typescript.js | 1 + .../DeclarationFiles/lib/typescript.ts | 1 + .../DeclarationFiles/src/main.ts | 7 ++ .../PathResolution/DirnameImports/main.js | 15 +++ .../DirnameImports/nested/target.js | 2 + .../PathResolution/DirnameImports/target.js | 2 + .../DistContainsSrc/package.json | 3 + .../PathResolution/DistContainsSrc/src/foo.ts | 1 + .../Extended/base/tsconfig.base.json | 11 ++ .../PathResolution/Extended/lib/file.ts | 1 + .../PathResolution/Extended/lib/index.ts | 1 + .../PathResolution/Extended/lib/nostar.ts | 1 + .../PathResolution/Extended/src/main.ts | 35 ++++++ .../PathResolution/Extended/tsconfig.json | 4 + .../PathResolution/Fallback/lib1/both.ts | 1 + .../Fallback/lib1/differentExtension.js | 1 + .../PathResolution/Fallback/lib1/only1.ts | 1 + .../Fallback/lib1/subdir/both.ts | 1 + .../Fallback/lib1/subdir/index.ts | 1 + .../Fallback/lib1/subdir/only1.ts | 1 + .../PathResolution/Fallback/lib2/both.ts | 1 + .../Fallback/lib2/differentExtension.ts | 1 + .../PathResolution/Fallback/lib2/only2.ts | 1 + .../Fallback/lib2/subdir/both.ts | 1 + .../Fallback/lib2/subdir/index.ts | 1 + .../Fallback/lib2/subdir/only2.ts | 1 + .../PathResolution/Fallback/src/main.ts | 10 ++ .../PathResolution/Fallback/tsconfig.json | 8 ++ .../PathResolution/JSDocProvide/lib.js | 5 + .../PathResolution/JSDocProvide/main.js | 1 + .../PathResolution/MainIsFolder/package.json | 4 + .../PathResolution/MainIsFolder/src/index.ts | 1 + .../PathResolution/MinifiedMain/package.json | 3 + .../MinifiedMain/src/library.ts | 1 + .../PathResolution/NoBaseUrl/lib/file.ts | 1 + .../PathResolution/NoBaseUrl/lib/index.ts | 1 + .../PathResolution/NoBaseUrl/lib/nostar.ts | 1 + .../PathResolution/NoBaseUrl/src/main.ts | 35 ++++++ .../PathResolution/NoBaseUrl/tsconfig.json | 10 ++ .../NodeModules/node_modules/foo/index.js | 1 + .../NodeModules/node_modules/foo/package.json | 3 + .../PathResolution/NodeModules/outermain.ts | 2 + .../subfolder/node_modules/bar/index.js | 1 + .../subfolder/node_modules/bar/package.json | 3 + .../NodeModules/subfolder/src/main.ts | 2 + .../PathResolution/PackageGuess1/package.json | 3 + .../PathResolution/PackageGuess1/src/index.ts | 1 + .../PackageGuess2/blah/stuff.ts | 1 + .../PathResolution/PackageGuess2/package.json | 6 + .../PathResolution/PackageIndexFile/index.js | 1 + .../PackageIndexFile/package.json | 3 + .../PackageWithExports/fake-file-impl.js | 1 + .../PathResolution/PackageWithExports/main.js | 1 + .../PackageWithExports/package.json | 14 +++ .../PackageWithExports/star-impl/foo.js | 1 + .../PathResolution/PackageWithMain/main.js | 1 + .../PackageWithMain/package.json | 4 + .../PackageWithMainExt/lib/main.ts | 1 + .../PackageWithMainExt/package.json | 4 + .../PackageWithModuleMain/main.js | 1 + .../PackageWithModuleMain/package.json | 4 + .../PathResolution/RootDir/my-root/foo.ts | 1 + .../PathResolution/RootDir/tsconfig.json | 7 ++ .../PathResolution/TSConfigOutDir/src/foo.ts | 1 + .../TSConfigOutDir/tsconfig.json | 7 ++ .../PathResolution/import-packages.ts | 35 ++++++ .../PathResolution/test.expected | 111 ++++++++++++++++++ .../test/library-tests/PathResolution/test.ql | 5 + .../library-tests/PathResolution/test.qlref | 2 + .../PathResolution/tsconfig.json | 1 + 81 files changed, 487 insertions(+) create mode 100644 javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib/file.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib/index.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib/nostar.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib2/file.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/BaseUrl/src/main.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/BaseUrl/tsconfig.json create mode 100644 javascript/ql/test/library-tests/PathResolution/Basic/Subdir/sub.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Basic/index.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/split.d.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/split.js create mode 100644 javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/typescript.d.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/typescript.js create mode 100644 javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/typescript.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/DeclarationFiles/src/main.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/DirnameImports/main.js create mode 100644 javascript/ql/test/library-tests/PathResolution/DirnameImports/nested/target.js create mode 100644 javascript/ql/test/library-tests/PathResolution/DirnameImports/target.js create mode 100644 javascript/ql/test/library-tests/PathResolution/DistContainsSrc/package.json create mode 100644 javascript/ql/test/library-tests/PathResolution/DistContainsSrc/src/foo.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Extended/base/tsconfig.base.json create mode 100644 javascript/ql/test/library-tests/PathResolution/Extended/lib/file.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Extended/lib/index.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Extended/lib/nostar.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Extended/src/main.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Extended/tsconfig.json create mode 100644 javascript/ql/test/library-tests/PathResolution/Fallback/lib1/both.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Fallback/lib1/differentExtension.js create mode 100644 javascript/ql/test/library-tests/PathResolution/Fallback/lib1/only1.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Fallback/lib1/subdir/both.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Fallback/lib1/subdir/index.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Fallback/lib1/subdir/only1.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Fallback/lib2/both.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Fallback/lib2/differentExtension.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Fallback/lib2/only2.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Fallback/lib2/subdir/both.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Fallback/lib2/subdir/index.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Fallback/lib2/subdir/only2.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Fallback/src/main.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/Fallback/tsconfig.json create mode 100644 javascript/ql/test/library-tests/PathResolution/JSDocProvide/lib.js create mode 100644 javascript/ql/test/library-tests/PathResolution/JSDocProvide/main.js create mode 100644 javascript/ql/test/library-tests/PathResolution/MainIsFolder/package.json create mode 100644 javascript/ql/test/library-tests/PathResolution/MainIsFolder/src/index.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/MinifiedMain/package.json create mode 100644 javascript/ql/test/library-tests/PathResolution/MinifiedMain/src/library.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/NoBaseUrl/lib/file.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/NoBaseUrl/lib/index.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/NoBaseUrl/lib/nostar.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/NoBaseUrl/src/main.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/NoBaseUrl/tsconfig.json create mode 100644 javascript/ql/test/library-tests/PathResolution/NodeModules/node_modules/foo/index.js create mode 100644 javascript/ql/test/library-tests/PathResolution/NodeModules/node_modules/foo/package.json create mode 100644 javascript/ql/test/library-tests/PathResolution/NodeModules/outermain.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/NodeModules/subfolder/node_modules/bar/index.js create mode 100644 javascript/ql/test/library-tests/PathResolution/NodeModules/subfolder/node_modules/bar/package.json create mode 100644 javascript/ql/test/library-tests/PathResolution/NodeModules/subfolder/src/main.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageGuess1/package.json create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageGuess1/src/index.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageGuess2/blah/stuff.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageGuess2/package.json create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageIndexFile/index.js create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageIndexFile/package.json create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageWithExports/fake-file-impl.js create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageWithExports/main.js create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageWithExports/package.json create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageWithExports/star-impl/foo.js create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageWithMain/main.js create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageWithMain/package.json create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageWithMainExt/lib/main.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageWithMainExt/package.json create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageWithModuleMain/main.js create mode 100644 javascript/ql/test/library-tests/PathResolution/PackageWithModuleMain/package.json create mode 100644 javascript/ql/test/library-tests/PathResolution/RootDir/my-root/foo.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/RootDir/tsconfig.json create mode 100644 javascript/ql/test/library-tests/PathResolution/TSConfigOutDir/src/foo.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/TSConfigOutDir/tsconfig.json create mode 100644 javascript/ql/test/library-tests/PathResolution/import-packages.ts create mode 100644 javascript/ql/test/library-tests/PathResolution/test.expected create mode 100644 javascript/ql/test/library-tests/PathResolution/test.ql create mode 100644 javascript/ql/test/library-tests/PathResolution/test.qlref create mode 100644 javascript/ql/test/library-tests/PathResolution/tsconfig.json diff --git a/javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib/file.ts b/javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib/file.ts new file mode 100644 index 000000000000..f8a2b761a99e --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib/file.ts @@ -0,0 +1 @@ +export const x = "file.ts" diff --git a/javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib/index.ts b/javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib/index.ts new file mode 100644 index 000000000000..8d1382ced0ce --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib/index.ts @@ -0,0 +1 @@ +export const x = "index.ts"; diff --git a/javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib/nostar.ts b/javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib/nostar.ts new file mode 100644 index 000000000000..9245143d085d --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib/nostar.ts @@ -0,0 +1 @@ +export const x = "nostar.ts" diff --git a/javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib2/file.ts b/javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib2/file.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/BaseUrl/base/lib2/file.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/BaseUrl/src/main.ts b/javascript/ql/test/library-tests/PathResolution/BaseUrl/src/main.ts new file mode 100644 index 000000000000..9c5b90729035 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/BaseUrl/src/main.ts @@ -0,0 +1,47 @@ +// Relative import +import "../base/lib/file"; // $ importTarget=BaseUrl/base/lib/file.ts +import "../base/lib/file.ts"; // $ importTarget=BaseUrl/base/lib/file.ts +import "../base/lib/file.js"; // $ importTarget=BaseUrl/base/lib/file.ts +import "../base/lib"; // $ importTarget=BaseUrl/base/lib/index.ts +import "../base/lib/index"; // $ importTarget=BaseUrl/base/lib/index.ts +import "../base/lib/index.ts"; // $ importTarget=BaseUrl/base/lib/index.ts +import "../base/lib/index.js"; // $ importTarget=BaseUrl/base/lib/index.ts + +// Import relative to baseUrl +import "lib/file"; // $ importTarget=BaseUrl/base/lib/file.ts +import "lib/file.ts"; // $ importTarget=BaseUrl/base/lib/file.ts +import "lib/file.js"; // $ importTarget=BaseUrl/base/lib/file.ts +import "lib"; // $ importTarget=BaseUrl/base/lib/index.ts +import "lib/index"; // $ importTarget=BaseUrl/base/lib/index.ts +import "lib/index.ts"; // $ importTarget=BaseUrl/base/lib/index.ts +import "lib/index.js"; // $ importTarget=BaseUrl/base/lib/index.ts + +// Import matching "@/*" path mapping +import "@/file"; // $ importTarget=BaseUrl/base/lib/file.ts +import "@/file.ts"; // $ importTarget=BaseUrl/base/lib/file.ts +import "@/file.js"; // $ importTarget=BaseUrl/base/lib/file.ts +import "@"; // $ importTarget=BaseUrl/base/lib/nostar.ts +import "@/index"; // $ importTarget=BaseUrl/base/lib/index.ts +import "@/index.ts"; // $ importTarget=BaseUrl/base/lib/index.ts +import "@/index.js"; // $ importTarget=BaseUrl/base/lib/index.ts + +// Import matching "#/*" path mapping +import "#/file"; // $ importTarget=BaseUrl/base/lib/file.ts +import "#/file.ts"; // $ importTarget=BaseUrl/base/lib/file.ts +import "#/file.js"; // $ importTarget=BaseUrl/base/lib/file.ts +import "#/index"; // $ importTarget=BaseUrl/base/lib/index.ts +import "#/index.ts"; // $ importTarget=BaseUrl/base/lib/index.ts +import "#/index.js"; // $ importTarget=BaseUrl/base/lib/index.ts + +// Import matching "^lib*" path mapping +import "^lib/file"; // $ importTarget=BaseUrl/base/lib/file.ts +import "^lib2/file"; // $ importTarget=BaseUrl/base/lib2/file.ts + +// Import matching "@/*.xyz" path mapping. Note that this is not actually supported by TypeScript. +import "@/file.xyz"; +import "@/file.ts.xyz"; +import "@/file.js.xyz"; +import "@.xyz"; +import "@/index.xyz"; +import "@/index.ts.xyz"; +import "@/index.js.xyz"; diff --git a/javascript/ql/test/library-tests/PathResolution/BaseUrl/tsconfig.json b/javascript/ql/test/library-tests/PathResolution/BaseUrl/tsconfig.json new file mode 100644 index 000000000000..9167650c05a5 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/BaseUrl/tsconfig.json @@ -0,0 +1,14 @@ +{ + "include": ["."], + "compilerOptions": { + // Path mappings are resolved relative to baseUrl + "baseUrl": "./base", + "paths": { + "@/*": ["lib/*"], + "#/*": ["./lib/*"], // relative paths here are also resolved from the base url + "^lib*": ["./lib*"], // must end with "*" but not necessarily "/*" + "@/*.xyz": ["lib/*"], + "@": ["lib/nostar.ts"] + } + } +} diff --git a/javascript/ql/test/library-tests/PathResolution/Basic/Subdir/sub.ts b/javascript/ql/test/library-tests/PathResolution/Basic/Subdir/sub.ts new file mode 100644 index 000000000000..375c5f955376 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Basic/Subdir/sub.ts @@ -0,0 +1,4 @@ +import '..'; // $ importTarget=Basic/index.ts +import '../'; // $ importTarget=Basic/index.ts +import './..'; // $ importTarget=Basic/index.ts +import './../'; // $ importTarget=Basic/index.ts diff --git a/javascript/ql/test/library-tests/PathResolution/Basic/index.ts b/javascript/ql/test/library-tests/PathResolution/Basic/index.ts new file mode 100644 index 000000000000..1d8ed2b606a6 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Basic/index.ts @@ -0,0 +1 @@ +import './Subdir/sub'; // $ importTarget=Basic/Subdir/sub.ts diff --git a/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/split.d.ts b/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/split.d.ts new file mode 100644 index 000000000000..83e844e755e8 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/split.d.ts @@ -0,0 +1,5 @@ +// Type declaration for dual-module +export interface DualType { + prop: string; +} +export declare function helper(): DualType; diff --git a/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/split.js b/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/split.js new file mode 100644 index 000000000000..be8d5d53bafe --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/split.js @@ -0,0 +1,4 @@ +// Implementation of dual-module +export function helper() { + return { prop: "implementation" }; +} diff --git a/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/typescript.d.ts b/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/typescript.d.ts new file mode 100644 index 000000000000..226fa6a598be --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/typescript.d.ts @@ -0,0 +1 @@ +export const x: number; diff --git a/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/typescript.js b/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/typescript.js new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/typescript.js @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/typescript.ts b/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/typescript.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/lib/typescript.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/src/main.ts b/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/src/main.ts new file mode 100644 index 000000000000..cfa7c750d9af --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/src/main.ts @@ -0,0 +1,7 @@ +import "../lib/split"; // $ importTarget=DeclarationFiles/lib/split.d.ts importTarget=DeclarationFiles/lib/split.js +import "../lib/split.js"; // $ importTarget=DeclarationFiles/lib/split.js importTarget=DeclarationFiles/lib/split.d.ts +import "../lib/split.d.ts"; // $ importTarget=DeclarationFiles/lib/split.d.ts + +import "../lib/typescript"; // $ importTarget=DeclarationFiles/lib/typescript.ts +import "../lib/typescript.js"; // $ importTarget=DeclarationFiles/lib/typescript.ts +import "../lib/typescript.d.ts"; // $ importTarget=DeclarationFiles/lib/typescript.d.ts SPURIOUS: importTarget=DeclarationFiles/lib/typescript.ts diff --git a/javascript/ql/test/library-tests/PathResolution/DirnameImports/main.js b/javascript/ql/test/library-tests/PathResolution/DirnameImports/main.js new file mode 100644 index 000000000000..7303809541ce --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/DirnameImports/main.js @@ -0,0 +1,15 @@ +// Test for imports using __dirname +const path = require('path'); + +require(__dirname + '/target.js'); // $ importTarget=DirnameImports/target.js +require(__dirname + '/nested/target.js'); // $ importTarget=DirnameImports/nested/target.js +require(__dirname + '/../import-packages.ts'); // $ importTarget=import-packages.ts +require(__dirname + '/' + 'target.js'); // $ importTarget=DirnameImports/target.js + +require(path.join(__dirname, 'target.js')); // $ importTarget=DirnameImports/target.js +require(path.resolve(__dirname, 'target.js')); // $ MISSING: importTarget=DirnameImports/target.js + +const subdir = 'nested'; +require(__dirname + '/' + subdir + '/target.js'); // $ importTarget=DirnameImports/nested/target.js + +require(`${__dirname}/target.js`); // $ MISSING: importTarget=DirnameImports/target.js diff --git a/javascript/ql/test/library-tests/PathResolution/DirnameImports/nested/target.js b/javascript/ql/test/library-tests/PathResolution/DirnameImports/nested/target.js new file mode 100644 index 000000000000..329f6242a404 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/DirnameImports/nested/target.js @@ -0,0 +1,2 @@ +// Nested target file for __dirname imports +module.exports = { name: 'nested-target' }; diff --git a/javascript/ql/test/library-tests/PathResolution/DirnameImports/target.js b/javascript/ql/test/library-tests/PathResolution/DirnameImports/target.js new file mode 100644 index 000000000000..bb9a3de92023 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/DirnameImports/target.js @@ -0,0 +1,2 @@ +// Target file for __dirname imports +module.exports = { name: 'target' }; diff --git a/javascript/ql/test/library-tests/PathResolution/DistContainsSrc/package.json b/javascript/ql/test/library-tests/PathResolution/DistContainsSrc/package.json new file mode 100644 index 000000000000..d830ef0f5679 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/DistContainsSrc/package.json @@ -0,0 +1,3 @@ +{ + "main": "./dist/src/foo.js" +} diff --git a/javascript/ql/test/library-tests/PathResolution/DistContainsSrc/src/foo.ts b/javascript/ql/test/library-tests/PathResolution/DistContainsSrc/src/foo.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/DistContainsSrc/src/foo.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/Extended/base/tsconfig.base.json b/javascript/ql/test/library-tests/PathResolution/Extended/base/tsconfig.base.json new file mode 100644 index 000000000000..dd5518cad9ec --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Extended/base/tsconfig.base.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + // The baseUrl is interpreted relative to this file, not the "root" tsconfig.json file extending it. + "baseUrl": "./../", + "paths": { + "@/*": ["lib/*"], + "@/*.xyz": ["lib/*"], + "@": ["lib/nostar.ts"] + } + } +} diff --git a/javascript/ql/test/library-tests/PathResolution/Extended/lib/file.ts b/javascript/ql/test/library-tests/PathResolution/Extended/lib/file.ts new file mode 100644 index 000000000000..f8a2b761a99e --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Extended/lib/file.ts @@ -0,0 +1 @@ +export const x = "file.ts" diff --git a/javascript/ql/test/library-tests/PathResolution/Extended/lib/index.ts b/javascript/ql/test/library-tests/PathResolution/Extended/lib/index.ts new file mode 100644 index 000000000000..8d1382ced0ce --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Extended/lib/index.ts @@ -0,0 +1 @@ +export const x = "index.ts"; diff --git a/javascript/ql/test/library-tests/PathResolution/Extended/lib/nostar.ts b/javascript/ql/test/library-tests/PathResolution/Extended/lib/nostar.ts new file mode 100644 index 000000000000..9245143d085d --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Extended/lib/nostar.ts @@ -0,0 +1 @@ +export const x = "nostar.ts" diff --git a/javascript/ql/test/library-tests/PathResolution/Extended/src/main.ts b/javascript/ql/test/library-tests/PathResolution/Extended/src/main.ts new file mode 100644 index 000000000000..949bc7c7908c --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Extended/src/main.ts @@ -0,0 +1,35 @@ +// Relative import +import "../lib/file"; // $ importTarget=Extended/lib/file.ts +import "../lib/file.ts"; // $ importTarget=Extended/lib/file.ts +import "../lib/file.js"; // $ importTarget=Extended/lib/file.ts +import "../lib"; // $ importTarget=Extended/lib/index.ts +import "../lib/index"; // $ importTarget=Extended/lib/index.ts +import "../lib/index.ts"; // $ importTarget=Extended/lib/index.ts +import "../lib/index.js"; // $ importTarget=Extended/lib/index.ts + +// Import relative to baseUrl +import "lib/file"; // $ importTarget=Extended/lib/file.ts +import "lib/file.ts"; // $ importTarget=Extended/lib/file.ts +import "lib/file.js"; // $ importTarget=Extended/lib/file.ts +import "lib"; // $ importTarget=Extended/lib/index.ts +import "lib/index"; // $ importTarget=Extended/lib/index.ts +import "lib/index.ts"; // $ importTarget=Extended/lib/index.ts +import "lib/index.js"; // $ importTarget=Extended/lib/index.ts + +// Import matching "@/*" path mapping +import "@/file"; // $ importTarget=Extended/lib/file.ts +import "@/file.ts"; // $ importTarget=Extended/lib/file.ts +import "@/file.js"; // $ importTarget=Extended/lib/file.ts +import "@"; // $ importTarget=Extended/lib/nostar.ts +import "@/index"; // $ importTarget=Extended/lib/index.ts +import "@/index.ts"; // $ importTarget=Extended/lib/index.ts +import "@/index.js"; // $ importTarget=Extended/lib/index.ts + +// Import matching "@/*.xyz" path mapping. Note that this is not actually supported by TypeScript. +import "@/file.xyz"; +import "@/file.ts.xyz"; +import "@/file.js.xyz"; +import "@.xyz"; +import "@/index.xyz"; +import "@/index.ts.xyz"; +import "@/index.js.xyz"; diff --git a/javascript/ql/test/library-tests/PathResolution/Extended/tsconfig.json b/javascript/ql/test/library-tests/PathResolution/Extended/tsconfig.json new file mode 100644 index 000000000000..608d152f71a0 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Extended/tsconfig.json @@ -0,0 +1,4 @@ +{ + "include": ["."], + "extends": "./base/tsconfig.base.json" +} diff --git a/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/both.ts b/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/both.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/both.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/differentExtension.js b/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/differentExtension.js new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/differentExtension.js @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/only1.ts b/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/only1.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/only1.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/subdir/both.ts b/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/subdir/both.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/subdir/both.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/subdir/index.ts b/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/subdir/index.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/subdir/index.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/subdir/only1.ts b/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/subdir/only1.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Fallback/lib1/subdir/only1.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/both.ts b/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/both.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/both.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/differentExtension.ts b/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/differentExtension.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/differentExtension.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/only2.ts b/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/only2.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/only2.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/subdir/both.ts b/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/subdir/both.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/subdir/both.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/subdir/index.ts b/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/subdir/index.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/subdir/index.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/subdir/only2.ts b/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/subdir/only2.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Fallback/lib2/subdir/only2.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/Fallback/src/main.ts b/javascript/ql/test/library-tests/PathResolution/Fallback/src/main.ts new file mode 100644 index 000000000000..1b0bdb14e99b --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Fallback/src/main.ts @@ -0,0 +1,10 @@ +import "@/both" // $ importTarget=Fallback/lib1/both.ts +import "@/only1" // $ importTarget=Fallback/lib1/only1.ts +import "@/only2" // $ importTarget=Fallback/lib2/only2.ts +import "@/differentExtension" // $ importTarget=Fallback/lib2/differentExtension.ts +import "@/differentExtension.js" // $ importTarget=Fallback/lib2/differentExtension.ts + +import "@/subdir" // $ importTarget=Fallback/lib1/subdir/index.ts +import "@/subdir/both" // $ importTarget=Fallback/lib1/subdir/both.ts +import "@/subdir/only1" // $ importTarget=Fallback/lib1/subdir/only1.ts +import "@/subdir/only2" // $ importTarget=Fallback/lib2/subdir/only2.ts diff --git a/javascript/ql/test/library-tests/PathResolution/Fallback/tsconfig.json b/javascript/ql/test/library-tests/PathResolution/Fallback/tsconfig.json new file mode 100644 index 000000000000..239fac925588 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/Fallback/tsconfig.json @@ -0,0 +1,8 @@ +{ + "include": ["."], + "compilerOptions": { + "paths": { + "@/*": ["./lib1/*", "./lib2/*"], + } + } +} diff --git a/javascript/ql/test/library-tests/PathResolution/JSDocProvide/lib.js b/javascript/ql/test/library-tests/PathResolution/JSDocProvide/lib.js new file mode 100644 index 000000000000..ba12858811b9 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/JSDocProvide/lib.js @@ -0,0 +1,5 @@ +/** + * @providesModule jsdoc-provided-module/foo/bar/baz + */ + +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/JSDocProvide/main.js b/javascript/ql/test/library-tests/PathResolution/JSDocProvide/main.js new file mode 100644 index 000000000000..5e1aaf8bd7b3 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/JSDocProvide/main.js @@ -0,0 +1 @@ +import 'jsdoc-provided-module/foo/bar/baz'; // $ importTarget=JSDocProvide/lib.js diff --git a/javascript/ql/test/library-tests/PathResolution/MainIsFolder/package.json b/javascript/ql/test/library-tests/PathResolution/MainIsFolder/package.json new file mode 100644 index 000000000000..d5947ffcfa5d --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/MainIsFolder/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/main-is-folder", + "main": "dist" +} diff --git a/javascript/ql/test/library-tests/PathResolution/MainIsFolder/src/index.ts b/javascript/ql/test/library-tests/PathResolution/MainIsFolder/src/index.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/MainIsFolder/src/index.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/MinifiedMain/package.json b/javascript/ql/test/library-tests/PathResolution/MinifiedMain/package.json new file mode 100644 index 000000000000..bd7204f0a66b --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/MinifiedMain/package.json @@ -0,0 +1,3 @@ +{ + "main": "dist/library.min.js" +} diff --git a/javascript/ql/test/library-tests/PathResolution/MinifiedMain/src/library.ts b/javascript/ql/test/library-tests/PathResolution/MinifiedMain/src/library.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/MinifiedMain/src/library.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/NoBaseUrl/lib/file.ts b/javascript/ql/test/library-tests/PathResolution/NoBaseUrl/lib/file.ts new file mode 100644 index 000000000000..f8a2b761a99e --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/NoBaseUrl/lib/file.ts @@ -0,0 +1 @@ +export const x = "file.ts" diff --git a/javascript/ql/test/library-tests/PathResolution/NoBaseUrl/lib/index.ts b/javascript/ql/test/library-tests/PathResolution/NoBaseUrl/lib/index.ts new file mode 100644 index 000000000000..8d1382ced0ce --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/NoBaseUrl/lib/index.ts @@ -0,0 +1 @@ +export const x = "index.ts"; diff --git a/javascript/ql/test/library-tests/PathResolution/NoBaseUrl/lib/nostar.ts b/javascript/ql/test/library-tests/PathResolution/NoBaseUrl/lib/nostar.ts new file mode 100644 index 000000000000..9245143d085d --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/NoBaseUrl/lib/nostar.ts @@ -0,0 +1 @@ +export const x = "nostar.ts" diff --git a/javascript/ql/test/library-tests/PathResolution/NoBaseUrl/src/main.ts b/javascript/ql/test/library-tests/PathResolution/NoBaseUrl/src/main.ts new file mode 100644 index 000000000000..799794a2c6b4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/NoBaseUrl/src/main.ts @@ -0,0 +1,35 @@ +// Relative import +import "../lib/file"; // $ importTarget=NoBaseUrl/lib/file.ts +import "../lib/file.ts"; // $ importTarget=NoBaseUrl/lib/file.ts +import "../lib/file.js"; // $ importTarget=NoBaseUrl/lib/file.ts +import "../lib"; // $ importTarget=NoBaseUrl/lib/index.ts +import "../lib/index"; // $ importTarget=NoBaseUrl/lib/index.ts +import "../lib/index.ts"; // $ importTarget=NoBaseUrl/lib/index.ts +import "../lib/index.js"; // $ importTarget=NoBaseUrl/lib/index.ts + +// Import unresolvable due to missing baseUrl +import "lib/file"; +import "lib/file.ts"; +import "lib/file.js"; +import "lib"; +import "lib/index"; +import "lib/index.ts"; +import "lib/index.js"; + +// Import matching "@/*" path mapping +import "@/file"; // $ importTarget=NoBaseUrl/lib/file.ts +import "@/file.ts"; // $ importTarget=NoBaseUrl/lib/file.ts +import "@/file.js"; // $ importTarget=NoBaseUrl/lib/file.ts +import "@"; // $ importTarget=NoBaseUrl/lib/nostar.ts +import "@/index"; // $ importTarget=NoBaseUrl/lib/index.ts +import "@/index.ts"; // $ importTarget=NoBaseUrl/lib/index.ts +import "@/index.js"; // $ importTarget=NoBaseUrl/lib/index.ts + +// Import matching "@/*.xyz" path mapping. Note that this is not actually supported by TypeScript. +import "@/file.xyz"; +import "@/file.ts.xyz"; +import "@/file.js.xyz"; +import "@.xyz"; +import "@/index.xyz"; +import "@/index.ts.xyz"; +import "@/index.js.xyz"; diff --git a/javascript/ql/test/library-tests/PathResolution/NoBaseUrl/tsconfig.json b/javascript/ql/test/library-tests/PathResolution/NoBaseUrl/tsconfig.json new file mode 100644 index 000000000000..192347d919c4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/NoBaseUrl/tsconfig.json @@ -0,0 +1,10 @@ +{ + "include": ["."], + "compilerOptions": { + "paths": { + "@/*": ["./lib/*"], + "@/*.xyz": ["./lib/*"], + "@": ["./lib/nostar.ts"] + } + } +} diff --git a/javascript/ql/test/library-tests/PathResolution/NodeModules/node_modules/foo/index.js b/javascript/ql/test/library-tests/PathResolution/NodeModules/node_modules/foo/index.js new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/NodeModules/node_modules/foo/index.js @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/NodeModules/node_modules/foo/package.json b/javascript/ql/test/library-tests/PathResolution/NodeModules/node_modules/foo/package.json new file mode 100644 index 000000000000..7173713a8cd4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/NodeModules/node_modules/foo/package.json @@ -0,0 +1,3 @@ +{ + "name": "foo" +} diff --git a/javascript/ql/test/library-tests/PathResolution/NodeModules/outermain.ts b/javascript/ql/test/library-tests/PathResolution/NodeModules/outermain.ts new file mode 100644 index 000000000000..47da8ef42292 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/NodeModules/outermain.ts @@ -0,0 +1,2 @@ +import 'foo'; // $ importTarget=NodeModules/node_modules/foo/index.js +import 'bar'; // $ SPURIOUS: importTarget=NodeModules/subfolder/node_modules/bar/index.js // Technically would not resolve diff --git a/javascript/ql/test/library-tests/PathResolution/NodeModules/subfolder/node_modules/bar/index.js b/javascript/ql/test/library-tests/PathResolution/NodeModules/subfolder/node_modules/bar/index.js new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/NodeModules/subfolder/node_modules/bar/index.js @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/NodeModules/subfolder/node_modules/bar/package.json b/javascript/ql/test/library-tests/PathResolution/NodeModules/subfolder/node_modules/bar/package.json new file mode 100644 index 000000000000..f31168998ef3 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/NodeModules/subfolder/node_modules/bar/package.json @@ -0,0 +1,3 @@ +{ + "name": "bar" +} diff --git a/javascript/ql/test/library-tests/PathResolution/NodeModules/subfolder/src/main.ts b/javascript/ql/test/library-tests/PathResolution/NodeModules/subfolder/src/main.ts new file mode 100644 index 000000000000..1da40b0e2f8c --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/NodeModules/subfolder/src/main.ts @@ -0,0 +1,2 @@ +import 'foo'; // $ importTarget=NodeModules/node_modules/foo/index.js +import 'bar'; // $ importTarget=NodeModules/subfolder/node_modules/bar/index.js diff --git a/javascript/ql/test/library-tests/PathResolution/PackageGuess1/package.json b/javascript/ql/test/library-tests/PathResolution/PackageGuess1/package.json new file mode 100644 index 000000000000..ea524ea79000 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageGuess1/package.json @@ -0,0 +1,3 @@ +{ + "name": "@example/package-guess1" +} diff --git a/javascript/ql/test/library-tests/PathResolution/PackageGuess1/src/index.ts b/javascript/ql/test/library-tests/PathResolution/PackageGuess1/src/index.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageGuess1/src/index.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/PackageGuess2/blah/stuff.ts b/javascript/ql/test/library-tests/PathResolution/PackageGuess2/blah/stuff.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageGuess2/blah/stuff.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/PackageGuess2/package.json b/javascript/ql/test/library-tests/PathResolution/PackageGuess2/package.json new file mode 100644 index 000000000000..afa0dbe1c8ed --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageGuess2/package.json @@ -0,0 +1,6 @@ +{ + "name": "@example/package-guess2", + "files": [ + "./blah/stuff.js" + ] +} diff --git a/javascript/ql/test/library-tests/PathResolution/PackageIndexFile/index.js b/javascript/ql/test/library-tests/PathResolution/PackageIndexFile/index.js new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageIndexFile/index.js @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/PackageIndexFile/package.json b/javascript/ql/test/library-tests/PathResolution/PackageIndexFile/package.json new file mode 100644 index 000000000000..8d52b4ea6560 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageIndexFile/package.json @@ -0,0 +1,3 @@ +{ + "name": "@example/package-with-index-file" +} diff --git a/javascript/ql/test/library-tests/PathResolution/PackageWithExports/fake-file-impl.js b/javascript/ql/test/library-tests/PathResolution/PackageWithExports/fake-file-impl.js new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageWithExports/fake-file-impl.js @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/PackageWithExports/main.js b/javascript/ql/test/library-tests/PathResolution/PackageWithExports/main.js new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageWithExports/main.js @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/PackageWithExports/package.json b/javascript/ql/test/library-tests/PathResolution/PackageWithExports/package.json new file mode 100644 index 000000000000..229803c3301b --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageWithExports/package.json @@ -0,0 +1,14 @@ +{ + "name": "@example/package-with-exports", + "exports": { + ".": { + "default": "./main.js" + }, + "./fake-file": { + "default": "./fake-file-impl.js" + }, + "./star/*": { + "default": "./star-impl/*" + } + } +} diff --git a/javascript/ql/test/library-tests/PathResolution/PackageWithExports/star-impl/foo.js b/javascript/ql/test/library-tests/PathResolution/PackageWithExports/star-impl/foo.js new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageWithExports/star-impl/foo.js @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/PackageWithMain/main.js b/javascript/ql/test/library-tests/PathResolution/PackageWithMain/main.js new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageWithMain/main.js @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/PackageWithMain/package.json b/javascript/ql/test/library-tests/PathResolution/PackageWithMain/package.json new file mode 100644 index 000000000000..7aab9ed43163 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageWithMain/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/package-with-main", + "main": "./main.js" +} diff --git a/javascript/ql/test/library-tests/PathResolution/PackageWithMainExt/lib/main.ts b/javascript/ql/test/library-tests/PathResolution/PackageWithMainExt/lib/main.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageWithMainExt/lib/main.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/PackageWithMainExt/package.json b/javascript/ql/test/library-tests/PathResolution/PackageWithMainExt/package.json new file mode 100644 index 000000000000..c178bf7cbb2d --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageWithMainExt/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/package-with-main-ext", + "main": "./lib/main.js" +} diff --git a/javascript/ql/test/library-tests/PathResolution/PackageWithModuleMain/main.js b/javascript/ql/test/library-tests/PathResolution/PackageWithModuleMain/main.js new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageWithModuleMain/main.js @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/PackageWithModuleMain/package.json b/javascript/ql/test/library-tests/PathResolution/PackageWithModuleMain/package.json new file mode 100644 index 000000000000..ff43010d7d5b --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/PackageWithModuleMain/package.json @@ -0,0 +1,4 @@ +{ + "name": "@example/package-with-module-main", + "module": "./main.js" +} diff --git a/javascript/ql/test/library-tests/PathResolution/RootDir/my-root/foo.ts b/javascript/ql/test/library-tests/PathResolution/RootDir/my-root/foo.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/RootDir/my-root/foo.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/RootDir/tsconfig.json b/javascript/ql/test/library-tests/PathResolution/RootDir/tsconfig.json new file mode 100644 index 000000000000..2bfc42007b62 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/RootDir/tsconfig.json @@ -0,0 +1,7 @@ +{ + "include": ["my-root","my-tests"], + "compilerOptions": { + "rootDir": "./my-root", + "outDir": "./my-out", + } +} diff --git a/javascript/ql/test/library-tests/PathResolution/TSConfigOutDir/src/foo.ts b/javascript/ql/test/library-tests/PathResolution/TSConfigOutDir/src/foo.ts new file mode 100644 index 000000000000..ad1d380d6cc4 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/TSConfigOutDir/src/foo.ts @@ -0,0 +1 @@ +export const x = 1; diff --git a/javascript/ql/test/library-tests/PathResolution/TSConfigOutDir/tsconfig.json b/javascript/ql/test/library-tests/PathResolution/TSConfigOutDir/tsconfig.json new file mode 100644 index 000000000000..09d14078cb69 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/TSConfigOutDir/tsconfig.json @@ -0,0 +1,7 @@ +{ + "include": ["src"], + "compilerOptions": { + // Use unusual name to test independently of naming heuristics + "outDir": "./customOutDir" + } +} diff --git a/javascript/ql/test/library-tests/PathResolution/import-packages.ts b/javascript/ql/test/library-tests/PathResolution/import-packages.ts new file mode 100644 index 000000000000..8f1ec41d9cba --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/import-packages.ts @@ -0,0 +1,35 @@ +import './PackageWithMain/main'; // $ importTarget=PackageWithMain/main.js +import '@example/package-with-main'; // $ importTarget=PackageWithMain/main.js + +import './PackageWithModuleMain'; // $ MISSING: importTarget=PackageWithModuleMain/main.js +import '@example/package-with-module-main'; // $ importTarget=PackageWithModuleMain/main.js + +import './PackageWithExports'; // Not a valid import +import './PackageWithExports/fake-file'; // Not a valid import +import './PackageWithExports/star/foo'; // Not a valid import +import '@example/package-with-exports'; // $ importTarget=PackageWithExports/main.js +import '@example/package-with-exports/fake-file'; // $ MISSING: importTarget=PackageWithExports/fake-file-impl.js +import '@example/package-with-exports/star/foo'; // $ MISSING: importTarget=PackageWithExports/star-impl/foo.js + +import './PackageIndexFile'; // $ importTarget=PackageIndexFile/index.js +import '@example/package-with-index-file'; // $ importTarget=PackageIndexFile/index.js + +import './PackageGuess1'; // $ MISSING: importTarget=PackageGuess1/src/index.ts +import '@example/package-guess1'; // $ importTarget=PackageGuess1/src/index.ts + +import './PackageGuess2'; // $ MISSING: importTarget=PackageGuess2/blah/stuff.ts +import '@example/package-guess2'; // $ importTarget=PackageGuess2/blah/stuff.ts + +import './PackageWithMainExt'; // $ importTarget=PackageWithMainExt/lib/main.ts +import '@example/package-with-main-ext'; // $ importTarget=PackageWithMainExt/lib/main.ts + +import './TSConfigOutDir/customOutDir/foo.js'; // $ importTarget=TSConfigOutDir/src/foo.ts + +import './MainIsFolder'; // $ MISSING: importTarget=MainIsFolder/src/index.ts +import '@example/main-is-folder'; // $ importTarget=MainIsFolder/src/index.ts + +import './DistContainsSrc'; // $ MISSING: importTarget=DistContainsSrc/src/foo.ts + +import './MinifiedMain'; // $ MISSING: importTarget=MinifiedMain/src/library.ts + +import './RootDir/my-out/foo.js'; // $ importTarget=RootDir/my-root/foo.ts diff --git a/javascript/ql/test/library-tests/PathResolution/test.expected b/javascript/ql/test/library-tests/PathResolution/test.expected new file mode 100644 index 000000000000..cbabd2cc7bc7 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/test.expected @@ -0,0 +1,111 @@ +| BaseUrl/src/main.ts:2:1:2:26 | import ... /file"; | BaseUrl/base/lib/file.ts | +| BaseUrl/src/main.ts:3:1:3:29 | import ... le.ts"; | BaseUrl/base/lib/file.ts | +| BaseUrl/src/main.ts:4:1:4:29 | import ... le.js"; | BaseUrl/base/lib/file.ts | +| BaseUrl/src/main.ts:5:1:5:21 | import ... e/lib"; | BaseUrl/base/lib/index.ts | +| BaseUrl/src/main.ts:6:1:6:27 | import ... index"; | BaseUrl/base/lib/index.ts | +| BaseUrl/src/main.ts:7:1:7:30 | import ... ex.ts"; | BaseUrl/base/lib/index.ts | +| BaseUrl/src/main.ts:8:1:8:30 | import ... ex.js"; | BaseUrl/base/lib/index.ts | +| BaseUrl/src/main.ts:11:1:11:18 | import "lib/file"; | BaseUrl/base/lib/file.ts | +| BaseUrl/src/main.ts:12:1:12:21 | import ... le.ts"; | BaseUrl/base/lib/file.ts | +| BaseUrl/src/main.ts:13:1:13:21 | import ... le.js"; | BaseUrl/base/lib/file.ts | +| BaseUrl/src/main.ts:14:1:14:13 | import "lib"; | BaseUrl/base/lib/index.ts | +| BaseUrl/src/main.ts:15:1:15:19 | import "lib/index"; | BaseUrl/base/lib/index.ts | +| BaseUrl/src/main.ts:16:1:16:22 | import ... ex.ts"; | BaseUrl/base/lib/index.ts | +| BaseUrl/src/main.ts:17:1:17:22 | import ... ex.js"; | BaseUrl/base/lib/index.ts | +| BaseUrl/src/main.ts:20:1:20:16 | import "@/file"; | BaseUrl/base/lib/file.ts | +| BaseUrl/src/main.ts:21:1:21:19 | import "@/file.ts"; | BaseUrl/base/lib/file.ts | +| BaseUrl/src/main.ts:22:1:22:19 | import "@/file.js"; | BaseUrl/base/lib/file.ts | +| BaseUrl/src/main.ts:23:1:23:11 | import "@"; | BaseUrl/base/lib/nostar.ts | +| BaseUrl/src/main.ts:24:1:24:17 | import "@/index"; | BaseUrl/base/lib/index.ts | +| BaseUrl/src/main.ts:25:1:25:20 | import "@/index.ts"; | BaseUrl/base/lib/index.ts | +| BaseUrl/src/main.ts:26:1:26:20 | import "@/index.js"; | BaseUrl/base/lib/index.ts | +| BaseUrl/src/main.ts:29:1:29:16 | import "#/file"; | BaseUrl/base/lib/file.ts | +| BaseUrl/src/main.ts:30:1:30:19 | import "#/file.ts"; | BaseUrl/base/lib/file.ts | +| BaseUrl/src/main.ts:31:1:31:19 | import "#/file.js"; | BaseUrl/base/lib/file.ts | +| BaseUrl/src/main.ts:32:1:32:17 | import "#/index"; | BaseUrl/base/lib/index.ts | +| BaseUrl/src/main.ts:33:1:33:20 | import "#/index.ts"; | BaseUrl/base/lib/index.ts | +| BaseUrl/src/main.ts:34:1:34:20 | import "#/index.js"; | BaseUrl/base/lib/index.ts | +| BaseUrl/src/main.ts:37:1:37:19 | import "^lib/file"; | BaseUrl/base/lib/file.ts | +| BaseUrl/src/main.ts:38:1:38:20 | import "^lib2/file"; | BaseUrl/base/lib2/file.ts | +| Basic/Subdir/sub.ts:1:1:1:12 | import '..'; | Basic/index.ts | +| Basic/Subdir/sub.ts:2:1:2:13 | import '../'; | Basic/index.ts | +| Basic/Subdir/sub.ts:3:1:3:14 | import './..'; | Basic/index.ts | +| Basic/Subdir/sub.ts:4:1:4:15 | import './../'; | Basic/index.ts | +| Basic/index.ts:1:1:1:22 | import ... r/sub'; | Basic/Subdir/sub.ts | +| DeclarationFiles/src/main.ts:1:1:1:22 | import ... split"; | DeclarationFiles/lib/split.d.ts | +| DeclarationFiles/src/main.ts:1:1:1:22 | import ... split"; | DeclarationFiles/lib/split.js | +| DeclarationFiles/src/main.ts:2:1:2:25 | import ... it.js"; | DeclarationFiles/lib/split.d.ts | +| DeclarationFiles/src/main.ts:2:1:2:25 | import ... it.js"; | DeclarationFiles/lib/split.js | +| DeclarationFiles/src/main.ts:3:1:3:27 | import ... .d.ts"; | DeclarationFiles/lib/split.d.ts | +| DeclarationFiles/src/main.ts:5:1:5:27 | import ... cript"; | DeclarationFiles/lib/typescript.ts | +| DeclarationFiles/src/main.ts:6:1:6:30 | import ... pt.js"; | DeclarationFiles/lib/typescript.ts | +| DeclarationFiles/src/main.ts:7:1:7:32 | import ... .d.ts"; | DeclarationFiles/lib/typescript.d.ts | +| DeclarationFiles/src/main.ts:7:1:7:32 | import ... .d.ts"; | DeclarationFiles/lib/typescript.ts | +| DirnameImports/main.js:4:1:4:33 | require ... et.js') | DirnameImports/target.js | +| DirnameImports/main.js:5:1:5:40 | require ... et.js') | DirnameImports/nested/target.js | +| DirnameImports/main.js:6:1:6:45 | require ... es.ts') | import-packages.ts | +| DirnameImports/main.js:7:1:7:38 | require ... et.js') | DirnameImports/target.js | +| DirnameImports/main.js:9:1:9:42 | require ... t.js')) | DirnameImports/target.js | +| DirnameImports/main.js:13:1:13:48 | require ... et.js') | DirnameImports/nested/target.js | +| Extended/src/main.ts:2:1:2:21 | import ... /file"; | Extended/lib/file.ts | +| Extended/src/main.ts:3:1:3:24 | import ... le.ts"; | Extended/lib/file.ts | +| Extended/src/main.ts:4:1:4:24 | import ... le.js"; | Extended/lib/file.ts | +| Extended/src/main.ts:5:1:5:16 | import "../lib"; | Extended/lib/index.ts | +| Extended/src/main.ts:6:1:6:22 | import ... index"; | Extended/lib/index.ts | +| Extended/src/main.ts:7:1:7:25 | import ... ex.ts"; | Extended/lib/index.ts | +| Extended/src/main.ts:8:1:8:25 | import ... ex.js"; | Extended/lib/index.ts | +| Extended/src/main.ts:11:1:11:18 | import "lib/file"; | Extended/lib/file.ts | +| Extended/src/main.ts:12:1:12:21 | import ... le.ts"; | Extended/lib/file.ts | +| Extended/src/main.ts:13:1:13:21 | import ... le.js"; | Extended/lib/file.ts | +| Extended/src/main.ts:14:1:14:13 | import "lib"; | Extended/lib/index.ts | +| Extended/src/main.ts:15:1:15:19 | import "lib/index"; | Extended/lib/index.ts | +| Extended/src/main.ts:16:1:16:22 | import ... ex.ts"; | Extended/lib/index.ts | +| Extended/src/main.ts:17:1:17:22 | import ... ex.js"; | Extended/lib/index.ts | +| Extended/src/main.ts:20:1:20:16 | import "@/file"; | Extended/lib/file.ts | +| Extended/src/main.ts:21:1:21:19 | import "@/file.ts"; | Extended/lib/file.ts | +| Extended/src/main.ts:22:1:22:19 | import "@/file.js"; | Extended/lib/file.ts | +| Extended/src/main.ts:23:1:23:11 | import "@"; | Extended/lib/nostar.ts | +| Extended/src/main.ts:24:1:24:17 | import "@/index"; | Extended/lib/index.ts | +| Extended/src/main.ts:25:1:25:20 | import "@/index.ts"; | Extended/lib/index.ts | +| Extended/src/main.ts:26:1:26:20 | import "@/index.js"; | Extended/lib/index.ts | +| Fallback/src/main.ts:1:1:1:15 | import "@/both" | Fallback/lib1/both.ts | +| Fallback/src/main.ts:2:1:2:16 | import "@/only1" | Fallback/lib1/only1.ts | +| Fallback/src/main.ts:3:1:3:16 | import "@/only2" | Fallback/lib2/only2.ts | +| Fallback/src/main.ts:4:1:4:29 | import ... ension" | Fallback/lib2/differentExtension.ts | +| Fallback/src/main.ts:5:1:5:32 | import ... ion.js" | Fallback/lib2/differentExtension.ts | +| Fallback/src/main.ts:7:1:7:17 | import "@/subdir" | Fallback/lib1/subdir/index.ts | +| Fallback/src/main.ts:8:1:8:22 | import ... r/both" | Fallback/lib1/subdir/both.ts | +| Fallback/src/main.ts:9:1:9:23 | import ... /only1" | Fallback/lib1/subdir/only1.ts | +| Fallback/src/main.ts:10:1:10:23 | import ... /only2" | Fallback/lib2/subdir/only2.ts | +| JSDocProvide/main.js:1:1:1:43 | import ... r/baz'; | JSDocProvide/lib.js | +| NoBaseUrl/src/main.ts:2:1:2:21 | import ... /file"; | NoBaseUrl/lib/file.ts | +| NoBaseUrl/src/main.ts:3:1:3:24 | import ... le.ts"; | NoBaseUrl/lib/file.ts | +| NoBaseUrl/src/main.ts:4:1:4:24 | import ... le.js"; | NoBaseUrl/lib/file.ts | +| NoBaseUrl/src/main.ts:5:1:5:16 | import "../lib"; | NoBaseUrl/lib/index.ts | +| NoBaseUrl/src/main.ts:6:1:6:22 | import ... index"; | NoBaseUrl/lib/index.ts | +| NoBaseUrl/src/main.ts:7:1:7:25 | import ... ex.ts"; | NoBaseUrl/lib/index.ts | +| NoBaseUrl/src/main.ts:8:1:8:25 | import ... ex.js"; | NoBaseUrl/lib/index.ts | +| NoBaseUrl/src/main.ts:20:1:20:16 | import "@/file"; | NoBaseUrl/lib/file.ts | +| NoBaseUrl/src/main.ts:21:1:21:19 | import "@/file.ts"; | NoBaseUrl/lib/file.ts | +| NoBaseUrl/src/main.ts:22:1:22:19 | import "@/file.js"; | NoBaseUrl/lib/file.ts | +| NoBaseUrl/src/main.ts:23:1:23:11 | import "@"; | NoBaseUrl/lib/nostar.ts | +| NoBaseUrl/src/main.ts:24:1:24:17 | import "@/index"; | NoBaseUrl/lib/index.ts | +| NoBaseUrl/src/main.ts:25:1:25:20 | import "@/index.ts"; | NoBaseUrl/lib/index.ts | +| NoBaseUrl/src/main.ts:26:1:26:20 | import "@/index.js"; | NoBaseUrl/lib/index.ts | +| NodeModules/outermain.ts:1:1:1:13 | import 'foo'; | NodeModules/node_modules/foo/index.js | +| NodeModules/outermain.ts:2:1:2:13 | import 'bar'; | NodeModules/subfolder/node_modules/bar/index.js | +| NodeModules/subfolder/src/main.ts:1:1:1:13 | import 'foo'; | NodeModules/node_modules/foo/index.js | +| NodeModules/subfolder/src/main.ts:2:1:2:13 | import 'bar'; | NodeModules/subfolder/node_modules/bar/index.js | +| import-packages.ts:1:1:1:32 | import ... /main'; | PackageWithMain/main.js | +| import-packages.ts:2:1:2:36 | import ... -main'; | PackageWithMain/main.js | +| import-packages.ts:5:1:5:43 | import ... -main'; | PackageWithModuleMain/main.js | +| import-packages.ts:10:1:10:39 | import ... ports'; | PackageWithExports/main.js | +| import-packages.ts:14:1:14:28 | import ... xFile'; | PackageIndexFile/index.js | +| import-packages.ts:15:1:15:42 | import ... -file'; | PackageIndexFile/index.js | +| import-packages.ts:18:1:18:33 | import ... uess1'; | PackageGuess1/src/index.ts | +| import-packages.ts:21:1:21:33 | import ... uess2'; | PackageGuess2/blah/stuff.ts | +| import-packages.ts:23:1:23:30 | import ... inExt'; | PackageWithMainExt/lib/main.ts | +| import-packages.ts:24:1:24:40 | import ... n-ext'; | PackageWithMainExt/lib/main.ts | +| import-packages.ts:26:1:26:46 | import ... oo.js'; | TSConfigOutDir/src/foo.ts | +| import-packages.ts:29:1:29:33 | import ... older'; | MainIsFolder/src/index.ts | +| import-packages.ts:35:1:35:33 | import ... oo.js'; | RootDir/my-root/foo.ts | diff --git a/javascript/ql/test/library-tests/PathResolution/test.ql b/javascript/ql/test/library-tests/PathResolution/test.ql new file mode 100644 index 000000000000..a3cf0884659a --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/test.ql @@ -0,0 +1,5 @@ +import javascript + +query predicate importTarget(Import imprt, string value) { + imprt.getImportedModule().getFile().getRelativePath() = value +} diff --git a/javascript/ql/test/library-tests/PathResolution/test.qlref b/javascript/ql/test/library-tests/PathResolution/test.qlref new file mode 100644 index 000000000000..ab6773f15f90 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/test.qlref @@ -0,0 +1,2 @@ +query: test.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql diff --git a/javascript/ql/test/library-tests/PathResolution/tsconfig.json b/javascript/ql/test/library-tests/PathResolution/tsconfig.json new file mode 100644 index 000000000000..81edd78b2ff8 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/tsconfig.json @@ -0,0 +1 @@ +{} // dummy file to enable full TS extraction From 17aa5220a60775265c124eedb0d394b3aafecb7d Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 24 Apr 2025 09:04:18 +0200 Subject: [PATCH 135/336] JS: Add some helpers --- javascript/ql/lib/semmle/javascript/Files.qll | 13 +++++++++++++ javascript/ql/lib/semmle/javascript/NPM.qll | 11 ++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/Files.qll b/javascript/ql/lib/semmle/javascript/Files.qll index 9febb67117d9..e717eb6def41 100644 --- a/javascript/ql/lib/semmle/javascript/Files.qll +++ b/javascript/ql/lib/semmle/javascript/Files.qll @@ -75,6 +75,19 @@ class Folder extends Container, Impl::Folder { ) } + /** + * Gets an implementation file and/or a typings file from this folder that has the given `stem`. + * This could be a single `.ts` file or a pair of `.js` and `.d.ts` files. + */ + File getJavaScriptFileOrTypings(string stem) { + exists(File jsFile | jsFile = this.getJavaScriptFile(stem) | + result = jsFile + or + not jsFile.getFileType().isTypeScript() and + result = this.getFile(stem + ".d.ts") + ) + } + /** Gets a subfolder contained in this folder. */ Folder getASubFolder() { result = this.getAChildContainer() } } diff --git a/javascript/ql/lib/semmle/javascript/NPM.qll b/javascript/ql/lib/semmle/javascript/NPM.qll index b70ff8055b4f..b625612aa338 100644 --- a/javascript/ql/lib/semmle/javascript/NPM.qll +++ b/javascript/ql/lib/semmle/javascript/NPM.qll @@ -12,12 +12,21 @@ class PackageJson extends JsonObject { this.isTopLevel() } + /** Gets the folder containing this `package.json` file. */ + Folder getFolder() { result = this.getJsonFile().getParentContainer() } + + /** + * Gets the name of this package as it appears in the `name` field. + */ + pragma[nomagic] + string getDeclaredPackageName() { result = this.getPropStringValue("name") } + /** * Gets the name of this package. * If the package is located under the package `pkg1` and its relative path is `foo/bar`, then the resulting package name will be `pkg1/foo/bar`. */ string getPackageName() { - result = this.getPropStringValue("name") + result = this.getDeclaredPackageName() or exists( PackageJson parentPkg, Container currentDir, Container parentDir, string parentPkgName, From ef32a036b1e40ba0a793398f34986b46e1165f39 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 28 Apr 2025 13:23:34 +0200 Subject: [PATCH 136/336] JS: Extract from methods from PathString into a non-abstract base class The new class 'FilePath' has bindingset[this] so one just has to cast a string to that type and you can use its methods. --- javascript/ql/lib/semmle/javascript/Paths.qll | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/Paths.qll b/javascript/ql/lib/semmle/javascript/Paths.qll index 66a840e9f26b..cfbe00afbeea 100644 --- a/javascript/ql/lib/semmle/javascript/Paths.qll +++ b/javascript/ql/lib/semmle/javascript/Paths.qll @@ -96,27 +96,22 @@ private class ConsPath extends Path, TConsPath { private string pathRegex() { result = "(.*)(?:/|^)(([^/]*?)(\\.([^.]*))?)" } /** - * A string value that represents a (relative or absolute) file system path. - * - * Each path string is associated with one or more root folders relative to - * which the path may be resolved. For instance, paths inside a module are - * usually resolved relative to the module's folder, with a default - * lookup path as the fallback. + * A `string` with some additional member predicates for extracting parts of a file path. */ -abstract class PathString extends string { +class FilePath extends string { bindingset[this] - PathString() { any() } - - /** Gets a root folder relative to which this path can be resolved. */ - abstract Folder getARootFolder(); + FilePath() { any() } /** Gets the `i`th component of this path. */ + bindingset[this] string getComponent(int i) { result = this.splitAt("/", i) } /** Gets the number of components of this path. */ + bindingset[this] int getNumComponent() { result = count(int i | exists(this.getComponent(i))) } /** Gets the base name of the folder or file this path refers to. */ + bindingset[this] string getBaseName() { result = this.regexpCapture(pathRegex(), 2) } /** @@ -124,9 +119,11 @@ abstract class PathString extends string { * up to (but not including) the last dot character if there is one, or the entire * base name if there is not */ + bindingset[this] string getStem() { result = this.regexpCapture(pathRegex(), 3) } /** Gets the path of the parent folder of the folder or file this path refers to. */ + bindingset[this] string getDirName() { result = this.regexpCapture(pathRegex(), 1) } /** @@ -135,8 +132,26 @@ abstract class PathString extends string { * * Has no result if the base name does not contain a dot. */ + bindingset[this] string getExtension() { result = this.regexpCapture(pathRegex(), 4) } +} + +/** + * A string value that represents a (relative or absolute) file system path. + * + * Each path string is associated with one or more root folders relative to + * which the path may be resolved. For instance, paths inside a module are + * usually resolved relative to the module's folder, with a default + * lookup path as the fallback. + */ +abstract class PathString extends FilePath { + bindingset[this] + PathString() { any() } + + /** Gets a root folder relative to which this path can be resolved. */ + abstract Folder getARootFolder(); + /** * Gets the absolute path that the sub-path consisting of the first `n` * components of this path refers to when resolved relative to the From 59e1cbcc7b795f3f65a7c6612ec470d6834e95ab Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 24 Apr 2025 09:06:33 +0200 Subject: [PATCH 137/336] JS: Add tsconfig class --- .../ql/lib/semmle/javascript/TSConfig.qll | 180 ++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 javascript/ql/lib/semmle/javascript/TSConfig.qll diff --git a/javascript/ql/lib/semmle/javascript/TSConfig.qll b/javascript/ql/lib/semmle/javascript/TSConfig.qll new file mode 100644 index 000000000000..358326c20d7a --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/TSConfig.qll @@ -0,0 +1,180 @@ +/** + * Provides a class for working with `tsconfig.json` files. + */ + +private import javascript + +/** + * A TypeScript configuration file, usually named `tsconfig.json`. + */ +class TSConfig extends JsonObject { + TSConfig() { + this.getJsonFile().getBaseName().matches("%tsconfig%.json") and + this.isTopLevel() + } + + /** Gets the folder containing this file. */ + Folder getFolder() { result = this.getJsonFile().getParentContainer() } + + /** Gets the `compilerOptions` object. */ + JsonObject getCompilerOptions() { result = this.getPropValue("compilerOptions") } + + /** Gets the string value in the `extends` property. */ + string getExtendsPath() { result = this.getPropStringValue("extends") } + + /** Gets the file referred to by the `extends` property. */ + File getExtendedFile() { result = Resolver::resolve(this.getFolder(), this.getExtendsPath()) } + + /** Gets the `TSConfig` file referred to by the `extends` property. */ + TSConfig getExtendedTSConfig() { result.getJsonFile() = this.getExtendedFile() } + + /** Gets the string value in the `baseUrl` property. */ + string getBaseUrlPath() { result = this.getCompilerOptions().getPropStringValue("baseUrl") } + + /** Gets the folder referred to by the `baseUrl` property in this file, not taking `extends` into account. */ + Folder getOwnBaseUrlFolder() { + result = Resolver::resolve(this.getFolder(), this.getBaseUrlPath()) + } + + /** Gets the effective baseUrl folder for this tsconfig file. */ + Folder getBaseUrlFolder() { + result = this.getOwnBaseUrlFolder() + or + not exists(this.getOwnBaseUrlFolder()) and + result = this.getExtendedTSConfig().getBaseUrlFolder() + } + + /** Gets the effective baseUrl folder for this tsconfig file, or its enclosing folder if there is no baseUrl. */ + Folder getBaseUrlFolderOrOwnFolder() { + result = this.getBaseUrlFolder() + or + not exists(this.getBaseUrlFolder()) and + result = this.getFolder() + } + + /** Gets a path mentioned in the `include` property. */ + string getAnIncludePath() { + result = this.getPropStringValue("include") + or + result = this.getPropValue("include").(JsonArray).getElementStringValue(_) + } + + /** + * Gets a file or folder refenced by a path the `include` property, possibly + * inherited from an extended tsconfig file. + * + * Does not include all the files within includes directories, use `getAnIncludedContainer` for that. + */ + Container getAnIncludePathTarget() { + result = Resolver::resolve(this.getFolder(), this.getAnIncludePath()) + or + not exists(this.getPropValue("include")) and + result = this.getExtendedTSConfig().getAnIncludePathTarget() + } + + /** + * Gets a file or folder inside the directory tree mentioned in the `include` property. + */ + Container getAnIncludedContainer() { + result = this.getAnIncludePathTarget() + or + result = this.getAnIncludedContainer().getAChildContainer() + } + + /** Gets the path mentioned in the `rootDir` property. */ + string getRootDirPath() { result = this.getCompilerOptions().getPropStringValue("rootDir") } + + private Container getOwnRootDir() { + result = Resolver::resolve(this.getFolder(), this.getRootDirPath()) + } + + /** Gets the file or folder referenced by the `rootDir` property. */ + Container getRootDir() { + result = this.getOwnRootDir() + or + not exists(this.getRootDirPath()) and + result = this.getExtendedTSConfig().getOwnRootDir() + } + + private string getATopLevelIncludePath() { + result = this.getAnIncludePath().(FilePath).getComponent(0) + } + + private string getUniqueTopLevelIncludePath() { + result = unique( | | this.getATopLevelIncludePath()) + } + + /** + * Gets the folder referred to by the `rootDir` property, or if absent, an effective root dir + * derived from `include` paths. + */ + Container getEffectiveRootDir() { + result = this.getRootDir() + or + not exists(this.getRootDir()) and + ( + result = this.getFolder().getFolder(this.getUniqueTopLevelIncludePath()) + or + not exists(this.getUniqueTopLevelIncludePath()) and + exists(this.getATopLevelIncludePath()) and + result = this.getFolder() + or + not exists(this.getATopLevelIncludePath()) and + result = this.getExtendedTSConfig().getEffectiveRootDir() + ) + } + + private JsonObject getPathMappings() { result = this.getCompilerOptions().getPropValue("paths") } + + /** + * Holds if this has a path mapping from `pattern` to `newPath`. + * + * For example, `"paths": { "@/*": "./src/*" }` maps the `@/*` pattern to `./src/*`. + * + * Does not include path mappings from extended tsconfig files. + */ + predicate hasPathMapping(string pattern, string newPath) { + this.getPathMappings().getPropStringValue(pattern) = newPath + or + this.getPathMappings().getPropValue(pattern).(JsonArray).getElementStringValue(_) = newPath + } + + /** + * Holds if this has an exact path mapping from `pattern` to `newPath`. + * + * For example, `"paths": { "@": "./src/index.ts" }` maps the `@` path to `./src/index.ts`. + * + * Does not include path mappings from extended tsconfig files. + */ + predicate hasExactPathMapping(string pattern, string newPath) { + this.hasPathMapping(pattern, newPath) and + not pattern.matches("%*%") + } + + /** + * Holds if this has a path mapping from the `pattern` prefix to the `newPath` prefix. + * The trailing `*` is not included. + * + * For example, `"paths": { "@/*": "./src/*" }` maps the `@/` pattern to `./src/`. + * + * Does not include path mappings from extended tsconfig files. + */ + predicate hasPrefixPathMapping(string pattern, string newPath) { + this.hasPathMapping(pattern + "*", newPath + "*") + } +} + +/** For resolving paths in a tsconfig file, except `paths` mappings. */ +private module ResolverConfig implements Folder::ResolveSig { + predicate shouldResolve(Container base, string path) { + exists(TSConfig cfg | + base = cfg.getFolder() and + path = + [cfg.getExtendsPath(), cfg.getBaseUrlPath(), cfg.getRootDirPath(), cfg.getAnIncludePath()] + ) + } + + predicate allowGlobs() { any() } // "include" can use globs +} + +private module Resolver = Folder::Resolve; From bb91df814539ca8af695fbd24d7163cafca36341 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 24 Apr 2025 11:12:55 +0200 Subject: [PATCH 138/336] JS: Add helper for doing path resolution with JS rules --- .../javascript/internal/paths/JSPaths.qll | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 javascript/ql/lib/semmle/javascript/internal/paths/JSPaths.qll diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/JSPaths.qll b/javascript/ql/lib/semmle/javascript/internal/paths/JSPaths.qll new file mode 100644 index 000000000000..dc90dcc39469 --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/internal/paths/JSPaths.qll @@ -0,0 +1,70 @@ +/** + * Provides predicates for use in `Folder::ResolveSig` in order to resolve + * paths using JavaScript semantics. + */ + +private import javascript +private import semmle.javascript.TSConfig + +/** + * Gets a folder name that is a common source folder name. + */ +string getASrcFolderName() { result = ["ts", "js", "src", "lib"] } + +/** + * Gets a folder name that is a common build output folder name. + */ +string getABuildOutputFolderName() { result = ["dist", "build", "out", "lib"] } + +/** + * Provides predicates for use in a `Folder::ResolveSig` in order to resolve + * paths using JavaScript semantics. + * + * This accounts for two things: + * - automatic file extensions (e.g `./foo` may resolve to `./foo.js`) + * - mapping compiled-generated files back to their original source files + */ +module JSPaths { + private Container getAnAdditionalChildFromBuildMapping(Container base, string name) { + // When importing a .js file, map to the original file that compiles to the .js file. + exists(string stem | + result = base.(Folder).getJavaScriptFileOrTypings(stem) and + name = stem + ".js" + ) + or + // Redirect './bar' to 'foo' given a tsconfig like: + // + // { include: ["foo"], compilerOptions: { outDir: "./bar" }} + // + exists(TSConfig tsconfig | + name = + tsconfig.getCompilerOptions().getPropStringValue("outDir").regexpReplaceAll("^\\./", "") and + base = tsconfig.getFolder() and + result = tsconfig.getEffectiveRootDir() + ) + } + + /** + * Gets an additional child of `base` to include when resolving JS paths. + */ + pragma[nomagic] + Container getAnAdditionalChild(Container base, string name) { + // Automatically fill in file extensions + result = base.(Folder).getJavaScriptFileOrTypings(name) + or + result = getAnAdditionalChildFromBuildMapping(base, name) + or + // Heuristic version of the above based on commonly used source and build folder names + not exists(getAnAdditionalChildFromBuildMapping(base, name)) and + exists(Folder folder | base = folder | + folder = any(PackageJson pkg).getFolder() and + name = getABuildOutputFolderName() and + not exists(folder.getJavaScriptFileOrTypings(name)) and + ( + result = folder.getChildContainer(getASrcFolderName()) + or + result = folder + ) + ) + } +} From f542956f66d930be53e7b3134b39a251bbdb354c Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 24 Apr 2025 11:13:10 +0200 Subject: [PATCH 139/336] JS: Add internal extension of PackageJson class --- javascript/ql/lib/semmle/javascript/NPM.qll | 32 ++-- .../internal/paths/PackageJsonEx.qll | 151 ++++++++++++++++++ 2 files changed, 162 insertions(+), 21 deletions(-) create mode 100644 javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll diff --git a/javascript/ql/lib/semmle/javascript/NPM.qll b/javascript/ql/lib/semmle/javascript/NPM.qll index b625612aa338..92e349594144 100644 --- a/javascript/ql/lib/semmle/javascript/NPM.qll +++ b/javascript/ql/lib/semmle/javascript/NPM.qll @@ -4,6 +4,7 @@ import javascript private import NodeModuleResolutionImpl +private import semmle.javascript.internal.paths.PackageJsonEx /** A `package.json` configuration object. */ class PackageJson extends JsonObject { @@ -93,7 +94,10 @@ class PackageJson extends JsonObject { * `module` paths to be exported under the relative path `"."`. */ string getExportedPath(string relativePath) { - result = MainModulePath::of(this, relativePath).getValue() + this.(PackageJsonEx).hasExactPathMapping(relativePath, result) + or + relativePath = "." and + result = this.(PackageJsonEx).getMainPath() } /** Gets the path of a command defined for this package. */ @@ -220,7 +224,7 @@ class PackageJson extends JsonObject { /** * Gets the main module of this package. */ - Module getMainModule() { result = this.getExportedModule(".") } + Module getMainModule() { result.getFile() = this.(PackageJsonEx).getMainFileOrBestGuess() } /** * Gets the module exported under the given relative path. @@ -228,12 +232,10 @@ class PackageJson extends JsonObject { * The main module is considered exported under the path `"."`. */ Module getExportedModule(string relativePath) { - result = - min(Module m, int prio | - m.getFile() = resolveMainModule(this, prio, relativePath) - | - m order by prio - ) + this.(PackageJsonEx).hasExactPathMappingTo(relativePath, result.getFile()) + or + relativePath = "." and + result = this.getMainModule() } /** @@ -245,19 +247,7 @@ class PackageJson extends JsonObject { * Gets the file containing the typings of this package, which can either be from the `types` or * `typings` field, or derived from the `main` or `module` fields. */ - File getTypingsFile() { - result = - TypingsModulePathString::of(this).resolve(this.getFile().getParentContainer()).getContainer() - or - not exists(TypingsModulePathString::of(this)) and - exists(File mainFile | - mainFile = this.getMainModule().getFile() and - result = - mainFile - .getParentContainer() - .getFile(mainFile.getStem().regexpReplaceAll("\\.d$", "") + ".d.ts") - ) - } + File getTypingsFile() { none() } // implemented in PackageJsonEx /** * Gets the module containing the typings of this package, which can either be from the `types` or diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll new file mode 100644 index 000000000000..4e2a51aaf7d4 --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll @@ -0,0 +1,151 @@ +private import javascript +private import semmle.javascript.internal.paths.JSPaths + +/** + * Extension of `PackageJson` with some internal path-resolution predicates. + */ +class PackageJsonEx extends PackageJson { + private JsonValue getAPartOfExportsSection(string pattern) { + result = this.getPropValue("exports") and + pattern = "" + or + exists(string prop, string prevPath | + result = this.getAPartOfExportsSection(prevPath).getPropValue(prop) and + if prop.matches("./%") then pattern = prop.suffix(2) else pattern = prevPath + ) + } + + predicate hasPathMapping(string pattern, string newPath) { + this.getAPartOfExportsSection(pattern).getStringValue() = newPath + } + + predicate hasExactPathMapping(string pattern, string newPath) { + this.getAPartOfExportsSection(pattern).getStringValue() = newPath and + not pattern.matches("%*%") + } + + predicate hasPrefixPathMapping(string pattern, string newPath) { + this.hasPathMapping(pattern + "*", newPath + "*") + } + + predicate hasExactPathMappingTo(string pattern, Container target) { + exists(string newPath | + this.hasExactPathMapping(pattern, newPath) and + target = Resolver::resolve(this.getFolder(), newPath) + ) + } + + predicate hasPrefixPathMappingTo(string pattern, Container target) { + exists(string newPath | + this.hasPrefixPathMapping(pattern, newPath) and + target = Resolver::resolve(this.getFolder(), newPath) + ) + } + + string getMainPath() { result = this.getPropStringValue(["main", "module"]) } + + File getMainFile() { + exists(Container main | main = Resolver::resolve(this.getFolder(), this.getMainPath()) | + result = main + or + result = main.(Folder).getJavaScriptFileOrTypings("index") + ) + } + + File getMainFileOrBestGuess() { + result = this.getMainFile() + or + result = guessPackageJsonMain1(this) + or + result = guessPackageJsonMain2(this) + } + + string getAPathInFilesArray() { + result = this.getPropValue("files").(JsonArray).getElementStringValue(_) + } + + Container getAFileInFilesArray() { + result = Resolver::resolve(this.getFolder(), this.getAPathInFilesArray()) + } + + override File getTypingsFile() { + result = Resolver::resolve(this.getFolder(), this.getTypings()) + or + not exists(this.getTypings()) and + exists(File mainFile | + mainFile = this.getMainFileOrBestGuess() and + result = + mainFile + .getParentContainer() + .getFile(mainFile.getStem().regexpReplaceAll("\\.d$", "") + ".d.ts") + ) + } +} + +private module ResolverConfig implements Folder::ResolveSig { + additional predicate shouldResolve(PackageJsonEx pkg, Container base, string path) { + base = pkg.getFolder() and + ( + pkg.hasExactPathMapping(_, path) + or + pkg.hasPrefixPathMapping(_, path) + or + path = pkg.getMainPath() + or + path = pkg.getAPathInFilesArray() + or + path = pkg.getTypings() + ) + } + + predicate shouldResolve(Container base, string path) { shouldResolve(_, base, path) } + + predicate getAnAdditionalChild = JSPaths::getAnAdditionalChild/2; + + predicate isOptionalPathComponent(string segment) { + // Try to omit paths can might refer to a build format, .e.g `dist/cjs/foo.cjs` -> `src/foo.ts` + segment = ["cjs", "mjs", "js"] + } + + bindingset[segment] + string rewritePathSegment(string segment) { + // Try removing anything after the first dot, such as foo.min.js -> foo (the extension is then filled in by getAdditionalChild) + result = segment.regexpReplaceAll("\\..*", "") + } +} + +private module Resolver = Folder::Resolve; + +/** + * Removes the scope from a package name, e.g. `@foo/bar` -> `bar`. + */ +bindingset[name] +private string stripPackageScope(string name) { result = name.regexpReplaceAll("^@[^/]+/", "") } + +private predicate isImplementationFile(File f) { not f.getBaseName().matches("%.d.ts") } + +File guessPackageJsonMain1(PackageJsonEx pkg) { + not isImplementationFile(pkg.getMainFile()) and + exists(Folder folder, Folder subfolder | + folder = pkg.getFolder() and + ( + subfolder = folder or + subfolder = folder.getChildContainer(getASrcFolderName()) or + subfolder = + folder + .getChildContainer(getASrcFolderName()) + .(Folder) + .getChildContainer(getASrcFolderName()) + ) + | + result = subfolder.getJavaScriptFileOrTypings("index") + or + result = subfolder.getJavaScriptFileOrTypings(stripPackageScope(pkg.getDeclaredPackageName())) + ) +} + +File guessPackageJsonMain2(PackageJsonEx pkg) { + not isImplementationFile(pkg.getMainFile()) and + not isImplementationFile(guessPackageJsonMain1(pkg)) and + result = pkg.getAFileInFilesArray() +} From ed4864edf7bb6cd9afe1e9e0aeb66f5b086ea789 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 28 Apr 2025 13:24:06 +0200 Subject: [PATCH 140/336] JS: Add two more helpers to FilePath class --- javascript/ql/lib/semmle/javascript/Paths.qll | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/javascript/ql/lib/semmle/javascript/Paths.qll b/javascript/ql/lib/semmle/javascript/Paths.qll index cfbe00afbeea..981e43f8966d 100644 --- a/javascript/ql/lib/semmle/javascript/Paths.qll +++ b/javascript/ql/lib/semmle/javascript/Paths.qll @@ -135,6 +135,31 @@ class FilePath extends string { bindingset[this] string getExtension() { result = this.regexpCapture(pathRegex(), 4) } + /** + * Holds if this is a relative path starting with an explicit `./` or similar syntax meaning it + * must be resolved relative to its enclosing folder. + * + * Specifically this holds when the string is `.` or `..`, or starts with `./` or `../` or + * `.\` or `..\`. + */ + bindingset[this] + pragma[inline_late] + predicate isDotRelativePath() { this.regexpMatch("\\.\\.?(?:[/\\\\].*)?") } + + /** + * Gets the NPM package name from the beginning of the given import path. + * + * Has no result for paths starting with a `.` or `/` + * + * For example: + * - `foo/bar` maps to `foo` + * - `@example/foo/bar` maps to `@example/foo` + * - `./foo` maps to nothing. + */ + bindingset[this] + string getPackagePrefix() { + result = this.regexpFind("^(@[^/\\\\]+[/\\\\])?[^@./\\\\][^/\\\\]*", _, _) + } } /** From 6725cb5b8cb73f3810d7ad26c70ebad772fa8977 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Apr 2025 12:52:15 +0200 Subject: [PATCH 141/336] JS: Implement import resolution --- .../lib/semmle/javascript/ES2015Modules.qll | 18 +- .../ql/lib/semmle/javascript/Modules.qll | 66 +---- .../ql/lib/semmle/javascript/TSConfig.qll | 42 +++ .../internal/paths/PathConcatenation.qll | 35 +++ .../internal/paths/PathExprResolver.qll | 249 ++++++++++++++++++ .../javascript/internal/paths/PathMapping.qll | 31 +++ .../test/library-tests/NodeJS/tests.expected | 4 +- .../DeclarationFiles/src/main.ts | 2 +- .../PathResolution/Fallback/src/main.ts | 10 +- .../PathResolution/import-packages.ts | 16 +- .../PathResolution/test.expected | 14 +- 11 files changed, 394 insertions(+), 93 deletions(-) create mode 100644 javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll create mode 100644 javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll create mode 100644 javascript/ql/lib/semmle/javascript/internal/paths/PathMapping.qll diff --git a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll index cc84fb87324d..378094e7c982 100644 --- a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll +++ b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll @@ -2,6 +2,7 @@ import javascript private import semmle.javascript.internal.CachedStages +private import semmle.javascript.internal.paths.PathExprResolver /** * An ECMAScript 2015 module. @@ -725,22 +726,7 @@ abstract class ReExportDeclaration extends ExportDeclaration { cached Module getReExportedModule() { Stages::Imports::ref() and - result.getFile() = this.getEnclosingModule().resolve(this.getImportedPath()) - or - result = this.resolveFromTypeRoot() - } - - /** - * Gets a module in a `node_modules/@types/` folder that matches the imported module name. - */ - private Module resolveFromTypeRoot() { - result.getFile() = - min(TypeRootFolder typeRoot | - | - typeRoot.getModuleFile(this.getImportedPath().getStringValue()) - order by - typeRoot.getSearchPriority(this.getFile().getParentContainer()) - ) + result.getFile() = ImportPathResolver::resolveExpr(this.getImportedPath()) } } diff --git a/javascript/ql/lib/semmle/javascript/Modules.qll b/javascript/ql/lib/semmle/javascript/Modules.qll index 8c36044bb24d..6dc27f980b8f 100644 --- a/javascript/ql/lib/semmle/javascript/Modules.qll +++ b/javascript/ql/lib/semmle/javascript/Modules.qll @@ -6,6 +6,7 @@ import javascript private import semmle.javascript.internal.CachedStages +private import semmle.javascript.internal.paths.PathExprResolver /** * A module, which may either be an ECMAScript 2015-style module, @@ -138,39 +139,17 @@ abstract class Import extends AstNode { /** * Gets the module the path of this import resolves to. */ - Module resolveImportedPath() { - result.getFile() = this.getEnclosingModule().resolve(this.getImportedPath()) - } + Module resolveImportedPath() { result.getFile() = this.getTargetFile() } /** - * Gets a module with a `@providesModule` JSDoc tag that matches - * the imported path. - */ - private Module resolveAsProvidedModule() { - exists(JSDocTag tag | - tag.getTitle() = "providesModule" and - tag.getParent().getComment().getTopLevel() = result and - tag.getDescription().trim() = this.getImportedPath().getValue() - ) - } - - /** - * Gets a module in a `node_modules/@types/` folder that matches the imported module name. + * Gets the module the path of this import resolves to. */ - private Module resolveFromTypeRoot() { - result.getFile() = - min(TypeRootFolder typeRoot | - | - typeRoot.getModuleFile(this.getImportedPath().getValue()) - order by - typeRoot.getSearchPriority(this.getFile().getParentContainer()) - ) - } + File getTargetFile() { result = ImportPathResolver::resolveExpr(this.getImportedPath()) } /** - * Gets the imported module, as determined by the TypeScript compiler, if any. + * DEPRECATED. Use `getImportedModule()` instead. */ - private Module resolveFromTypeScriptSymbol() { + deprecated Module resolveFromTypeScriptSymbol() { exists(CanonicalName symbol | ast_node_symbol(this, symbol) and ast_node_symbol(result, symbol) @@ -190,13 +169,7 @@ abstract class Import extends AstNode { Stages::Imports::ref() and if exists(this.resolveExternsImport()) then result = this.resolveExternsImport() - else ( - result = this.resolveAsProvidedModule() or - result = this.resolveImportedPath() or - result = this.resolveFromTypeRoot() or - result = this.resolveFromTypeScriptSymbol() or - result = resolveNeighbourPackage(this.getImportedPath().getValue()) - ) + else result = this.resolveImportedPath() } /** @@ -204,28 +177,3 @@ abstract class Import extends AstNode { */ abstract DataFlow::Node getImportedModuleNode(); } - -/** - * Gets a module imported from another package in the same repository. - * - * No support for importing from folders inside the other package. - */ -private Module resolveNeighbourPackage(PathString importPath) { - exists(PackageJson json | importPath = json.getPackageName() and result = json.getMainModule()) - or - exists(string package | - result.getFile().getParentContainer() = getPackageFolder(package) and - importPath = package + "/" + [result.getFile().getBaseName(), result.getFile().getStem()] - ) -} - -/** - * Gets the folder for a package that has name `package` according to a package.json file in the resulting folder. - */ -pragma[noinline] -private Folder getPackageFolder(string package) { - exists(PackageJson json | - json.getPackageName() = package and - result = json.getFile().getParentContainer() - ) -} diff --git a/javascript/ql/lib/semmle/javascript/TSConfig.qll b/javascript/ql/lib/semmle/javascript/TSConfig.qll index 358326c20d7a..b38fa1d1dc92 100644 --- a/javascript/ql/lib/semmle/javascript/TSConfig.qll +++ b/javascript/ql/lib/semmle/javascript/TSConfig.qll @@ -3,6 +3,7 @@ */ private import javascript +private import semmle.javascript.internal.paths.PathMapping /** * A TypeScript configuration file, usually named `tsconfig.json`. @@ -178,3 +179,44 @@ private module ResolverConfig implements Folder::ResolveSig { } private module Resolver = Folder::Resolve; + +/** + * Gets a tsconfig file to use as fallback for handling paths in `c`. + * + * This holds for files and folders where no tsconfig seems to include it, + * but it has one or more tsconfig files in parent directories. + */ +private TSConfig getFallbackTSConfig(Container c) { + not c = any(TSConfig t).getAnIncludedContainer() and + ( + c = result.getFolder() + or + result = getFallbackTSConfig(c.getParentContainer()) + ) +} + +private class TSConfigPathMapping extends PathMapping, TSConfig { + override File getAnAffectedFile() { + result = this.getAnIncludedContainer() + or + this = getFallbackTSConfig(result) + } + + override predicate hasExactPathMapping(string pattern, Container newContext, string newPath) { + exists(TSConfig tsconfig | + tsconfig = this.getExtendedTSConfig*() and + tsconfig.hasExactPathMapping(pattern, newPath) and + newContext = tsconfig.getBaseUrlFolderOrOwnFolder() + ) + } + + override predicate hasPrefixPathMapping(string pattern, Container newContext, string newPath) { + exists(TSConfig tsconfig | + tsconfig = this.getExtendedTSConfig*() and + tsconfig.hasPrefixPathMapping(pattern, newPath) and + newContext = tsconfig.getBaseUrlFolderOrOwnFolder() + ) + } + + override predicate hasBaseUrl(Container base) { base = this.getBaseUrlFolder() } +} diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll new file mode 100644 index 000000000000..448c7e55e016 --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll @@ -0,0 +1,35 @@ +private import javascript + +/** + * A path expression that can be constant-folded by concatenating subexpressions. + */ +abstract class PathConcatenation extends Expr { + /** Gets the separator to insert between paths */ + string getSeparator() { result = "" } + + /** Gets the `n`th operand to concatenate. */ + abstract Expr getOperand(int n); +} + +private class AddExprConcatenation extends PathConcatenation, AddExpr { + override Expr getOperand(int n) { + n = 0 and result = this.getLeftOperand() + or + n = 1 and result = this.getRightOperand() + } +} + +private class TemplateConcatenation extends PathConcatenation, TemplateLiteral { + override Expr getOperand(int n) { result = this.getElement(n) } +} + +private class JoinCallConcatenation extends PathConcatenation, CallExpr { + JoinCallConcatenation() { + this.getReceiver().(VarAccess).getName() = "path" and + this.getCalleeName() = ["join", "resolve"] + } + + override Expr getOperand(int n) { result = this.getArgument(n) } + + override string getSeparator() { result = "/" } +} diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll new file mode 100644 index 000000000000..853939dfe5f8 --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll @@ -0,0 +1,249 @@ +private import javascript +private import semmle.javascript.internal.paths.PackageJsonEx +private import semmle.javascript.internal.paths.JSPaths +private import semmle.javascript.internal.paths.PathMapping +private import semmle.javascript.internal.paths.PathConcatenation +private import semmle.javascript.dataflow.internal.DataFlowNode + +/** + * Gets the file to import when an imported path resolves to the given `folder`. + */ +File getFileFromFolderImport(Folder folder) { + result = folder.getJavaScriptFileOrTypings("index") + or + // Note that unlike "exports" paths, "main" and "module" also take effect when the package + // is imported via a relative path, e.g. `require("..")` targeting a folder with a package.json file. + exists(PackageJsonEx pkg | + pkg.getFolder() = folder and + result = pkg.getMainFileOrBestGuess() + ) +} + +private Variable dirnameVar() { result.getName() = "__dirname" } + +private Variable filenameVar() { result.getName() = "__filename" } + +private signature predicate exprSig(Expr e); + +module ResolveExpr { + /** Holds if we need the constant string-value of `node`. */ + private predicate needsConstantFolding(EarlyStageNode node) { + exists(Expr e | + shouldResolveExpr(e) and + node = TValueNode(e) + ) + or + exists(EarlyStageNode needsFolding | needsConstantFolding(needsFolding) | + DataFlow::Impl::earlyStageImmediateFlowStep(node, needsFolding) + or + exists(PathConcatenation joiner | + needsFolding = TValueNode(joiner) and + node = TValueNode(joiner.getOperand(_)) + ) + ) + } + + /** Gets the constant-value of `node` */ + language[monotonicAggregates] + private string getValue(EarlyStageNode node) { + needsConstantFolding(node) and + ( + exists(Expr e | node = TValueNode(e) | + result = e.getStringValue() + or + e = dirnameVar().getAnAccess() and + result = "./" // Ensure the path gets interpreted relative to the current directory + or + e = filenameVar().getAnAccess() and + result = "./" + e.getFile().getBaseName() + ) + or + exists(EarlyStageNode pred | + DataFlow::Impl::earlyStageImmediateFlowStep(pred, node) and + result = getValue(pred) + ) + or + exists(PathConcatenation join | + node = TValueNode(join) and + result = + strictconcat(int n, EarlyStageNode child, string sep | + child = TValueNode(join.getOperand(n)) and sep = join.getSeparator() + | + getValue(child), sep order by n + ) + ) + ) + } + + final private class FinalExpr = Expr; + + private class RelevantExpr extends FinalExpr { + RelevantExpr() { shouldResolveExpr(this) } + + /** Gets the string-value of this path. */ + string getValue() { result = getValue(TValueNode(this)) } + + /** Gets a path mapping affecting this path. */ + pragma[nomagic] + PathMapping getAPathMapping() { result.getAnAffectedFile() = this.getFile() } + + /** Gets the NPM package name from the beginning of this path. */ + pragma[nomagic] + string getPackagePrefix() { result = this.getValue().(FilePath).getPackagePrefix() } + } + + /** + * Holds if `expr` matches a path mapping, and should thus be resolved as `newPath` relative to `base`. + */ + pragma[nomagic] + private predicate resolveViaPathMapping(RelevantExpr expr, Container base, string newPath) { + // Handle path mappings such as `{ "paths": { "@/*": "./src/*" }}` in a tsconfig.json file + exists(PathMapping mapping, string value | + mapping = expr.getAPathMapping() and + value = expr.getValue() + | + mapping.hasExactPathMapping(value, base, newPath) + or + exists(string pattern, string suffix, string mappedPath | + mapping.hasPrefixPathMapping(pattern, base, mappedPath) and + value = pattern + suffix and + newPath = mappedPath + suffix + ) + ) + or + // Handle imports referring to a package by name, where we have a package.json + // file for that package in the codebase. This is treated separately from PathMapping for performance + // reasons, as there can be a large number of packages which affect all files in the project. + // + // This part only handles the "exports" property of package.json. "main" and "modules" are + // handled further down because their semantics are easier to handle there. + exists(PackageJsonEx pkg, string packageName, string remainder | + packageName = expr.getPackagePrefix() and + pkg.getDeclaredPackageName() = packageName and + remainder = expr.getValue().suffix(packageName.length()).regexpReplaceAll("^[/\\\\]", "") + | + // "exports": { ".": "./foo.js" } + // "exports": { "./foo.js": "./foo/impl.js" } + pkg.hasExactPathMappingTo(remainder, base) and + newPath = "" + or + // "exports": { "./*": "./foo/*" } + exists(string prefix | + pkg.hasPrefixPathMappingTo(prefix, base) and + remainder = prefix + newPath + ) + ) + } + + pragma[noopt] + private predicate relativePathExpr(RelevantExpr expr, Container base, FilePath path) { + expr instanceof RelevantExpr and + path = expr.getValue() and + path.isDotRelativePath() and + exists(File file | + file = expr.getFile() and + base = file.getParentContainer() + ) + } + + pragma[nomagic] + private Container getJSDocProvidedModule(string moduleName) { + exists(JSDocTag tag | + tag.getTitle() = "providesModule" and + tag.getDescription().trim() = moduleName and + tag.getFile() = result + ) + } + + /** + * Holds if `expr` should be resolved as `path` relative to `base`. + */ + pragma[nomagic] + private predicate shouldResolve(RelevantExpr expr, Container base, FilePath path) { + // Relative paths are resolved from their enclosing folder + relativePathExpr(expr, base, path) + or + resolveViaPathMapping(expr, base, path) + or + // Resolve from baseUrl of relevant tsconfig.json file + path = expr.getValue() and + not path.isDotRelativePath() and + expr.getAPathMapping().hasBaseUrl(base) + or + // If the path starts with the name of a package, resolve relative to the directory of that package. + // Note that `getFileFromFolderImport` may subsequently redirect this to the package's "main", + // so we don't have to deal with that here. + exists(PackageJson pkg, string packageName | + packageName = expr.getPackagePrefix() and + pkg.getDeclaredPackageName() = packageName and + path = expr.getValue().suffix(packageName.length()) and + base = pkg.getFolder() + ) + or + base = getJSDocProvidedModule(expr.getValue()) and + path = "" + } + + private module ResolverConfig implements Folder::ResolveSig { + predicate shouldResolve(Container base, string path) { shouldResolve(_, base, path) } + + predicate getAnAdditionalChild = JSPaths::getAnAdditionalChild/2; + } + + private module Resolver = Folder::Resolve; + + private Container resolvePathExpr1(RelevantExpr expr) { + exists(Container base, string path | + shouldResolve(expr, base, path) and + result = Resolver::resolve(base, path) + ) + } + + File resolveExpr(RelevantExpr expr) { + result = resolvePathExpr1(expr) + or + result = getFileFromFolderImport(resolvePathExpr1(expr)) + } + + module Debug { + class PathExprToDebug extends RelevantExpr { + PathExprToDebug() { this.getValue() = "vs/nls" } + } + + query PathExprToDebug pathExprs() { any() } + + query string getPackagePrefixFromPathExpr_(PathExprToDebug expr) { + result = expr.getPackagePrefix() + } + + query predicate resolveViaPathMapping_(PathExprToDebug expr, Container base, string newPath) { + resolveViaPathMapping(expr, base, newPath) + } + + query predicate shouldResolve_(PathExprToDebug expr, Container base, string newPath) { + shouldResolve(expr, base, newPath) + } + + query Container resolvePathExpr1_(PathExprToDebug expr) { result = resolvePathExpr1(expr) } + + query File resolveExpr_(PathExprToDebug expr) { result = resolveExpr(expr) } + + // Some predicates that are usually small enough that they don't need restriction + query File getPackageMainFile(PackageJsonEx pkg) { result = pkg.getMainFile() } + + query predicate guessPackageJsonMain1_ = guessPackageJsonMain1/1; + + query predicate guessPackageJsonMain2_ = guessPackageJsonMain2/1; + + query predicate getFileFromFolderImport_ = getFileFromFolderImport/1; + } +} + +private predicate isImportPathExpr(Expr e) { + e = any(Import imprt).getImportedPath() + or + e = any(ReExportDeclaration decl).getImportedPath() +} + +/** Resolves paths in imports and re-exports. */ +module ImportPathResolver = ResolveExpr; diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PathMapping.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PathMapping.qll new file mode 100644 index 000000000000..d3da0a51cfa3 --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PathMapping.qll @@ -0,0 +1,31 @@ +/** + * Provides an extensible mechanism for modeling path mappings. + */ + +private import javascript +private import semmle.javascript.TSConfig + +/** + * A `tsconfig.json`-like configuration object that can affect import resolution via path mappings. + */ +abstract class PathMapping extends Locatable { + /** + * Gets a file affected by this path mapping. + */ + abstract File getAnAffectedFile(); + + /** + * Holds if imports paths exactly matching `pattern` should be redirected to `newPath` + * resolved relative to `newContext`. + */ + predicate hasExactPathMapping(string pattern, Container newContext, string newPath) { none() } + + /** + * Holds if imports paths starting with `pattern` should have the matched prefix replaced by `newPath` + * and then resolved relative to `newContext`. + */ + predicate hasPrefixPathMapping(string pattern, Container newContext, string newPath) { none() } + + /** Holds if non-relative paths in affected files should be resolved relative to `base`. */ + predicate hasBaseUrl(Container base) { none() } +} diff --git a/javascript/ql/test/library-tests/NodeJS/tests.expected b/javascript/ql/test/library-tests/NodeJS/tests.expected index b97c6a345e8f..964b784cf93f 100644 --- a/javascript/ql/test/library-tests/NodeJS/tests.expected +++ b/javascript/ql/test/library-tests/NodeJS/tests.expected @@ -94,14 +94,12 @@ requireImport | a.js:3:6:3:23 | require('./sub/c') | ./sub/c | sub/c.js:1:1:4:0 | | | a.js:4:6:4:29 | require ... /d.js') | ./sub/../d.js | d.js:1:1:7:15 | | | a.js:7:1:7:18 | require('./sub/c') | ./sub/c | sub/c.js:1:1:4:0 | | -| a.js:10:1:10:18 | require(__dirname) | | index.js:1:1:3:0 | | -| a.js:11:1:11:25 | require ... + '/e') | /e | e.js:1:1:6:0 | | | a.js:12:1:12:28 | require ... + 'c') | ./sub/c | sub/c.js:1:1:4:0 | | | b.js:1:1:1:18 | require('./sub/c') | ./sub/c | sub/c.js:1:1:4:0 | | | d.js:7:1:7:14 | require('foo') | foo | sub/f.js:1:1:4:17 | | -| index.js:2:1:2:41 | require ... b.js")) | /index.js/../b.js | b.js:1:1:8:0 | | | mjs-files/require-from-js.js:1:12:1:36 | require ... on-me') | ./depend-on-me | mjs-files/depend-on-me.mjs:1:1:7:1 | | | mjs-files/require-from-js.js:2:12:2:39 | require ... me.js') | ./depend-on-me.js | mjs-files/depend-on-me.js:1:1:8:0 | | +| mjs-files/require-from-js.js:2:12:2:39 | require ... me.js') | ./depend-on-me.js | mjs-files/depend-on-me.mjs:1:1:7:1 | | | mjs-files/require-from-js.js:3:12:3:40 | require ... e.mjs') | ./depend-on-me.mjs | mjs-files/depend-on-me.mjs:1:1:7:1 | | | reexport/b.js:1:11:1:24 | require("./a") | ./a | reexport/a.js:1:1:3:1 | | | sub/c.js:1:1:1:15 | require('../a') | ../a | a.js:1:1:14:0 | | diff --git a/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/src/main.ts b/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/src/main.ts index cfa7c750d9af..7682a39f00a0 100644 --- a/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/src/main.ts +++ b/javascript/ql/test/library-tests/PathResolution/DeclarationFiles/src/main.ts @@ -4,4 +4,4 @@ import "../lib/split.d.ts"; // $ importTarget=DeclarationFiles/lib/split.d.ts import "../lib/typescript"; // $ importTarget=DeclarationFiles/lib/typescript.ts import "../lib/typescript.js"; // $ importTarget=DeclarationFiles/lib/typescript.ts -import "../lib/typescript.d.ts"; // $ importTarget=DeclarationFiles/lib/typescript.d.ts SPURIOUS: importTarget=DeclarationFiles/lib/typescript.ts +import "../lib/typescript.d.ts"; // $ importTarget=DeclarationFiles/lib/typescript.d.ts diff --git a/javascript/ql/test/library-tests/PathResolution/Fallback/src/main.ts b/javascript/ql/test/library-tests/PathResolution/Fallback/src/main.ts index 1b0bdb14e99b..aad239811b53 100644 --- a/javascript/ql/test/library-tests/PathResolution/Fallback/src/main.ts +++ b/javascript/ql/test/library-tests/PathResolution/Fallback/src/main.ts @@ -1,10 +1,10 @@ -import "@/both" // $ importTarget=Fallback/lib1/both.ts +import "@/both" // $ importTarget=Fallback/lib1/both.ts SPURIOUS: importTarget=Fallback/lib2/both.ts import "@/only1" // $ importTarget=Fallback/lib1/only1.ts import "@/only2" // $ importTarget=Fallback/lib2/only2.ts -import "@/differentExtension" // $ importTarget=Fallback/lib2/differentExtension.ts -import "@/differentExtension.js" // $ importTarget=Fallback/lib2/differentExtension.ts +import "@/differentExtension" // $ importTarget=Fallback/lib2/differentExtension.ts SPURIOUS: importTarget=Fallback/lib1/differentExtension.js +import "@/differentExtension.js" // $ importTarget=Fallback/lib2/differentExtension.ts SPURIOUS: importTarget=Fallback/lib1/differentExtension.js -import "@/subdir" // $ importTarget=Fallback/lib1/subdir/index.ts -import "@/subdir/both" // $ importTarget=Fallback/lib1/subdir/both.ts +import "@/subdir" // $ importTarget=Fallback/lib1/subdir/index.ts SPURIOUS: importTarget=Fallback/lib2/subdir/index.ts +import "@/subdir/both" // $ importTarget=Fallback/lib1/subdir/both.ts SPURIOUS: importTarget=Fallback/lib2/subdir/both.ts import "@/subdir/only1" // $ importTarget=Fallback/lib1/subdir/only1.ts import "@/subdir/only2" // $ importTarget=Fallback/lib2/subdir/only2.ts diff --git a/javascript/ql/test/library-tests/PathResolution/import-packages.ts b/javascript/ql/test/library-tests/PathResolution/import-packages.ts index 8f1ec41d9cba..6b7ca9014e4f 100644 --- a/javascript/ql/test/library-tests/PathResolution/import-packages.ts +++ b/javascript/ql/test/library-tests/PathResolution/import-packages.ts @@ -1,23 +1,23 @@ import './PackageWithMain/main'; // $ importTarget=PackageWithMain/main.js import '@example/package-with-main'; // $ importTarget=PackageWithMain/main.js -import './PackageWithModuleMain'; // $ MISSING: importTarget=PackageWithModuleMain/main.js +import './PackageWithModuleMain'; // $ importTarget=PackageWithModuleMain/main.js import '@example/package-with-module-main'; // $ importTarget=PackageWithModuleMain/main.js import './PackageWithExports'; // Not a valid import import './PackageWithExports/fake-file'; // Not a valid import import './PackageWithExports/star/foo'; // Not a valid import import '@example/package-with-exports'; // $ importTarget=PackageWithExports/main.js -import '@example/package-with-exports/fake-file'; // $ MISSING: importTarget=PackageWithExports/fake-file-impl.js -import '@example/package-with-exports/star/foo'; // $ MISSING: importTarget=PackageWithExports/star-impl/foo.js +import '@example/package-with-exports/fake-file'; // $ importTarget=PackageWithExports/fake-file-impl.js +import '@example/package-with-exports/star/foo'; // $ importTarget=PackageWithExports/star-impl/foo.js import './PackageIndexFile'; // $ importTarget=PackageIndexFile/index.js import '@example/package-with-index-file'; // $ importTarget=PackageIndexFile/index.js -import './PackageGuess1'; // $ MISSING: importTarget=PackageGuess1/src/index.ts +import './PackageGuess1'; // $ importTarget=PackageGuess1/src/index.ts import '@example/package-guess1'; // $ importTarget=PackageGuess1/src/index.ts -import './PackageGuess2'; // $ MISSING: importTarget=PackageGuess2/blah/stuff.ts +import './PackageGuess2'; // $ importTarget=PackageGuess2/blah/stuff.ts import '@example/package-guess2'; // $ importTarget=PackageGuess2/blah/stuff.ts import './PackageWithMainExt'; // $ importTarget=PackageWithMainExt/lib/main.ts @@ -25,11 +25,11 @@ import '@example/package-with-main-ext'; // $ importTarget=PackageWithMainExt/li import './TSConfigOutDir/customOutDir/foo.js'; // $ importTarget=TSConfigOutDir/src/foo.ts -import './MainIsFolder'; // $ MISSING: importTarget=MainIsFolder/src/index.ts +import './MainIsFolder'; // $ importTarget=MainIsFolder/src/index.ts import '@example/main-is-folder'; // $ importTarget=MainIsFolder/src/index.ts -import './DistContainsSrc'; // $ MISSING: importTarget=DistContainsSrc/src/foo.ts +import './DistContainsSrc'; // $ importTarget=DistContainsSrc/src/foo.ts -import './MinifiedMain'; // $ MISSING: importTarget=MinifiedMain/src/library.ts +import './MinifiedMain'; // $ importTarget=MinifiedMain/src/library.ts import './RootDir/my-out/foo.js'; // $ importTarget=RootDir/my-root/foo.ts diff --git a/javascript/ql/test/library-tests/PathResolution/test.expected b/javascript/ql/test/library-tests/PathResolution/test.expected index cbabd2cc7bc7..492aa6efd44b 100644 --- a/javascript/ql/test/library-tests/PathResolution/test.expected +++ b/javascript/ql/test/library-tests/PathResolution/test.expected @@ -40,7 +40,6 @@ | DeclarationFiles/src/main.ts:5:1:5:27 | import ... cript"; | DeclarationFiles/lib/typescript.ts | | DeclarationFiles/src/main.ts:6:1:6:30 | import ... pt.js"; | DeclarationFiles/lib/typescript.ts | | DeclarationFiles/src/main.ts:7:1:7:32 | import ... .d.ts"; | DeclarationFiles/lib/typescript.d.ts | -| DeclarationFiles/src/main.ts:7:1:7:32 | import ... .d.ts"; | DeclarationFiles/lib/typescript.ts | | DirnameImports/main.js:4:1:4:33 | require ... et.js') | DirnameImports/target.js | | DirnameImports/main.js:5:1:5:40 | require ... et.js') | DirnameImports/nested/target.js | | DirnameImports/main.js:6:1:6:45 | require ... es.ts') | import-packages.ts | @@ -69,12 +68,17 @@ | Extended/src/main.ts:25:1:25:20 | import "@/index.ts"; | Extended/lib/index.ts | | Extended/src/main.ts:26:1:26:20 | import "@/index.js"; | Extended/lib/index.ts | | Fallback/src/main.ts:1:1:1:15 | import "@/both" | Fallback/lib1/both.ts | +| Fallback/src/main.ts:1:1:1:15 | import "@/both" | Fallback/lib2/both.ts | | Fallback/src/main.ts:2:1:2:16 | import "@/only1" | Fallback/lib1/only1.ts | | Fallback/src/main.ts:3:1:3:16 | import "@/only2" | Fallback/lib2/only2.ts | +| Fallback/src/main.ts:4:1:4:29 | import ... ension" | Fallback/lib1/differentExtension.js | | Fallback/src/main.ts:4:1:4:29 | import ... ension" | Fallback/lib2/differentExtension.ts | +| Fallback/src/main.ts:5:1:5:32 | import ... ion.js" | Fallback/lib1/differentExtension.js | | Fallback/src/main.ts:5:1:5:32 | import ... ion.js" | Fallback/lib2/differentExtension.ts | | Fallback/src/main.ts:7:1:7:17 | import "@/subdir" | Fallback/lib1/subdir/index.ts | +| Fallback/src/main.ts:7:1:7:17 | import "@/subdir" | Fallback/lib2/subdir/index.ts | | Fallback/src/main.ts:8:1:8:22 | import ... r/both" | Fallback/lib1/subdir/both.ts | +| Fallback/src/main.ts:8:1:8:22 | import ... r/both" | Fallback/lib2/subdir/both.ts | | Fallback/src/main.ts:9:1:9:23 | import ... /only1" | Fallback/lib1/subdir/only1.ts | | Fallback/src/main.ts:10:1:10:23 | import ... /only2" | Fallback/lib2/subdir/only2.ts | | JSDocProvide/main.js:1:1:1:43 | import ... r/baz'; | JSDocProvide/lib.js | @@ -98,14 +102,22 @@ | NodeModules/subfolder/src/main.ts:2:1:2:13 | import 'bar'; | NodeModules/subfolder/node_modules/bar/index.js | | import-packages.ts:1:1:1:32 | import ... /main'; | PackageWithMain/main.js | | import-packages.ts:2:1:2:36 | import ... -main'; | PackageWithMain/main.js | +| import-packages.ts:4:1:4:33 | import ... eMain'; | PackageWithModuleMain/main.js | | import-packages.ts:5:1:5:43 | import ... -main'; | PackageWithModuleMain/main.js | | import-packages.ts:10:1:10:39 | import ... ports'; | PackageWithExports/main.js | +| import-packages.ts:11:1:11:49 | import ... -file'; | PackageWithExports/fake-file-impl.js | +| import-packages.ts:12:1:12:48 | import ... r/foo'; | PackageWithExports/star-impl/foo.js | | import-packages.ts:14:1:14:28 | import ... xFile'; | PackageIndexFile/index.js | | import-packages.ts:15:1:15:42 | import ... -file'; | PackageIndexFile/index.js | +| import-packages.ts:17:1:17:25 | import ... uess1'; | PackageGuess1/src/index.ts | | import-packages.ts:18:1:18:33 | import ... uess1'; | PackageGuess1/src/index.ts | +| import-packages.ts:20:1:20:25 | import ... uess2'; | PackageGuess2/blah/stuff.ts | | import-packages.ts:21:1:21:33 | import ... uess2'; | PackageGuess2/blah/stuff.ts | | import-packages.ts:23:1:23:30 | import ... inExt'; | PackageWithMainExt/lib/main.ts | | import-packages.ts:24:1:24:40 | import ... n-ext'; | PackageWithMainExt/lib/main.ts | | import-packages.ts:26:1:26:46 | import ... oo.js'; | TSConfigOutDir/src/foo.ts | +| import-packages.ts:28:1:28:24 | import ... older'; | MainIsFolder/src/index.ts | | import-packages.ts:29:1:29:33 | import ... older'; | MainIsFolder/src/index.ts | +| import-packages.ts:31:1:31:27 | import ... nsSrc'; | DistContainsSrc/src/foo.ts | +| import-packages.ts:33:1:33:24 | import ... dMain'; | MinifiedMain/src/library.ts | | import-packages.ts:35:1:35:33 | import ... oo.js'; | RootDir/my-root/foo.ts | From e4420f63fb2966e3c058f8688e0748d5f4ed648f Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 28 Apr 2025 12:52:24 +0200 Subject: [PATCH 142/336] JS: Move babel-root-import test This moves the test for the babel `root-import` plugin into the new unit test for import resolution, so we only have one set of tests to maintain. The actual implementation is added in the next commit. --- .../BabelRootImport}/tst1/.babelrc.json | 0 .../BabelRootImport}/tst1/a.js | 0 .../PathResolution/BabelRootImport/tst1/index.js | 1 + .../PathResolution/BabelRootImport/tst1/nested/tst.js | 1 + .../PathResolution/BabelRootImport/tst2/index.js | 2 ++ .../BabelRootImport}/tst2/package.json | 0 .../BabelRootImport}/tst2/src/js/b.js | 0 .../BabelRootImport}/tst3/.babelrc.json | 0 .../PathResolution/BabelRootImport/tst3/index.js | 1 + .../BabelRootImport}/tst3/src/b.js | 0 .../PathResolution/BabelRootImport/tst4/index.js | 2 ++ .../BabelRootImport}/tst4/package.json | 0 .../BabelRootImport}/tst4/src/js/b.js | 0 .../frameworks/babel/root-import/Imports.expected | 9 --------- .../frameworks/babel/root-import/Imports.ql | 4 ---- .../frameworks/babel/root-import/tst1/index.js | 1 - .../frameworks/babel/root-import/tst1/nested/tst.js | 1 - .../frameworks/babel/root-import/tst2/index.js | 2 -- .../frameworks/babel/root-import/tst3/index.js | 1 - .../frameworks/babel/root-import/tst4/index.js | 2 -- 20 files changed, 7 insertions(+), 20 deletions(-) rename javascript/ql/test/library-tests/{frameworks/babel/root-import => PathResolution/BabelRootImport}/tst1/.babelrc.json (100%) rename javascript/ql/test/library-tests/{frameworks/babel/root-import => PathResolution/BabelRootImport}/tst1/a.js (100%) create mode 100644 javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/index.js create mode 100644 javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/nested/tst.js create mode 100644 javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst2/index.js rename javascript/ql/test/library-tests/{frameworks/babel/root-import => PathResolution/BabelRootImport}/tst2/package.json (100%) rename javascript/ql/test/library-tests/{frameworks/babel/root-import => PathResolution/BabelRootImport}/tst2/src/js/b.js (100%) rename javascript/ql/test/library-tests/{frameworks/babel/root-import => PathResolution/BabelRootImport}/tst3/.babelrc.json (100%) create mode 100644 javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst3/index.js rename javascript/ql/test/library-tests/{frameworks/babel/root-import => PathResolution/BabelRootImport}/tst3/src/b.js (100%) create mode 100644 javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst4/index.js rename javascript/ql/test/library-tests/{frameworks/babel/root-import => PathResolution/BabelRootImport}/tst4/package.json (100%) rename javascript/ql/test/library-tests/{frameworks/babel/root-import => PathResolution/BabelRootImport}/tst4/src/js/b.js (100%) delete mode 100644 javascript/ql/test/library-tests/frameworks/babel/root-import/Imports.expected delete mode 100644 javascript/ql/test/library-tests/frameworks/babel/root-import/Imports.ql delete mode 100644 javascript/ql/test/library-tests/frameworks/babel/root-import/tst1/index.js delete mode 100644 javascript/ql/test/library-tests/frameworks/babel/root-import/tst1/nested/tst.js delete mode 100644 javascript/ql/test/library-tests/frameworks/babel/root-import/tst2/index.js delete mode 100644 javascript/ql/test/library-tests/frameworks/babel/root-import/tst3/index.js delete mode 100644 javascript/ql/test/library-tests/frameworks/babel/root-import/tst4/index.js diff --git a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst1/.babelrc.json b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/.babelrc.json similarity index 100% rename from javascript/ql/test/library-tests/frameworks/babel/root-import/tst1/.babelrc.json rename to javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/.babelrc.json diff --git a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst1/a.js b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/a.js similarity index 100% rename from javascript/ql/test/library-tests/frameworks/babel/root-import/tst1/a.js rename to javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/a.js diff --git a/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/index.js b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/index.js new file mode 100644 index 000000000000..78238f8a22c8 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/index.js @@ -0,0 +1 @@ +import f from '~/a'; // $ MISSING: importTarget=BabelRootImport/tst1/a.js diff --git a/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/nested/tst.js b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/nested/tst.js new file mode 100644 index 000000000000..78238f8a22c8 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/nested/tst.js @@ -0,0 +1 @@ +import f from '~/a'; // $ MISSING: importTarget=BabelRootImport/tst1/a.js diff --git a/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst2/index.js b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst2/index.js new file mode 100644 index 000000000000..bb9ac8e56313 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst2/index.js @@ -0,0 +1,2 @@ +import g from '~/b.js'; // $ MISSING: importTarget=BabelRootImport/tst2/src/js/b.js +import f from '#/a'; // $ MISSING: importTarget=BabelRootImport/tst1/a.js diff --git a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst2/package.json b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst2/package.json similarity index 100% rename from javascript/ql/test/library-tests/frameworks/babel/root-import/tst2/package.json rename to javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst2/package.json diff --git a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst2/src/js/b.js b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst2/src/js/b.js similarity index 100% rename from javascript/ql/test/library-tests/frameworks/babel/root-import/tst2/src/js/b.js rename to javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst2/src/js/b.js diff --git a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst3/.babelrc.json b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst3/.babelrc.json similarity index 100% rename from javascript/ql/test/library-tests/frameworks/babel/root-import/tst3/.babelrc.json rename to javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst3/.babelrc.json diff --git a/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst3/index.js b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst3/index.js new file mode 100644 index 000000000000..f7297a51022d --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst3/index.js @@ -0,0 +1 @@ +import greeting from '~/b.js'; // $ MISSING: importTarget=BabelRootImport/tst3/src/b.js diff --git a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst3/src/b.js b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst3/src/b.js similarity index 100% rename from javascript/ql/test/library-tests/frameworks/babel/root-import/tst3/src/b.js rename to javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst3/src/b.js diff --git a/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst4/index.js b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst4/index.js new file mode 100644 index 000000000000..fc3e863f6d10 --- /dev/null +++ b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst4/index.js @@ -0,0 +1,2 @@ +import g from '~/b.js'; // $ MISSING: importTarget=BabelRootImport/tst4/src/js/b.js +import f from '#/a'; // $ MISSING: importTarget=BabelRootImport/tst1/a.js diff --git a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst4/package.json b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst4/package.json similarity index 100% rename from javascript/ql/test/library-tests/frameworks/babel/root-import/tst4/package.json rename to javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst4/package.json diff --git a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst4/src/js/b.js b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst4/src/js/b.js similarity index 100% rename from javascript/ql/test/library-tests/frameworks/babel/root-import/tst4/src/js/b.js rename to javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst4/src/js/b.js diff --git a/javascript/ql/test/library-tests/frameworks/babel/root-import/Imports.expected b/javascript/ql/test/library-tests/frameworks/babel/root-import/Imports.expected deleted file mode 100644 index ee3f8cd7aaf5..000000000000 --- a/javascript/ql/test/library-tests/frameworks/babel/root-import/Imports.expected +++ /dev/null @@ -1,9 +0,0 @@ -| tst1/index.js:1:1:1:20 | import f from '~/a'; | tst1/a.js:1:1:2:0 | | -| tst1/nested/tst.js:1:1:1:20 | import f from '~/a'; | tst1/a.js:1:1:2:0 | | -| tst2/index.js:1:1:1:23 | import ... /b.js'; | tst2/src/js/b.js:1:1:2:0 | | -| tst2/index.js:2:1:2:20 | import f from '#/a'; | tst1/a.js:1:1:2:0 | | -| tst2/index.js:2:1:2:20 | import f from '#/a'; | tst1/index.js:1:1:2:0 | | -| tst3/index.js:1:1:1:30 | import ... /b.js'; | tst3/src/b.js:1:1:2:0 | | -| tst4/index.js:1:1:1:23 | import ... /b.js'; | tst4/src/js/b.js:1:1:2:0 | | -| tst4/index.js:2:1:2:20 | import f from '#/a'; | tst1/a.js:1:1:2:0 | | -| tst4/index.js:2:1:2:20 | import f from '#/a'; | tst1/index.js:1:1:2:0 | | diff --git a/javascript/ql/test/library-tests/frameworks/babel/root-import/Imports.ql b/javascript/ql/test/library-tests/frameworks/babel/root-import/Imports.ql deleted file mode 100644 index 343775bedc03..000000000000 --- a/javascript/ql/test/library-tests/frameworks/babel/root-import/Imports.ql +++ /dev/null @@ -1,4 +0,0 @@ -import javascript - -from Import i -select i, i.getImportedModule() diff --git a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst1/index.js b/javascript/ql/test/library-tests/frameworks/babel/root-import/tst1/index.js deleted file mode 100644 index cd74a094e539..000000000000 --- a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst1/index.js +++ /dev/null @@ -1 +0,0 @@ -import f from '~/a'; diff --git a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst1/nested/tst.js b/javascript/ql/test/library-tests/frameworks/babel/root-import/tst1/nested/tst.js deleted file mode 100644 index cd74a094e539..000000000000 --- a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst1/nested/tst.js +++ /dev/null @@ -1 +0,0 @@ -import f from '~/a'; diff --git a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst2/index.js b/javascript/ql/test/library-tests/frameworks/babel/root-import/tst2/index.js deleted file mode 100644 index 1253ec4afd8b..000000000000 --- a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst2/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import g from '~/b.js'; -import f from '#/a'; diff --git a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst3/index.js b/javascript/ql/test/library-tests/frameworks/babel/root-import/tst3/index.js deleted file mode 100644 index ef05072a9a6b..000000000000 --- a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst3/index.js +++ /dev/null @@ -1 +0,0 @@ -import greeting from '~/b.js'; diff --git a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst4/index.js b/javascript/ql/test/library-tests/frameworks/babel/root-import/tst4/index.js deleted file mode 100644 index 1253ec4afd8b..000000000000 --- a/javascript/ql/test/library-tests/frameworks/babel/root-import/tst4/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import g from '~/b.js'; -import f from '#/a'; From d72487496983cb8b25ef606ab7cad71212f5687a Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 28 Apr 2025 13:35:23 +0200 Subject: [PATCH 143/336] JS: Implement babel-plugin-root-import as a PathMapping --- javascript/ql/lib/semmle/javascript/frameworks/Babel.qll | 9 +++++++++ .../PathResolution/BabelRootImport/tst1/index.js | 2 +- .../PathResolution/BabelRootImport/tst1/nested/tst.js | 2 +- .../PathResolution/BabelRootImport/tst2/index.js | 4 ++-- .../PathResolution/BabelRootImport/tst3/index.js | 2 +- .../PathResolution/BabelRootImport/tst4/index.js | 4 ++-- .../ql/test/library-tests/PathResolution/test.expected | 7 +++++++ 7 files changed, 23 insertions(+), 7 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll index 240e75627cf6..52315013d17f 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll @@ -3,6 +3,7 @@ */ import javascript +private import semmle.javascript.internal.paths.PathMapping module Babel { /** @@ -202,4 +203,12 @@ module Babel { ) } } + + private class BabelPathMapping extends PathMapping, RootImportConfig { + override File getAnAffectedFile() { result = this.getConfig().getAContainerInScope() } + + override predicate hasPrefixPathMapping(string pattern, Container newContext, string newPath) { + newPath = this.getRoot(pattern) and newContext = this.getFolder() + } + } } diff --git a/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/index.js b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/index.js index 78238f8a22c8..210dcc7893f6 100644 --- a/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/index.js +++ b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/index.js @@ -1 +1 @@ -import f from '~/a'; // $ MISSING: importTarget=BabelRootImport/tst1/a.js +import f from '~/a'; // $ importTarget=BabelRootImport/tst1/a.js diff --git a/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/nested/tst.js b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/nested/tst.js index 78238f8a22c8..210dcc7893f6 100644 --- a/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/nested/tst.js +++ b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst1/nested/tst.js @@ -1 +1 @@ -import f from '~/a'; // $ MISSING: importTarget=BabelRootImport/tst1/a.js +import f from '~/a'; // $ importTarget=BabelRootImport/tst1/a.js diff --git a/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst2/index.js b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst2/index.js index bb9ac8e56313..2c75396d24ea 100644 --- a/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst2/index.js +++ b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst2/index.js @@ -1,2 +1,2 @@ -import g from '~/b.js'; // $ MISSING: importTarget=BabelRootImport/tst2/src/js/b.js -import f from '#/a'; // $ MISSING: importTarget=BabelRootImport/tst1/a.js +import g from '~/b.js'; // $ importTarget=BabelRootImport/tst2/src/js/b.js +import f from '#/a'; // $ importTarget=BabelRootImport/tst1/a.js diff --git a/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst3/index.js b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst3/index.js index f7297a51022d..a4256149187a 100644 --- a/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst3/index.js +++ b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst3/index.js @@ -1 +1 @@ -import greeting from '~/b.js'; // $ MISSING: importTarget=BabelRootImport/tst3/src/b.js +import greeting from '~/b.js'; // $ importTarget=BabelRootImport/tst3/src/b.js diff --git a/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst4/index.js b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst4/index.js index fc3e863f6d10..7208e926bd9a 100644 --- a/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst4/index.js +++ b/javascript/ql/test/library-tests/PathResolution/BabelRootImport/tst4/index.js @@ -1,2 +1,2 @@ -import g from '~/b.js'; // $ MISSING: importTarget=BabelRootImport/tst4/src/js/b.js -import f from '#/a'; // $ MISSING: importTarget=BabelRootImport/tst1/a.js +import g from '~/b.js'; // $ importTarget=BabelRootImport/tst4/src/js/b.js +import f from '#/a'; // $ importTarget=BabelRootImport/tst1/a.js diff --git a/javascript/ql/test/library-tests/PathResolution/test.expected b/javascript/ql/test/library-tests/PathResolution/test.expected index 492aa6efd44b..fb546892af12 100644 --- a/javascript/ql/test/library-tests/PathResolution/test.expected +++ b/javascript/ql/test/library-tests/PathResolution/test.expected @@ -1,3 +1,10 @@ +| BabelRootImport/tst1/index.js:1:1:1:20 | import f from '~/a'; | BabelRootImport/tst1/a.js | +| BabelRootImport/tst1/nested/tst.js:1:1:1:20 | import f from '~/a'; | BabelRootImport/tst1/a.js | +| BabelRootImport/tst2/index.js:1:1:1:23 | import ... /b.js'; | BabelRootImport/tst2/src/js/b.js | +| BabelRootImport/tst2/index.js:2:1:2:20 | import f from '#/a'; | BabelRootImport/tst1/a.js | +| BabelRootImport/tst3/index.js:1:1:1:30 | import ... /b.js'; | BabelRootImport/tst3/src/b.js | +| BabelRootImport/tst4/index.js:1:1:1:23 | import ... /b.js'; | BabelRootImport/tst4/src/js/b.js | +| BabelRootImport/tst4/index.js:2:1:2:20 | import f from '#/a'; | BabelRootImport/tst1/a.js | | BaseUrl/src/main.ts:2:1:2:26 | import ... /file"; | BaseUrl/base/lib/file.ts | | BaseUrl/src/main.ts:3:1:3:29 | import ... le.ts"; | BaseUrl/base/lib/file.ts | | BaseUrl/src/main.ts:4:1:4:29 | import ... le.js"; | BaseUrl/base/lib/file.ts | From a195d074c934d466614b7e0a0551c09cdb0078cf Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 28 Apr 2025 12:54:35 +0200 Subject: [PATCH 144/336] JS: Resolve Angular2 templateUrl with ResolveExpr instead of PathExpr --- .../semmle/javascript/frameworks/Angular2.qll | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll index 3441b5d9c006..9fd24c81a4a4 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll @@ -9,6 +9,7 @@ private import semmle.javascript.security.dataflow.ClientSideUrlRedirectCustomiz private import semmle.javascript.DynamicPropertyAccess private import semmle.javascript.dataflow.internal.PreCallGraphStep private import semmle.javascript.ViewComponentInput +private import semmle.javascript.internal.paths.PathExprResolver /** * Provides classes for working with Angular (also known as Angular 2.x) applications. @@ -240,18 +241,15 @@ module Angular2 { class TemplateTopLevel = Templating::TemplateTopLevel; - /** The RHS of a `templateUrl` property, seen as a path expression. */ - private class TemplateUrlPath extends PathExpr { - TemplateUrlPath() { - exists(Property prop | - prop.getName() = "templateUrl" and - this = prop.getInit() - ) - } - - override string getValue() { result = this.(Expr).getStringValue() } + private predicate shouldResolveExpr(Expr e) { + exists(Property prop | + prop.getName() = "templateUrl" and + e = prop.getInit() + ) } + private module Resolver = ResolveExpr; + /** * Holds if the value of `attrib` is interpreted as an Angular expression. */ @@ -338,7 +336,7 @@ module Angular2 { */ pragma[noinline] File getTemplateFile() { - result = decorator.getOptionArgument(0, "templateUrl").asExpr().(PathExpr).resolve() + result = Resolver::resolveExpr(decorator.getOptionArgument(0, "templateUrl").asExpr()) } /** Gets an element in the HTML template of this component. */ From c293f03b9e09c7cb303c8c3ddb04a080a05922d3 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 28 Apr 2025 13:41:01 +0200 Subject: [PATCH 145/336] JS: Remove a dependency on getImportedPath() To avoid negative recursion in some upcoming changes, we want to make sure the modeling of createRequire does not depend on getImportedPath(). --- javascript/ql/lib/semmle/javascript/ES2015Modules.qll | 5 +++++ javascript/ql/lib/semmle/javascript/NodeJS.qll | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll index 378094e7c982..488c69099842 100644 --- a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll +++ b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll @@ -94,6 +94,11 @@ class ImportDeclaration extends Stmt, Import, @import_declaration { override PathExpr getImportedPath() { result = this.getChildExpr(-1) } + /** + * INTERNAL USE ONLY. DO NOT USE. + */ + string getRawImportPath() { result = this.getChildExpr(-1).getStringValue() } + /** * Gets the object literal passed as part of the `with` (or `assert`) clause in this import declaration. * diff --git a/javascript/ql/lib/semmle/javascript/NodeJS.qll b/javascript/ql/lib/semmle/javascript/NodeJS.qll index cd00e06e7226..1be6ad9902f6 100644 --- a/javascript/ql/lib/semmle/javascript/NodeJS.qll +++ b/javascript/ql/lib/semmle/javascript/NodeJS.qll @@ -242,7 +242,7 @@ private class RequireVariable extends Variable { private predicate moduleInFile(Module m, File f) { m.getFile() = f } private predicate isModuleModule(EarlyStageNode nd) { - exists(ImportDeclaration imp | imp.getImportedPath().getValue() = "module" | + exists(ImportDeclaration imp | imp.getRawImportPath() = "module" | nd = TDestructuredModuleImportNode(imp) or nd = TValueNode(imp.getASpecifier().(ImportNamespaceSpecifier)) @@ -268,7 +268,7 @@ private predicate isCreateRequire(EarlyStageNode nd) { ) or exists(ImportDeclaration decl, NamedImportSpecifier spec | - decl.getImportedPath().getValue() = "module" and + decl.getRawImportPath() = "module" and spec = decl.getASpecifier() and spec.getImportedName() = "createRequire" and nd = TValueNode(spec) From fe055ad6039f371fe5a2c6e54b096a2bab3085bd Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 28 Apr 2025 13:42:24 +0200 Subject: [PATCH 146/336] JS: Use PackageJsonEx instead of resolveMainModule --- .../ql/lib/semmle/javascript/PackageExports.qll | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/PackageExports.qll b/javascript/ql/lib/semmle/javascript/PackageExports.qll index ace840613e1c..b4032980688f 100644 --- a/javascript/ql/lib/semmle/javascript/PackageExports.qll +++ b/javascript/ql/lib/semmle/javascript/PackageExports.qll @@ -6,6 +6,7 @@ import javascript private import semmle.javascript.internal.CachedStages +private import semmle.javascript.internal.paths.PackageJsonEx /** * Gets a parameter that is a library input to a top-level package. @@ -126,19 +127,12 @@ private DataFlow::Node getAValueExportedByPackage() { // .... // })); // ``` - // Such files are not recognized as modules, so we manually use `NodeModule::resolveMainModule` to resolve the file against a `package.json` file. + // Such files are not recognized as modules, so we manually use `PackageJsonEx` to resolve the file against a `package.json` file. exists(ImmediatelyInvokedFunctionExpr func, DataFlow::ParameterNode factory, int i | factory.getName() = "factory" and func.getParameter(i) = factory.getParameter() and DataFlow::globalVarRef("define").getACall().getAnArgument() = factory.getALocalUse() and - func.getFile() = - min(int j, File f | - f = - NodeModule::resolveMainModule(any(PackageJson pack | exists(pack.getPackageName())), j, - ".") - | - f order by j - ) + func.getFile() = any(PackageJsonEx pack).getMainFileOrBestGuess() | result = func.getInvocation().getArgument(i).flow().getAFunctionValue().getAReturn() or From ed2a832a555f1001b15965de4e8b55b674a2eb6c Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Apr 2025 13:22:54 +0200 Subject: [PATCH 147/336] JS: Deprecate PathExpr and related classes --- javascript/ql/examples/snippets/importfrom.ql | 2 +- javascript/ql/lib/definitions.qll | 2 +- javascript/ql/lib/semmle/javascript/AMD.qll | 28 ++++++++++------ .../lib/semmle/javascript/ES2015Modules.qll | 8 ++--- javascript/ql/lib/semmle/javascript/Expr.qll | 4 +-- javascript/ql/lib/semmle/javascript/HTML.qll | 10 ++++-- .../ql/lib/semmle/javascript/Modules.qll | 16 +++++++--- .../ql/lib/semmle/javascript/NodeJS.qll | 32 ++++++------------- .../javascript/NodeModuleResolutionImpl.qll | 20 ++++++------ javascript/ql/lib/semmle/javascript/Paths.qll | 30 ++++++++--------- .../ql/lib/semmle/javascript/TypeScript.qll | 8 ++--- .../lib/semmle/javascript/dataflow/Nodes.qll | 2 +- .../internal/InterModuleTypeInference.qll | 4 +-- .../javascript/dependencies/Dependencies.qll | 7 +++- .../frameworks/AngularJS/AngularJSCore.qll | 2 +- .../semmle/javascript/frameworks/Babel.qll | 4 +-- .../javascript/frameworks/LazyCache.qll | 4 +-- .../semmle/javascript/frameworks/React.qll | 2 +- .../lib/semmle/javascript/frameworks/Vue.qll | 4 +-- .../data/internal/ApiGraphModelsSpecific.qll | 2 +- .../internal/paths/PathExprResolver.qll | 2 +- ...APIUsedWithUntrustedDataCustomizations.qll | 2 +- .../src/Declarations/UnstableCyclicImport.ql | 2 +- .../ql/src/NodeJS/UnresolvableImport.ql | 2 +- javascript/ql/src/NodeJS/UnusedDependency.ql | 17 +++++++--- javascript/ql/test/library-tests/AMD/tests.ql | 4 +-- .../ql/test/library-tests/Modules/tests.ql | 4 +-- .../ql/test/library-tests/NodeJS/tests.ql | 2 +- .../TypeScript/ImportEquals/tests.ql | 2 +- .../RegressionTests/ImportDtsFile/test.ql | 2 +- 30 files changed, 126 insertions(+), 104 deletions(-) diff --git a/javascript/ql/examples/snippets/importfrom.ql b/javascript/ql/examples/snippets/importfrom.ql index d466136ca2f2..a2efb17e169f 100644 --- a/javascript/ql/examples/snippets/importfrom.ql +++ b/javascript/ql/examples/snippets/importfrom.ql @@ -11,5 +11,5 @@ import javascript from ImportDeclaration id -where id.getImportedPath().getValue() = "react" +where id.getImportedPathString() = "react" select id diff --git a/javascript/ql/lib/definitions.qll b/javascript/ql/lib/definitions.qll index 7b4806b14786..2cc9313d3132 100644 --- a/javascript/ql/lib/definitions.qll +++ b/javascript/ql/lib/definitions.qll @@ -70,7 +70,7 @@ private predicate importLookup(AstNode path, Module target, string kind) { kind = "I" and ( exists(Import i | - path = i.getImportedPath() and + path = i.getImportedPathExpr() and target = i.getImportedModule() ) or diff --git a/javascript/ql/lib/semmle/javascript/AMD.qll b/javascript/ql/lib/semmle/javascript/AMD.qll index 3239dba9026d..4828aff27cc4 100644 --- a/javascript/ql/lib/semmle/javascript/AMD.qll +++ b/javascript/ql/lib/semmle/javascript/AMD.qll @@ -61,8 +61,14 @@ class AmdModuleDefinition extends CallExpr instanceof AmdModuleDefinition::Range result = this.getArgument(1) } + /** DEPRECATED. Use `getDependencyExpr` instead. */ + deprecated PathExpr getDependency(int i) { result = this.getDependencyExpr(i) } + + /** DEPRECATED. Use `getADependencyExpr` instead. */ + deprecated PathExpr getADependency() { result = this.getADependencyExpr() } + /** Gets the `i`th dependency of this module definition. */ - PathExpr getDependency(int i) { + Expr getDependencyExpr(int i) { exists(Expr expr | expr = this.getDependencies().getElement(i) and not isPseudoDependency(expr.getStringValue()) and @@ -71,8 +77,8 @@ class AmdModuleDefinition extends CallExpr instanceof AmdModuleDefinition::Range } /** Gets a dependency of this module definition. */ - PathExpr getADependency() { - result = this.getDependency(_) or + Expr getADependencyExpr() { + result = this.getDependencyExpr(_) or result = this.getARequireCall().getAnArgument() } @@ -233,7 +239,7 @@ private class AmdDependencyPath extends PathExprCandidate { } /** A constant path element appearing in an AMD dependency expression. */ -private class ConstantAmdDependencyPathElement extends PathExpr, ConstantString { +deprecated private class ConstantAmdDependencyPathElement extends PathExpr, ConstantString { ConstantAmdDependencyPathElement() { this = any(AmdDependencyPath amd).getAPart() } override string getValue() { result = this.getStringValue() } @@ -261,11 +267,13 @@ private predicate amdModuleTopLevel(AmdModuleDefinition def, TopLevel tl) { * An AMD dependency, viewed as an import. */ private class AmdDependencyImport extends Import { - AmdDependencyImport() { this = any(AmdModuleDefinition def).getADependency() } + AmdDependencyImport() { this = any(AmdModuleDefinition def).getADependencyExpr() } - override Module getEnclosingModule() { this = result.(AmdModule).getDefine().getADependency() } + override Module getEnclosingModule() { + this = result.(AmdModule).getDefine().getADependencyExpr() + } - override PathExpr getImportedPath() { result = this } + override Expr getImportedPathExpr() { result = this } /** * Gets a file that looks like it might be the target of this import. @@ -274,7 +282,7 @@ private class AmdDependencyImport extends Import { * adding well-known JavaScript file extensions like `.js`. */ private File guessTarget() { - exists(PathString imported, string abspath, string dirname, string basename | + exists(FilePath imported, string abspath, string dirname, string basename | this.targetCandidate(result, abspath, imported, dirname, basename) | abspath.regexpMatch(".*/\\Q" + imported + "\\E") @@ -296,9 +304,9 @@ private class AmdDependencyImport extends Import { * `dirname` and `basename` to the dirname and basename (respectively) of `imported`. */ private predicate targetCandidate( - File f, string abspath, PathString imported, string dirname, string basename + File f, string abspath, FilePath imported, string dirname, string basename ) { - imported = this.getImportedPath().getValue() and + imported = this.getImportedPathString() and f.getStem() = imported.getStem() and f.getAbsolutePath() = abspath and dirname = imported.getDirName() and diff --git a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll index 488c69099842..379403eb0ee7 100644 --- a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll +++ b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll @@ -92,13 +92,13 @@ private predicate hasDefaultExport(ES2015Module mod) { class ImportDeclaration extends Stmt, Import, @import_declaration { override ES2015Module getEnclosingModule() { result = this.getTopLevel() } - override PathExpr getImportedPath() { result = this.getChildExpr(-1) } - /** * INTERNAL USE ONLY. DO NOT USE. */ string getRawImportPath() { result = this.getChildExpr(-1).getStringValue() } + override Expr getImportedPathExpr() { result = this.getChildExpr(-1) } + /** * Gets the object literal passed as part of the `with` (or `assert`) clause in this import declaration. * @@ -155,7 +155,7 @@ class ImportDeclaration extends Stmt, Import, @import_declaration { } /** A literal path expression appearing in an `import` declaration. */ -private class LiteralImportPath extends PathExpr, ConstantString { +deprecated private class LiteralImportPath extends PathExpr, ConstantString { LiteralImportPath() { exists(ImportDeclaration req | this = req.getChildExpr(-1)) } override string getValue() { result = this.getStringValue() } @@ -736,7 +736,7 @@ abstract class ReExportDeclaration extends ExportDeclaration { } /** A literal path expression appearing in a re-export declaration. */ -private class LiteralReExportPath extends PathExpr, ConstantString { +deprecated private class LiteralReExportPath extends PathExpr, ConstantString { LiteralReExportPath() { exists(ReExportDeclaration bred | this = bred.getImportedPath()) } override string getValue() { result = this.getStringValue() } diff --git a/javascript/ql/lib/semmle/javascript/Expr.qll b/javascript/ql/lib/semmle/javascript/Expr.qll index e8ec55f0174d..8695c893f815 100644 --- a/javascript/ql/lib/semmle/javascript/Expr.qll +++ b/javascript/ql/lib/semmle/javascript/Expr.qll @@ -2821,7 +2821,7 @@ class DynamicImportExpr extends @dynamic_import, Expr, Import { result = this.getSource().getFirstControlFlowNode() } - override PathExpr getImportedPath() { result = this.getSource() } + override Expr getImportedPathExpr() { result = this.getSource() } /** * Gets the second "argument" to the import expression, that is, the `Y` in `import(X, Y)`. @@ -2852,7 +2852,7 @@ class DynamicImportExpr extends @dynamic_import, Expr, Import { } /** A literal path expression appearing in a dynamic import. */ -private class LiteralDynamicImportPath extends PathExpr, ConstantString { +deprecated private class LiteralDynamicImportPath extends PathExpr, ConstantString { LiteralDynamicImportPath() { exists(DynamicImportExpr di | this.getParentExpr*() = di.getSource()) } diff --git a/javascript/ql/lib/semmle/javascript/HTML.qll b/javascript/ql/lib/semmle/javascript/HTML.qll index 01ce54cef529..43b66db459ff 100644 --- a/javascript/ql/lib/semmle/javascript/HTML.qll +++ b/javascript/ql/lib/semmle/javascript/HTML.qll @@ -214,7 +214,7 @@ module HTML { result = path.regexpCapture("file://(/.*)", 1) or not path.regexpMatch("(\\w+:)?//.*") and - result = this.getSourcePath().(ScriptSrcPath).resolve(this.getSearchRoot()).toString() + result = ResolveScriptSrc::resolve(this.getSearchRoot(), this.getSourcePath()).toString() ) } @@ -274,10 +274,16 @@ module HTML { ) } + private module ResolverConfig implements Folder::ResolveSig { + predicate shouldResolve(Container base, string path) { scriptSrc(path, base) } + } + + private module ResolveScriptSrc = Folder::Resolve; + /** * A path string arising from the `src` attribute of a `script` tag. */ - private class ScriptSrcPath extends PathString { + deprecated private class ScriptSrcPath extends PathString { ScriptSrcPath() { scriptSrc(this, _) } override Folder getARootFolder() { scriptSrc(this, result) } diff --git a/javascript/ql/lib/semmle/javascript/Modules.qll b/javascript/ql/lib/semmle/javascript/Modules.qll index 6dc27f980b8f..1949abe4cdcb 100644 --- a/javascript/ql/lib/semmle/javascript/Modules.qll +++ b/javascript/ql/lib/semmle/javascript/Modules.qll @@ -69,7 +69,7 @@ abstract class Module extends TopLevel { * This predicate is not part of the public API, it is only exposed to allow * overriding by subclasses. */ - predicate searchRoot(PathExpr path, Folder searchRoot, int priority) { + deprecated predicate searchRoot(PathExpr path, Folder searchRoot, int priority) { path.getEnclosingModule() = this and priority = 0 and exists(string v | v = path.getValue() | @@ -90,7 +90,7 @@ abstract class Module extends TopLevel { * resolves to a folder containing a main module (such as `index.js`), then * that file is the result. */ - File resolve(PathExpr path) { + deprecated File resolve(PathExpr path) { path.getEnclosingModule() = this and ( // handle the case where the import path is complete @@ -123,8 +123,14 @@ abstract class Import extends AstNode { /** Gets the module in which this import appears. */ abstract Module getEnclosingModule(); + /** DEPRECATED. Use `getImportedPathExpr` instead. */ + deprecated PathExpr getImportedPath() { result = this.getImportedPathExpr() } + /** Gets the (unresolved) path that this import refers to. */ - abstract PathExpr getImportedPath(); + abstract Expr getImportedPathExpr(); + + /** Gets the imported path as a string. */ + final string getImportedPathString() { result = this.getImportedPathExpr().getStringValue() } /** * Gets an externs module the path of this import resolves to. @@ -133,7 +139,7 @@ abstract class Import extends AstNode { * path is assumed to be a possible target of the import. */ Module resolveExternsImport() { - result.isExterns() and result.getName() = this.getImportedPath().getValue() + result.isExterns() and result.getName() = this.getImportedPathString() } /** @@ -144,7 +150,7 @@ abstract class Import extends AstNode { /** * Gets the module the path of this import resolves to. */ - File getTargetFile() { result = ImportPathResolver::resolveExpr(this.getImportedPath()) } + File getTargetFile() { result = ImportPathResolver::resolveExpr(this.getImportedPathExpr()) } /** * DEPRECATED. Use `getImportedModule()` instead. diff --git a/javascript/ql/lib/semmle/javascript/NodeJS.qll b/javascript/ql/lib/semmle/javascript/NodeJS.qll index 1be6ad9902f6..175991ffa5eb 100644 --- a/javascript/ql/lib/semmle/javascript/NodeJS.qll +++ b/javascript/ql/lib/semmle/javascript/NodeJS.qll @@ -146,7 +146,7 @@ class NodeModule extends Module { ) } - override predicate searchRoot(PathExpr path, Folder searchRoot, int priority) { + deprecated override predicate searchRoot(PathExpr path, Folder searchRoot, int priority) { path.getEnclosingModule() = this and exists(string pathval | pathval = path.getValue() | // paths starting with `./` or `../` are resolved relative to the importing @@ -236,11 +236,6 @@ private class RequireVariable extends Variable { } } -/** - * Holds if module `m` is in file `f`. - */ -private predicate moduleInFile(Module m, File f) { m.getFile() = f } - private predicate isModuleModule(EarlyStageNode nd) { exists(ImportDeclaration imp | imp.getRawImportPath() = "module" | nd = TDestructuredModuleImportNode(imp) @@ -328,24 +323,17 @@ private predicate isRequire(EarlyStageNode nd) { class Require extends CallExpr, Import { Require() { isRequire(TValueNode(this.getCallee())) } - override PathExpr getImportedPath() { result = this.getArgument(0) } + override Expr getImportedPathExpr() { result = this.getArgument(0) } override Module getEnclosingModule() { this = result.getAnImport() } - override Module resolveImportedPath() { - moduleInFile(result, this.load(min(int prio | moduleInFile(_, this.load(prio))))) - or - not moduleInFile(_, this.load(_)) and - result = Import.super.resolveImportedPath() - } - /** * Gets the file that is imported by this `require`. * * The result can be a JavaScript file, a JSON file or a `.node` file. * Externs files are not treated differently from other files by this predicate. */ - File getImportedFile() { result = this.load(min(int prio | exists(this.load(prio)))) } + deprecated File getImportedFile() { result = this.load(min(int prio | exists(this.load(prio)))) } /** * Gets the file that this `require` refers to (which may not be a JavaScript file), @@ -402,8 +390,8 @@ class Require extends CallExpr, Import { * predicate `tryExtensions` that handles the repeated distinction between * `.js`, `.json` and `.node`. */ - private File load(int priority) { - exists(int r | this.getEnclosingModule().searchRoot(this.getImportedPath(), _, r) | + deprecated private File load(int priority) { + exists(int r | this.getEnclosingModule().searchRoot(this.getImportedPathExpr(), _, r) | result = loadAsFile(this, r, priority - prioritiesPerCandidate() * r) or result = loadAsDirectory(this, r, @@ -415,7 +403,7 @@ class Require extends CallExpr, Import { } /** An argument to `require` or `require.resolve`, considered as a path expression. */ -private class RequirePath extends PathExprCandidate { +deprecated private class RequirePath extends PathExprCandidate { RequirePath() { this = any(Require req).getArgument(0) or @@ -428,14 +416,14 @@ private class RequirePath extends PathExprCandidate { } /** A constant path element appearing in a call to `require` or `require.resolve`. */ -private class ConstantRequirePathElement extends PathExpr, ConstantString { +deprecated private class ConstantRequirePathElement extends PathExpr, ConstantString { ConstantRequirePathElement() { this = any(RequirePath rp).getAPart() } override string getValue() { result = this.getStringValue() } } /** A `__dirname` path expression. */ -private class DirNamePath extends PathExpr, VarAccess { +deprecated private class DirNamePath extends PathExpr, VarAccess { DirNamePath() { this.getName() = "__dirname" and this.getVariable().getScope() instanceof ModuleScope @@ -445,7 +433,7 @@ private class DirNamePath extends PathExpr, VarAccess { } /** A `__filename` path expression. */ -private class FileNamePath extends PathExpr, VarAccess { +deprecated private class FileNamePath extends PathExpr, VarAccess { FileNamePath() { this.getName() = "__filename" and this.getVariable().getScope() instanceof ModuleScope @@ -458,7 +446,7 @@ private class FileNamePath extends PathExpr, VarAccess { * A path expression of the form `path.join(p, "...")` where * `p` is also a path expression. */ -private class JoinedPath extends PathExpr, @call_expr { +deprecated private class JoinedPath extends PathExpr, @call_expr { JoinedPath() { exists(MethodCallExpr call | call = this | call.getReceiver().(VarAccess).getName() = "path" and diff --git a/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll b/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll index 03b5bf93fb06..467e14aa74fb 100644 --- a/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll +++ b/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll @@ -45,7 +45,7 @@ int numberOfExtensions() { result = count(getFileExtensionPriority(_)) } * Gets the resolution target with the given `priority` of `req` * when resolved from the root with priority `rootPriority`. */ -File loadAsFile(Require req, int rootPriority, int priority) { +deprecated File loadAsFile(Require req, int rootPriority, int priority) { exists(PathExpr path | path = req.getImportedPath() | result = path.resolve(rootPriority) and priority = 0 or @@ -60,7 +60,7 @@ File loadAsFile(Require req, int rootPriority, int priority) { * with the given `priority` of `req` when resolved from the root with * priority `rootPriority`. */ -File loadAsDirectory(Require req, int rootPriority, int priority) { +deprecated File loadAsDirectory(Require req, int rootPriority, int priority) { exists(Folder dir | dir = req.getImportedPath().resolve(rootPriority) | result = resolveMainModule(dir.(NpmPackage).getPackageJson(), priority, ".") or result = tryExtensions(dir, "index", priority - (numberOfExtensions() + 1)) @@ -99,7 +99,7 @@ private string getStem(string name) { * Gets a file that a main module from `pkg` exported as `mainPath` with the given `priority`. * `mainPath` is "." if it's the main module of the package. */ -private File resolveMainPath(PackageJson pkg, string mainPath, int priority) { +deprecated private File resolveMainPath(PackageJson pkg, string mainPath, int priority) { exists(PathExpr main | main = MainModulePath::of(pkg, mainPath) | result = main.resolve() and priority = 0 or @@ -132,7 +132,7 @@ private File resolveMainPath(PackageJson pkg, string mainPath, int priority) { /** * Gets the main module described by `pkg` with the given `priority`. */ -File resolveMainModule(PackageJson pkg, int priority, string exportPath) { +deprecated File resolveMainModule(PackageJson pkg, int priority, string exportPath) { result = resolveMainPath(pkg, exportPath, priority) or exportPath = "." and @@ -178,7 +178,7 @@ private string getASrcFolderName() { result = ["ts", "js", "src", "lib"] } * A JSON string in a `package.json` file specifying the path of one of the exported * modules of the package. */ -class MainModulePath extends PathExpr, @json_string { +deprecated class MainModulePath extends PathExpr, @json_string { PackageJson pkg; MainModulePath() { @@ -228,7 +228,7 @@ private string getExportRelativePath(JsonValue part) { result.matches(".%") } -module MainModulePath { +deprecated module MainModulePath { /** Gets the path to the main entry point of `pkg`. */ MainModulePath of(PackageJson pkg) { result = of(pkg, ".") } @@ -244,7 +244,7 @@ module MainModulePath { * These files are often imported directly from a client when a "main" module is not specified. * For performance reasons this only exists if there is no "main" field in the `package.json` file. */ -private class FilesPath extends PathExpr, @json_string { +deprecated private class FilesPath extends PathExpr, @json_string { PackageJson pkg; FilesPath() { @@ -263,7 +263,7 @@ private class FilesPath extends PathExpr, @json_string { } } -private module FilesPath { +deprecated private module FilesPath { FilesPath of(PackageJson pkg) { result.getPackageJson() = pkg } } @@ -271,7 +271,7 @@ private module FilesPath { * A JSON string in a `package.json` file specifying the path of the * TypeScript typings entry point. */ -class TypingsModulePathString extends PathString { +deprecated class TypingsModulePathString extends PathString { PackageJson pkg; TypingsModulePathString() { @@ -288,7 +288,7 @@ class TypingsModulePathString extends PathString { } /** Companion module to the `TypingsModulePathString` class. */ -module TypingsModulePathString { +deprecated module TypingsModulePathString { /** Get the typings path for the given `package.json` file. */ TypingsModulePathString of(PackageJson pkg) { result.getPackageJson() = pkg } } diff --git a/javascript/ql/lib/semmle/javascript/Paths.qll b/javascript/ql/lib/semmle/javascript/Paths.qll index 981e43f8966d..38c24a1b8e90 100644 --- a/javascript/ql/lib/semmle/javascript/Paths.qll +++ b/javascript/ql/lib/semmle/javascript/Paths.qll @@ -9,13 +9,13 @@ private import semmle.javascript.dataflow.internal.DataFlowNode /** * Internal representation of paths as lists of components. */ -private newtype TPath = +deprecated private newtype TPath = /** A root path. */ TRootPath(string root) { root = any(Folder f | not exists(f.getParentContainer())).getAbsolutePath() } or /** A path of the form `/`. */ - TConsPath(Path parent, string component) { + deprecated TConsPath(Path parent, string component) { // make sure we can represent paths of files in snapshot exists(Folder f | f = parent.getContainer() | exists(f.getChildContainer(component))) or @@ -32,7 +32,7 @@ private newtype TPath = * Gets a textual representation of path `p` using slashes as delimiters; * the empty path is represented as the empty string `""`. */ -private string pp(TPath p) { +deprecated private string pp(TPath p) { p = TRootPath(result + "/") or exists(TPath parent, string component | p = TConsPath(parent, component) | @@ -45,7 +45,7 @@ private string pp(TPath p) { * which may (but does not have to) correspond to a file or folder included * in the snapshot. */ -class Path extends TPath { +deprecated class Path extends TPath { /** * Gets the file or folder referred to by this path, if it exists. */ @@ -60,14 +60,14 @@ class Path extends TPath { /** * The empty path, which refers to the file system root. */ -private class RootPath extends Path, TRootPath { +deprecated private class RootPath extends Path, TRootPath { override string toString() { this = TRootPath(result) } } /** * A non-empty path of the form `/`. */ -private class ConsPath extends Path, TConsPath { +deprecated private class ConsPath extends Path, TConsPath { /** Gets the parent path of this path. */ Path getParent() { this = TConsPath(result, _) } @@ -170,7 +170,7 @@ class FilePath extends string { * usually resolved relative to the module's folder, with a default * lookup path as the fallback. */ -abstract class PathString extends FilePath { +abstract deprecated class PathString extends FilePath { bindingset[this] PathString() { any() } @@ -196,7 +196,7 @@ abstract class PathString extends FilePath { * components of this path refers to when resolved relative to the * given `root` folder. */ -private Path resolveUpTo(PathString p, int n, Folder root, boolean inTS) { +deprecated private Path resolveUpTo(PathString p, int n, Folder root, boolean inTS) { n = 0 and result.getContainer() = root and root = p.getARootFolder() and inTS = false or exists(Path base, string next | next = getComponent(p, n - 1, base, root, inTS) | @@ -225,7 +225,7 @@ private Path resolveUpTo(PathString p, int n, Folder root, boolean inTS) { * Supports that the root directory might be compiled output from TypeScript. * `inTS` is true if the result is TypeScript that is compiled into the path specified by `str`. */ -private string getComponent(PathString str, int n, Path base, Folder root, boolean inTS) { +deprecated private string getComponent(PathString str, int n, Path base, Folder root, boolean inTS) { exists(boolean prevTS | base = resolveUpTo(str, n, root, prevTS) and ( @@ -248,7 +248,7 @@ private string getComponent(PathString str, int n, Path base, Folder root, boole /** * Predicates for resolving imports to compiled TypeScript. */ -private module TypeScriptOutDir { +deprecated private module TypeScriptOutDir { /** * Gets a folder of TypeScript files that is compiled to JavaScript files in `outdir` relative to a `parent`. */ @@ -340,7 +340,7 @@ private module TypeScriptOutDir { * as their highest-priority root, with default library paths as additional roots * of lower priority. */ -abstract class PathExpr extends Locatable { +abstract deprecated class PathExpr extends Locatable { /** Gets the (unresolved) path represented by this expression. */ abstract string getValue(); @@ -413,7 +413,7 @@ abstract class PathExpr extends Locatable { } /** A path string derived from a path expression. */ -private class PathExprString extends PathString { +deprecated private class PathExprString extends PathString { PathExprString() { this = any(PathExpr pe).getValue() } override Folder getARootFolder() { @@ -422,13 +422,13 @@ private class PathExprString extends PathString { } pragma[nomagic] -private EarlyStageNode getAPathExprAlias(PathExpr expr) { +deprecated private EarlyStageNode getAPathExprAlias(PathExpr expr) { DataFlow::Impl::earlyStageImmediateFlowStep(TValueNode(expr), result) or DataFlow::Impl::earlyStageImmediateFlowStep(getAPathExprAlias(expr), result) } -private class PathExprFromAlias extends PathExpr { +deprecated private class PathExprFromAlias extends PathExpr { private PathExpr other; PathExprFromAlias() { TValueNode(this) = getAPathExprAlias(other) } @@ -444,7 +444,7 @@ private class PathExprFromAlias extends PathExpr { * A path expression of the form `p + q`, where both `p` and `q` * are path expressions. */ -private class ConcatPath extends PathExpr { +deprecated private class ConcatPath extends PathExpr { ConcatPath() { exists(AddExpr add | this = add | add.getLeftOperand() instanceof PathExpr and diff --git a/javascript/ql/lib/semmle/javascript/TypeScript.qll b/javascript/ql/lib/semmle/javascript/TypeScript.qll index d8b6b63a366f..4be331ed6a50 100644 --- a/javascript/ql/lib/semmle/javascript/TypeScript.qll +++ b/javascript/ql/lib/semmle/javascript/TypeScript.qll @@ -207,7 +207,7 @@ class ExternalModuleReference extends Expr, Import, @external_module_reference { /** Gets the expression specifying the module. */ Expr getExpression() { result = this.getChildExpr(0) } - override PathExpr getImportedPath() { result = this.getExpression() } + override Expr getImportedPathExpr() { result = this.getExpression() } override Module getEnclosingModule() { result = this.getTopLevel() } @@ -221,7 +221,7 @@ class ExternalModuleReference extends Expr, Import, @external_module_reference { } /** A literal path expression appearing in an external module reference. */ -private class LiteralExternalModulePath extends PathExpr, ConstantString { +deprecated private class LiteralExternalModulePath extends PathExpr, ConstantString { LiteralExternalModulePath() { exists(ExternalModuleReference emr | this.getParentExpr*() = emr.getExpression()) } @@ -743,7 +743,7 @@ class TypeAccess extends @typeaccess, TypeExpr, TypeRef { * For non-relative imports, it is the import path itself. */ private string getImportName(Import imprt) { - exists(string path | path = imprt.getImportedPath().getValue() | + exists(string path | path = imprt.getImportedPathString() | if path.regexpMatch("[./].*") then result = imprt.getImportedModule().getFile().getRelativePath() else result = path @@ -1731,7 +1731,7 @@ class TSGlobalDeclImport extends DataFlow::ModuleImportNode::Range { pkg = tt.getExpressionName() and // then, check pkg is imported as "import * as pkg from path" i.getLocal().getVariable() = pkg.getVariable() and - path = i.getImportedPath().getValue() and + path = i.getImportedPathString() and // finally, "this" needs to be a reference to gv this = DataFlow::exprNode(gv.getAnAccess()) ) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll index 2e2313835227..7f9b375f534e 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll @@ -738,7 +738,7 @@ module ModuleImportNode { DefaultRange() { exists(Import i | this = i.getImportedModuleNode() and - i.getImportedPath().getValue() = path + i.getImportedPathString() = path ) or // AMD require diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll index bb18ff078466..3134d76d8f16 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll @@ -25,7 +25,7 @@ private class AnalyzedImportSpecifier extends AnalyzedVarDef, @import_specifier override predicate isIncomplete(DataFlow::Incompleteness cause) { // mark as incomplete if the import could rely on the lookup path - mayDependOnLookupPath(id.getImportedPath().getValue()) and + mayDependOnLookupPath(id.getImportedPathString()) and cause = "import" or // mark as incomplete if we cannot fully analyze this import @@ -260,7 +260,7 @@ private class AnalyzedAmdImport extends AnalyzedPropertyRead, DataFlow::Node { Module required; AnalyzedAmdImport() { - exists(AmdModule amd, PathExpr dep | + exists(AmdModule amd, Expr dep | exists(Parameter p | amd.getDefine().dependencyParameter(dep, p) and this = DataFlow::parameterNode(p) diff --git a/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll b/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll index 948b8c9aff20..8ca2add4a274 100644 --- a/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll +++ b/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll @@ -151,6 +151,11 @@ class ExternalNpmDependency extends NpmDependency { } } +pragma[nomagic] +private string getPackagePrefix(Import i) { + result = i.getImportedPathString().(FilePath).getPackagePrefix() +} + /** * Holds if import `i` may refer to the declared dependency `dep` of package `pkg`, * where the result value is the nesting depth of the file containing `i` within `pkg`. @@ -159,7 +164,7 @@ private int importsDependency(Import i, NpmPackage pkg, NpmDependency dep) { exists(string name | dep = pkg.getPackageJson().getADependenciesObject(_).getPropValue(name) and not exists(i.getImportedModule()) and - i.getImportedPath().getComponent(0) = name and + name = getPackagePrefix(i) and i.getEnclosingModule() = pkg.getAModule() and result = distance(pkg, i.getFile()) ) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll index 1a6d11cd7534..a85a0a7813ce 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll @@ -32,7 +32,7 @@ pragma[nomagic] private predicate isAngularTopLevel(TopLevel tl) { exists(Import imprt | imprt.getTopLevel() = tl and - imprt.getImportedPath().getValue() = "angular" + imprt.getImportedPathString() = "angular" ) or exists(GlobalVarAccess global | diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll index 52315013d17f..4b3f70b77725 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll @@ -139,7 +139,7 @@ module Babel { /** * An import path expression that may be transformed by `babel-plugin-root-import`. */ - private class BabelRootTransformedPathExpr extends PathExpr, Expr { + deprecated private class BabelRootTransformedPathExpr extends PathExpr, Expr { RootImportConfig plugin; string prefix; string mappedPrefix; @@ -167,7 +167,7 @@ module Babel { /** * An import path transformed by `babel-plugin-root-import`. */ - private class BabelRootTransformedPath extends PathString { + deprecated private class BabelRootTransformedPath extends PathString { BabelRootTransformedPathExpr pathExpr; BabelRootTransformedPath() { this = pathExpr.getValue() } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll b/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll index 15240ce5cc0d..2c460fcc3451 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll @@ -36,7 +36,7 @@ module LazyCache { override Module getEnclosingModule() { result = this.getTopLevel() } - override PathExpr getImportedPath() { result = this.getArgument(0) } + override Expr getImportedPathExpr() { result = this.getArgument(0) } private LazyCacheVariable getVariable() { result = cache } @@ -58,7 +58,7 @@ module LazyCache { } /** A constant path element appearing in a call to a lazy-cache object. */ - private class LazyCachePathExpr extends PathExpr, ConstantString { + deprecated private class LazyCachePathExpr extends PathExpr, ConstantString { LazyCachePathExpr() { this = any(LazyCacheImport rp).getArgument(0) } override string getValue() { result = this.getStringValue() } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/React.qll b/javascript/ql/lib/semmle/javascript/frameworks/React.qll index 5ac0e419e264..4d126b888290 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/React.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/React.qll @@ -733,7 +733,7 @@ private class ReactRouterSource extends ClientSideRemoteFlowSource { * Holds if `mod` transitively depends on `react-router-dom`. */ private predicate dependsOnReactRouter(Module mod) { - mod.getAnImport().getImportedPath().getValue() = "react-router-dom" + mod.getAnImport().getImportedPathString() = "react-router-dom" or dependsOnReactRouter(mod.getAnImportedModule()) } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll index faba601df52d..2465ec668201 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll @@ -442,7 +442,7 @@ module Vue { override DataFlow::SourceNode getASource() { exists(Import imprt | - imprt.getImportedPath().resolve() instanceof VueFile and + imprt.getTargetFile() instanceof VueFile and result = imprt.getImportedModuleNode() ) } @@ -494,7 +494,7 @@ module Vue { // There is no explicit `new Vue()` call in .vue files, so instead get all the imports // of the .vue file. exists(Import imprt | - imprt.getImportedPath().resolve() = file and + imprt.getTargetFile() = file and result.asSource() = imprt.getImportedModuleNode() ) } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll index 1f51af3efda0..ee579d2c9db1 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll @@ -58,7 +58,7 @@ predicate parseTypeString(string rawType, string package, string qualifiedName) predicate isPackageUsed(string package) { package = "global" or - package = any(JS::Import imp).getImportedPath().getValue() + package = any(JS::Import imp).getImportedPathString() or any(JS::TypeName t).hasQualifiedName(package, _) or diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll index 853939dfe5f8..05b8a6207171 100644 --- a/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll @@ -240,7 +240,7 @@ module ResolveExpr { } private predicate isImportPathExpr(Expr e) { - e = any(Import imprt).getImportedPath() + e = any(Import imprt).getImportedPathExpr() or e = any(ReExportDeclaration decl).getImportedPath() } diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll index 7a6575f86475..f59c7b78e367 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll @@ -88,7 +88,7 @@ module ExternalApiUsedWithUntrustedData { not path instanceof SafeExternalApiPackage and // Exclude paths that can be resolved to a file in the project not exists(Import imprt | - imprt.getImportedPath().getValue() = path and exists(imprt.getImportedModule()) + imprt.getImportedPathString() = path and exists(imprt.getImportedModule()) ) ) or diff --git a/javascript/ql/src/Declarations/UnstableCyclicImport.ql b/javascript/ql/src/Declarations/UnstableCyclicImport.ql index 56f418c40a26..4ef4d8ca9465 100644 --- a/javascript/ql/src/Declarations/UnstableCyclicImport.ql +++ b/javascript/ql/src/Declarations/UnstableCyclicImport.ql @@ -152,4 +152,4 @@ where cycleAlert(mod, import_, importedModule, access) select access, access.getName() + " is uninitialized if $@ is loaded first in the cyclic import:" + " " + repr(import_) + " => " + min(pathToModule(importedModule, mod, _)) + " => " + repr(import_) + - ".", import_.getImportedPath(), importedModule.getName() + ".", import_.getImportedPathExpr(), importedModule.getName() diff --git a/javascript/ql/src/NodeJS/UnresolvableImport.ql b/javascript/ql/src/NodeJS/UnresolvableImport.ql index 16feba14348d..28c46229cf6a 100644 --- a/javascript/ql/src/NodeJS/UnresolvableImport.ql +++ b/javascript/ql/src/NodeJS/UnresolvableImport.ql @@ -24,7 +24,7 @@ PackageJson getClosestPackageJson(Folder f) { from Require r, string path, string mod where - path = r.getImportedPath().getValue() and + path = r.getImportedPathString() and // the imported module is the initial segment of the path, up to // `/` or the end of the string, whichever comes first; we exclude // local paths starting with `.` or `/`, since they might refer to files diff --git a/javascript/ql/src/NodeJS/UnusedDependency.ql b/javascript/ql/src/NodeJS/UnusedDependency.ql index 45bbde37294d..438f589cac9a 100644 --- a/javascript/ql/src/NodeJS/UnusedDependency.ql +++ b/javascript/ql/src/NodeJS/UnusedDependency.ql @@ -23,7 +23,17 @@ predicate declaresDependency(NpmPackage pkg, string name, JsonValue dep) { /** * Gets a path expression in a module belonging to `pkg`. */ -PathExpr getAPathExpr(NpmPackage pkg) { result.getEnclosingModule() = pkg.getAModule() } +Expr getAPathExpr(NpmPackage pkg) { + exists(Import imprt | + result = imprt.getImportedPathExpr() and + pkg.getAModule() = imprt.getEnclosingModule() + ) + or + exists(ReExportDeclaration decl | + result = decl.getImportedPath() and + pkg.getAModule() = decl.getEnclosingModule() + ) +} /** * Gets a URL-valued attribute in a module or HTML file belonging to `pkg`. @@ -56,9 +66,8 @@ predicate usesDependency(NpmPackage pkg, string name) { ( // there is a path expression (e.g., in a `require` or `import`) that // references `pkg` - exists(PathExpr path | path = getAPathExpr(pkg) | - // check whether the path is `name` or starts with `name/`, ignoring a prefix that ends with '!' (example: "scriptloader!moment") - path.getValue().regexpMatch("(.*!)?\\Q" + name + "\\E(/.*)?") + exists(Expr path | path = getAPathExpr(pkg) | + path.getStringValue().(FilePath).getPackagePrefix() = name ) or // there is an HTML URL attribute that may reference `pkg` diff --git a/javascript/ql/test/library-tests/AMD/tests.ql b/javascript/ql/test/library-tests/AMD/tests.ql index 956ad6d040ef..e71ae089f2d4 100644 --- a/javascript/ql/test/library-tests/AMD/tests.ql +++ b/javascript/ql/test/library-tests/AMD/tests.ql @@ -18,8 +18,8 @@ query predicate amdModuleDefinition(AmdModuleDefinition mod, DataFlow::SourceNod mod.getFactoryNode() = factory } -query predicate amdModuleDependencies(AmdModuleDefinition mod, PathExpr dependency) { - dependency = mod.getADependency() +query predicate amdModuleDependencies(AmdModuleDefinition mod, Expr dependency) { + dependency = mod.getADependencyExpr() } query predicate amdModuleExportedSymbol(AmdModule m, string sym) { sym = m.getAnExportedSymbol() } diff --git a/javascript/ql/test/library-tests/Modules/tests.ql b/javascript/ql/test/library-tests/Modules/tests.ql index ca0e196f488c..efe72731a7ba 100644 --- a/javascript/ql/test/library-tests/Modules/tests.ql +++ b/javascript/ql/test/library-tests/Modules/tests.ql @@ -22,8 +22,8 @@ query predicate test_ImportNamespaceSpecifier(ImportNamespaceSpecifier ins) { an query predicate test_ImportSpecifiers(ImportSpecifier is, VarDecl res) { res = is.getLocal() } -query predicate test_Imports(ImportDeclaration id, PathExpr res0, int res1) { - res0 = id.getImportedPath() and res1 = count(id.getASpecifier()) +query predicate test_Imports(ImportDeclaration id, Expr res0, int res1) { + res0 = id.getImportedPathExpr() and res1 = count(id.getASpecifier()) } query predicate test_Module_exports(Module m, string name, DataFlow::Node exportValue) { diff --git a/javascript/ql/test/library-tests/NodeJS/tests.ql b/javascript/ql/test/library-tests/NodeJS/tests.ql index eca3a132d263..f5e0f58dc467 100644 --- a/javascript/ql/test/library-tests/NodeJS/tests.ql +++ b/javascript/ql/test/library-tests/NodeJS/tests.ql @@ -26,7 +26,7 @@ query predicate require(Require r) { any() } query predicate requireImport(Require r, string path, Module mod) { exists(string fullpath, string prefix | - fullpath = r.getImportedPath().getValue() and + fullpath = r.getImportedPathString() and sourceLocationPrefix(prefix) and path = fullpath.replaceAll(prefix, "") and mod = r.getImportedModule() diff --git a/javascript/ql/test/library-tests/TypeScript/ImportEquals/tests.ql b/javascript/ql/test/library-tests/TypeScript/ImportEquals/tests.ql index 839ba2c560bf..5de6c99c748d 100644 --- a/javascript/ql/test/library-tests/TypeScript/ImportEquals/tests.ql +++ b/javascript/ql/test/library-tests/TypeScript/ImportEquals/tests.ql @@ -5,7 +5,7 @@ query predicate dataFlowModuleImports(string name, DataFlow::SourceNode imp) { } query predicate imports(Import imprt, string path, Module mod) { - path = imprt.getImportedPath().getValue() and + path = imprt.getImportedPathString() and mod = imprt.getImportedModule() } diff --git a/javascript/ql/test/library-tests/TypeScript/RegressionTests/ImportDtsFile/test.ql b/javascript/ql/test/library-tests/TypeScript/RegressionTests/ImportDtsFile/test.ql index 3c5e8a7fd168..0c8a95e3b3bd 100644 --- a/javascript/ql/test/library-tests/TypeScript/RegressionTests/ImportDtsFile/test.ql +++ b/javascript/ql/test/library-tests/TypeScript/RegressionTests/ImportDtsFile/test.ql @@ -1,4 +1,4 @@ import javascript from Import imprt -select imprt, imprt.getImportedPath().getValue(), imprt.getImportedModule() +select imprt, imprt.getImportedPathString(), imprt.getImportedModule() From acb9c20a7624c0817eaeb962cda1c4d30af44dbe Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 29 Apr 2025 13:22:11 +0100 Subject: [PATCH 148/336] Use explicit fastTC --- .../Resources/FileNotAlwaysClosedQuery.qll | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/python/ql/src/Resources/FileNotAlwaysClosedQuery.qll b/python/ql/src/Resources/FileNotAlwaysClosedQuery.qll index fe1d6578e11e..af31ec6ea4fb 100644 --- a/python/ql/src/Resources/FileNotAlwaysClosedQuery.qll +++ b/python/ql/src/Resources/FileNotAlwaysClosedQuery.qll @@ -52,14 +52,29 @@ class FileWrapperCall extends DataFlow::CallCfgNode { abstract class FileClose extends DataFlow::CfgNode { /** Holds if this file close will occur if an exception is thrown at `raises`. */ predicate guardsExceptions(DataFlow::CfgNode raises) { - this.asCfgNode() = raises.asCfgNode().getAnExceptionalSuccessor().getASuccessor*() + cfgGetASuccessorStar(raises.asCfgNode().getAnExceptionalSuccessor(), this.asCfgNode()) or // The expression is after the close call. // This also covers the body of a `with` statement. - raises.asCfgNode() = this.asCfgNode().getASuccessor*() + cfgGetASuccessorStar(this.asCfgNode(), raises.asCfgNode()) } } +private predicate cfgGetASuccessor(ControlFlowNode src, ControlFlowNode sink) { + sink = src.getASuccessor() +} + +pragma[inline] +private predicate cfgGetASuccessorPlus(ControlFlowNode src, ControlFlowNode sink) = + fastTC(cfgGetASuccessor/2)(src, sink) + +pragma[inline] +private predicate cfgGetASuccessorStar(ControlFlowNode src, ControlFlowNode sink) { + src = sink + or + cfgGetASuccessorPlus(src, sink) +} + /** A call to the `.close()` method of a file object. */ class FileCloseCall extends FileClose { FileCloseCall() { exists(DataFlow::MethodCallNode mc | mc.calls(this, "close")) } From 7f9020282dae18959a3ee34c1f21bdf3c744496c Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 29 Apr 2025 13:16:40 +0200 Subject: [PATCH 149/336] C++: Turn header variant tests that use PCH files into integration tests These tests currently test a code path in the extractor that only exists for these tests. By turning them into integration tests, we actually use the code path that normal database creation uses. --- .../header-variant-tests/clang-pch/a.c | 2 ++ .../header-variant-tests/clang-pch/a.h | 0 .../header-variant-tests/clang-pch/b.c | 0 .../header-variant-tests/clang-pch/b.h | 0 .../header-variant-tests/clang-pch/c.c | 3 +++ .../clang-pch/clang-pch.expected | 0 .../header-variant-tests/clang-pch/clang-pch.ql | 0 .../header-variant-tests/clang-pch/d.c | 1 + .../header-variant-tests/clang-pch/d.h | 0 .../header-variant-tests/clang-pch/e.c | 3 +++ .../header-variant-tests/clang-pch/f.c | 5 +++++ .../header-variant-tests/clang-pch/g.c | 5 +++++ .../header-variant-tests/clang-pch/h.c | 4 ++++ .../header-variant-tests/clang-pch/h1.h | 0 .../header-variant-tests/clang-pch/h2.h | 0 .../header-variant-tests/clang-pch/i.c | 1 - .../header-variant-tests/clang-pch/test.py | 16 ++++++++++++++++ .../header-variant-tests/microsoft-pch/a.c | 1 + .../header-variant-tests/microsoft-pch/a.h | 0 .../header-variant-tests/microsoft-pch/b.c | 6 ++++++ .../header-variant-tests/microsoft-pch/c.c | 6 ++++++ .../microsoft-pch/microsoft-pch.expected | 0 .../microsoft-pch/microsoft-pch.ql | 0 .../header-variant-tests/microsoft-pch/test.py | 10 ++++++++++ cpp/ql/test/header-variant-tests/clang-pch/_.c | 3 --- cpp/ql/test/header-variant-tests/clang-pch/a.c | 3 --- cpp/ql/test/header-variant-tests/clang-pch/c.c | 4 ---- cpp/ql/test/header-variant-tests/clang-pch/d.c | 2 -- cpp/ql/test/header-variant-tests/clang-pch/e.c | 4 ---- cpp/ql/test/header-variant-tests/clang-pch/f.c | 6 ------ cpp/ql/test/header-variant-tests/clang-pch/g.c | 6 ------ cpp/ql/test/header-variant-tests/clang-pch/h.c | 5 ----- .../test/header-variant-tests/microsoft-pch/_.c | 3 --- .../test/header-variant-tests/microsoft-pch/a.c | 2 -- .../test/header-variant-tests/microsoft-pch/b.c | 7 ------- .../test/header-variant-tests/microsoft-pch/c.c | 7 ------- 36 files changed, 62 insertions(+), 53 deletions(-) create mode 100644 cpp/ql/integration-tests/header-variant-tests/clang-pch/a.c rename cpp/ql/{test => integration-tests}/header-variant-tests/clang-pch/a.h (100%) rename cpp/ql/{test => integration-tests}/header-variant-tests/clang-pch/b.c (100%) rename cpp/ql/{test => integration-tests}/header-variant-tests/clang-pch/b.h (100%) create mode 100644 cpp/ql/integration-tests/header-variant-tests/clang-pch/c.c rename cpp/ql/{test => integration-tests}/header-variant-tests/clang-pch/clang-pch.expected (100%) rename cpp/ql/{test => integration-tests}/header-variant-tests/clang-pch/clang-pch.ql (100%) create mode 100644 cpp/ql/integration-tests/header-variant-tests/clang-pch/d.c rename cpp/ql/{test => integration-tests}/header-variant-tests/clang-pch/d.h (100%) create mode 100644 cpp/ql/integration-tests/header-variant-tests/clang-pch/e.c create mode 100644 cpp/ql/integration-tests/header-variant-tests/clang-pch/f.c create mode 100644 cpp/ql/integration-tests/header-variant-tests/clang-pch/g.c create mode 100644 cpp/ql/integration-tests/header-variant-tests/clang-pch/h.c rename cpp/ql/{test => integration-tests}/header-variant-tests/clang-pch/h1.h (100%) rename cpp/ql/{test => integration-tests}/header-variant-tests/clang-pch/h2.h (100%) rename cpp/ql/{test => integration-tests}/header-variant-tests/clang-pch/i.c (64%) create mode 100644 cpp/ql/integration-tests/header-variant-tests/clang-pch/test.py create mode 100644 cpp/ql/integration-tests/header-variant-tests/microsoft-pch/a.c rename cpp/ql/{test => integration-tests}/header-variant-tests/microsoft-pch/a.h (100%) create mode 100644 cpp/ql/integration-tests/header-variant-tests/microsoft-pch/b.c create mode 100644 cpp/ql/integration-tests/header-variant-tests/microsoft-pch/c.c rename cpp/ql/{test => integration-tests}/header-variant-tests/microsoft-pch/microsoft-pch.expected (100%) rename cpp/ql/{test => integration-tests}/header-variant-tests/microsoft-pch/microsoft-pch.ql (100%) create mode 100644 cpp/ql/integration-tests/header-variant-tests/microsoft-pch/test.py delete mode 100644 cpp/ql/test/header-variant-tests/clang-pch/_.c delete mode 100644 cpp/ql/test/header-variant-tests/clang-pch/a.c delete mode 100644 cpp/ql/test/header-variant-tests/clang-pch/c.c delete mode 100644 cpp/ql/test/header-variant-tests/clang-pch/d.c delete mode 100644 cpp/ql/test/header-variant-tests/clang-pch/e.c delete mode 100644 cpp/ql/test/header-variant-tests/clang-pch/f.c delete mode 100644 cpp/ql/test/header-variant-tests/clang-pch/g.c delete mode 100644 cpp/ql/test/header-variant-tests/clang-pch/h.c delete mode 100644 cpp/ql/test/header-variant-tests/microsoft-pch/_.c delete mode 100644 cpp/ql/test/header-variant-tests/microsoft-pch/a.c delete mode 100644 cpp/ql/test/header-variant-tests/microsoft-pch/b.c delete mode 100644 cpp/ql/test/header-variant-tests/microsoft-pch/c.c diff --git a/cpp/ql/integration-tests/header-variant-tests/clang-pch/a.c b/cpp/ql/integration-tests/header-variant-tests/clang-pch/a.c new file mode 100644 index 000000000000..f80dfe401603 --- /dev/null +++ b/cpp/ql/integration-tests/header-variant-tests/clang-pch/a.c @@ -0,0 +1,2 @@ +#include "a.h" +#define FOUR 4 diff --git a/cpp/ql/test/header-variant-tests/clang-pch/a.h b/cpp/ql/integration-tests/header-variant-tests/clang-pch/a.h similarity index 100% rename from cpp/ql/test/header-variant-tests/clang-pch/a.h rename to cpp/ql/integration-tests/header-variant-tests/clang-pch/a.h diff --git a/cpp/ql/test/header-variant-tests/clang-pch/b.c b/cpp/ql/integration-tests/header-variant-tests/clang-pch/b.c similarity index 100% rename from cpp/ql/test/header-variant-tests/clang-pch/b.c rename to cpp/ql/integration-tests/header-variant-tests/clang-pch/b.c diff --git a/cpp/ql/test/header-variant-tests/clang-pch/b.h b/cpp/ql/integration-tests/header-variant-tests/clang-pch/b.h similarity index 100% rename from cpp/ql/test/header-variant-tests/clang-pch/b.h rename to cpp/ql/integration-tests/header-variant-tests/clang-pch/b.h diff --git a/cpp/ql/integration-tests/header-variant-tests/clang-pch/c.c b/cpp/ql/integration-tests/header-variant-tests/clang-pch/c.c new file mode 100644 index 000000000000..e8c42c9c4b22 --- /dev/null +++ b/cpp/ql/integration-tests/header-variant-tests/clang-pch/c.c @@ -0,0 +1,3 @@ +int main() { + return ONE + FOUR; +} diff --git a/cpp/ql/test/header-variant-tests/clang-pch/clang-pch.expected b/cpp/ql/integration-tests/header-variant-tests/clang-pch/clang-pch.expected similarity index 100% rename from cpp/ql/test/header-variant-tests/clang-pch/clang-pch.expected rename to cpp/ql/integration-tests/header-variant-tests/clang-pch/clang-pch.expected diff --git a/cpp/ql/test/header-variant-tests/clang-pch/clang-pch.ql b/cpp/ql/integration-tests/header-variant-tests/clang-pch/clang-pch.ql similarity index 100% rename from cpp/ql/test/header-variant-tests/clang-pch/clang-pch.ql rename to cpp/ql/integration-tests/header-variant-tests/clang-pch/clang-pch.ql diff --git a/cpp/ql/integration-tests/header-variant-tests/clang-pch/d.c b/cpp/ql/integration-tests/header-variant-tests/clang-pch/d.c new file mode 100644 index 000000000000..35e2312fd892 --- /dev/null +++ b/cpp/ql/integration-tests/header-variant-tests/clang-pch/d.c @@ -0,0 +1 @@ +#import "d.h" diff --git a/cpp/ql/test/header-variant-tests/clang-pch/d.h b/cpp/ql/integration-tests/header-variant-tests/clang-pch/d.h similarity index 100% rename from cpp/ql/test/header-variant-tests/clang-pch/d.h rename to cpp/ql/integration-tests/header-variant-tests/clang-pch/d.h diff --git a/cpp/ql/integration-tests/header-variant-tests/clang-pch/e.c b/cpp/ql/integration-tests/header-variant-tests/clang-pch/e.c new file mode 100644 index 000000000000..571efb6f271a --- /dev/null +++ b/cpp/ql/integration-tests/header-variant-tests/clang-pch/e.c @@ -0,0 +1,3 @@ +int main() { + return SEVENTEEN; +} diff --git a/cpp/ql/integration-tests/header-variant-tests/clang-pch/f.c b/cpp/ql/integration-tests/header-variant-tests/clang-pch/f.c new file mode 100644 index 000000000000..613824dc7836 --- /dev/null +++ b/cpp/ql/integration-tests/header-variant-tests/clang-pch/f.c @@ -0,0 +1,5 @@ +#if 1 +#pragma hdrstop +extern int x; +#define SEEN_F +#endif diff --git a/cpp/ql/integration-tests/header-variant-tests/clang-pch/g.c b/cpp/ql/integration-tests/header-variant-tests/clang-pch/g.c new file mode 100644 index 000000000000..bf105c29e95f --- /dev/null +++ b/cpp/ql/integration-tests/header-variant-tests/clang-pch/g.c @@ -0,0 +1,5 @@ +#ifdef SEEN_F +static int g() { + return 20; +} +#endif diff --git a/cpp/ql/integration-tests/header-variant-tests/clang-pch/h.c b/cpp/ql/integration-tests/header-variant-tests/clang-pch/h.c new file mode 100644 index 000000000000..6f183a7070fc --- /dev/null +++ b/cpp/ql/integration-tests/header-variant-tests/clang-pch/h.c @@ -0,0 +1,4 @@ +#include "h1.h" +#pragma hdrstop +#include "h2.h" +#define SEEN_H diff --git a/cpp/ql/test/header-variant-tests/clang-pch/h1.h b/cpp/ql/integration-tests/header-variant-tests/clang-pch/h1.h similarity index 100% rename from cpp/ql/test/header-variant-tests/clang-pch/h1.h rename to cpp/ql/integration-tests/header-variant-tests/clang-pch/h1.h diff --git a/cpp/ql/test/header-variant-tests/clang-pch/h2.h b/cpp/ql/integration-tests/header-variant-tests/clang-pch/h2.h similarity index 100% rename from cpp/ql/test/header-variant-tests/clang-pch/h2.h rename to cpp/ql/integration-tests/header-variant-tests/clang-pch/h2.h diff --git a/cpp/ql/test/header-variant-tests/clang-pch/i.c b/cpp/ql/integration-tests/header-variant-tests/clang-pch/i.c similarity index 64% rename from cpp/ql/test/header-variant-tests/clang-pch/i.c rename to cpp/ql/integration-tests/header-variant-tests/clang-pch/i.c index 05aa74b3047b..1274d6750001 100644 --- a/cpp/ql/test/header-variant-tests/clang-pch/i.c +++ b/cpp/ql/integration-tests/header-variant-tests/clang-pch/i.c @@ -13,4 +13,3 @@ static int h2() { return 32; } #endif -// semmle-extractor-options: --clang -include-pch ${testdir}/clang-pch.testproj/h.pch diff --git a/cpp/ql/integration-tests/header-variant-tests/clang-pch/test.py b/cpp/ql/integration-tests/header-variant-tests/clang-pch/test.py new file mode 100644 index 000000000000..3cf2d42f7643 --- /dev/null +++ b/cpp/ql/integration-tests/header-variant-tests/clang-pch/test.py @@ -0,0 +1,16 @@ +import os + + +def test(codeql, cpp): + os.mkdir("pch") + codeql.database.create(command=[ + f'"{cpp.get_tool("extractor")}" --mimic-clang -emit-pch -o pch/a.pch a.c', + f'"{cpp.get_tool("extractor")}" --mimic-clang -include-pch pch/a.pch -Iextra_dummy_path b.c', + f'"{cpp.get_tool("extractor")}" --mimic-clang -include pch/a -Iextra_dummy_path c.c', + f'"{cpp.get_tool("extractor")}" --mimic-clang -emit-pch -o pch/d.pch d.c', + f'"{cpp.get_tool("extractor")}" --mimic-clang -include-pch pch/d.pch e.c', + f'"{cpp.get_tool("extractor")}" --mimic-clang -emit-pch -o pch/f.pch f.c', + f'"{cpp.get_tool("extractor")}" --mimic-clang -include-pch pch/f.pch g.c', + f'"{cpp.get_tool("extractor")}" --mimic-clang -emit-pch -o pch/h.pch h.c', + f'"{cpp.get_tool("extractor")}" --mimic-clang -include-pch pch/h.pch i.c', + ]) diff --git a/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/a.c b/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/a.c new file mode 100644 index 000000000000..2243de1baf9a --- /dev/null +++ b/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/a.c @@ -0,0 +1 @@ +#include "a.h" diff --git a/cpp/ql/test/header-variant-tests/microsoft-pch/a.h b/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/a.h similarity index 100% rename from cpp/ql/test/header-variant-tests/microsoft-pch/a.h rename to cpp/ql/integration-tests/header-variant-tests/microsoft-pch/a.h diff --git a/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/b.c b/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/b.c new file mode 100644 index 000000000000..ef8f5d3ca55d --- /dev/null +++ b/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/b.c @@ -0,0 +1,6 @@ +#pragma hdrstop +#include "b.h" + +int b() { + return A; +} diff --git a/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/c.c b/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/c.c new file mode 100644 index 000000000000..b270ddd64780 --- /dev/null +++ b/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/c.c @@ -0,0 +1,6 @@ +#include "d.h" +#include "c.h" + +int c() { + return A; +} diff --git a/cpp/ql/test/header-variant-tests/microsoft-pch/microsoft-pch.expected b/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/microsoft-pch.expected similarity index 100% rename from cpp/ql/test/header-variant-tests/microsoft-pch/microsoft-pch.expected rename to cpp/ql/integration-tests/header-variant-tests/microsoft-pch/microsoft-pch.expected diff --git a/cpp/ql/test/header-variant-tests/microsoft-pch/microsoft-pch.ql b/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/microsoft-pch.ql similarity index 100% rename from cpp/ql/test/header-variant-tests/microsoft-pch/microsoft-pch.ql rename to cpp/ql/integration-tests/header-variant-tests/microsoft-pch/microsoft-pch.ql diff --git a/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/test.py b/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/test.py new file mode 100644 index 000000000000..eaa0fdb8786c --- /dev/null +++ b/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/test.py @@ -0,0 +1,10 @@ +import os + + +def test(codeql, cpp): + os.mkdir("pch") + codeql.database.create(command=[ + f'"{cpp.get_tool("extractor")}" --mimic-cl /Yca.h /Fppch/a.pch a.c', + f'"{cpp.get_tool("extractor")}" --mimic-cl /Yub.h /Fppch/a.pch b.c', + f'"{cpp.get_tool("extractor")}" --mimic-cl /Yuc.h /Fppch/a.pch c.c', + ]) diff --git a/cpp/ql/test/header-variant-tests/clang-pch/_.c b/cpp/ql/test/header-variant-tests/clang-pch/_.c deleted file mode 100644 index 6186edd586f7..000000000000 --- a/cpp/ql/test/header-variant-tests/clang-pch/_.c +++ /dev/null @@ -1,3 +0,0 @@ -// This file exists to ensure that the output subdirectory exists prior to -// a.c being indexed, as said directory needs to exist for the PCH file to -// be created, and will be created by running the extractor. diff --git a/cpp/ql/test/header-variant-tests/clang-pch/a.c b/cpp/ql/test/header-variant-tests/clang-pch/a.c deleted file mode 100644 index 9164cdc19a58..000000000000 --- a/cpp/ql/test/header-variant-tests/clang-pch/a.c +++ /dev/null @@ -1,3 +0,0 @@ -#include "a.h" -#define FOUR 4 -// semmle-extractor-options: --clang -emit-pch -o ${testdir}/clang-pch.testproj/a.pch diff --git a/cpp/ql/test/header-variant-tests/clang-pch/c.c b/cpp/ql/test/header-variant-tests/clang-pch/c.c deleted file mode 100644 index 0a8b97667137..000000000000 --- a/cpp/ql/test/header-variant-tests/clang-pch/c.c +++ /dev/null @@ -1,4 +0,0 @@ -int main() { - return ONE + FOUR; -} -// semmle-extractor-options: --clang -include ${testdir}/clang-pch.testproj/a -Iextra_dummy_path diff --git a/cpp/ql/test/header-variant-tests/clang-pch/d.c b/cpp/ql/test/header-variant-tests/clang-pch/d.c deleted file mode 100644 index f81af3d1b63c..000000000000 --- a/cpp/ql/test/header-variant-tests/clang-pch/d.c +++ /dev/null @@ -1,2 +0,0 @@ -#import "d.h" -// semmle-extractor-options: --clang -emit-pch -o ${testdir}/clang-pch.testproj/d.pch diff --git a/cpp/ql/test/header-variant-tests/clang-pch/e.c b/cpp/ql/test/header-variant-tests/clang-pch/e.c deleted file mode 100644 index abdb59002009..000000000000 --- a/cpp/ql/test/header-variant-tests/clang-pch/e.c +++ /dev/null @@ -1,4 +0,0 @@ -int main() { - return SEVENTEEN; -} -// semmle-extractor-options: --clang -include-pch ${testdir}/clang-pch.testproj/d.pch diff --git a/cpp/ql/test/header-variant-tests/clang-pch/f.c b/cpp/ql/test/header-variant-tests/clang-pch/f.c deleted file mode 100644 index cca56931acd5..000000000000 --- a/cpp/ql/test/header-variant-tests/clang-pch/f.c +++ /dev/null @@ -1,6 +0,0 @@ -#if 1 -#pragma hdrstop -extern int x; -#define SEEN_F -#endif -// semmle-extractor-options: --clang -emit-pch -o ${testdir}/clang-pch.testproj/f.pch diff --git a/cpp/ql/test/header-variant-tests/clang-pch/g.c b/cpp/ql/test/header-variant-tests/clang-pch/g.c deleted file mode 100644 index b16ca33ab369..000000000000 --- a/cpp/ql/test/header-variant-tests/clang-pch/g.c +++ /dev/null @@ -1,6 +0,0 @@ -#ifdef SEEN_F -static int g() { - return 20; -} -#endif -// semmle-extractor-options: --clang -include-pch ${testdir}/clang-pch.testproj/f.pch diff --git a/cpp/ql/test/header-variant-tests/clang-pch/h.c b/cpp/ql/test/header-variant-tests/clang-pch/h.c deleted file mode 100644 index 7ffc9b6133c1..000000000000 --- a/cpp/ql/test/header-variant-tests/clang-pch/h.c +++ /dev/null @@ -1,5 +0,0 @@ -#include "h1.h" -#pragma hdrstop -#include "h2.h" -#define SEEN_H -// semmle-extractor-options: --clang -emit-pch -o ${testdir}/clang-pch.testproj/h.pch diff --git a/cpp/ql/test/header-variant-tests/microsoft-pch/_.c b/cpp/ql/test/header-variant-tests/microsoft-pch/_.c deleted file mode 100644 index 6186edd586f7..000000000000 --- a/cpp/ql/test/header-variant-tests/microsoft-pch/_.c +++ /dev/null @@ -1,3 +0,0 @@ -// This file exists to ensure that the output subdirectory exists prior to -// a.c being indexed, as said directory needs to exist for the PCH file to -// be created, and will be created by running the extractor. diff --git a/cpp/ql/test/header-variant-tests/microsoft-pch/a.c b/cpp/ql/test/header-variant-tests/microsoft-pch/a.c deleted file mode 100644 index ba41bafcaade..000000000000 --- a/cpp/ql/test/header-variant-tests/microsoft-pch/a.c +++ /dev/null @@ -1,2 +0,0 @@ -#include "a.h" -// semmle-extractor-options: --microsoft /Yca.h /Fp${testdir}/microsoft-pch.testproj/a.pch diff --git a/cpp/ql/test/header-variant-tests/microsoft-pch/b.c b/cpp/ql/test/header-variant-tests/microsoft-pch/b.c deleted file mode 100644 index b6ea5085fd1f..000000000000 --- a/cpp/ql/test/header-variant-tests/microsoft-pch/b.c +++ /dev/null @@ -1,7 +0,0 @@ -#pragma hdrstop -#include "b.h" - -int b() { - return A; -} -// semmle-extractor-options: --microsoft /Yub.h /Fp${testdir}/microsoft-pch.testproj/a.pch diff --git a/cpp/ql/test/header-variant-tests/microsoft-pch/c.c b/cpp/ql/test/header-variant-tests/microsoft-pch/c.c deleted file mode 100644 index aaddbae8688d..000000000000 --- a/cpp/ql/test/header-variant-tests/microsoft-pch/c.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "d.h" -#include "c.h" - -int c() { - return A; -} -// semmle-extractor-options: --microsoft /Yuc.h /Fp${testdir}/microsoft-pch.testproj/a.pch From e40b93b8a353b3fcdd87d4ee4e4e10d08ac866c6 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Apr 2025 14:50:57 +0200 Subject: [PATCH 150/336] JS: Add type-tracking step through simple Promise.all() calls --- .../internal/flow_summaries/Promises.qll | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll index 33299a3f5c09..1122c38320a5 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll @@ -4,6 +4,7 @@ private import javascript private import semmle.javascript.dataflow.FlowSummary +private import semmle.javascript.dataflow.TypeTracking private import FlowSummaryUtil DataFlow::SourceNode promiseConstructorRef() { @@ -211,12 +212,57 @@ private class PromiseReject extends SummarizedCallable { } } +/** + * A call to `Promise.all()`. + */ +class PromiseAllCall extends DataFlow::CallNode { + PromiseAllCall() { this = promiseConstructorRef().getAMemberCall("all") } + + /** Gets the source of the input array */ + DataFlow::ArrayCreationNode getInputArray() { result = this.getArgument(0).getALocalSource() } + + /** Gets the `n`th element of the input array */ + DataFlow::Node getNthInput(int n) { result = this.getInputArray().getElement(n) } + + /** Gets a reference to the output array. */ + DataFlow::SourceNode getOutputArray() { + exists(AwaitExpr await | + this.flowsToExpr(await.getOperand()) and + result = await.flow() + ) + or + result = this.getAMethodCall("then").getCallback(0).getParameter(0) + } + + /** Gets the `n`th output */ + DataFlow::SourceNode getNthOutput(int n) { + exists(string prop | + result = this.getOutputArray().getAPropertyRead(prop) and + n = prop.toInt() + ) + } +} + +/** + * Helps type-tracking simple uses of `Promise.all()` such as `const [a, b] = await Promise.all([x, y])`. + * + * Due to limited access path depth, type tracking can't track things that are in a promise and an array + * at once. This generates a step directly from the input array to the output array. + */ +private class PromiseAllStep extends SharedTypeTrackingStep { + override predicate loadStep(DataFlow::Node node1, DataFlow::Node node2, string prop) { + exists(PromiseAllCall call, int n | + node1 = call.getNthInput(n) and + node2 = call.getNthOutput(n) and + prop = Promises::valueProp() + ) + } +} + private class PromiseAll extends SummarizedCallable { PromiseAll() { this = "Promise.all()" } - override DataFlow::InvokeNode getACallSimple() { - result = promiseConstructorRef().getAMemberCall("all") - } + override DataFlow::InvokeNode getACallSimple() { result instanceof PromiseAllCall } override predicate propagatesFlow(string input, string output, boolean preservesValue) { preservesValue = true and From eae1e1cb0225bf8cfa93549d4df7eceea8f38129 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Apr 2025 14:51:17 +0200 Subject: [PATCH 151/336] JS: Make API graphs rely on type-tracking steps in general --- javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 974fdd7c0cbf..276fe5a01690 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -850,10 +850,10 @@ module API { ) or lbl = Label::promised() and - PromiseFlow::storeStep(rhs, pred, Promises::valueProp()) + SharedTypeTrackingStep::storeStep(rhs, pred, Promises::valueProp()) or lbl = Label::promisedError() and - PromiseFlow::storeStep(rhs, pred, Promises::errorProp()) + SharedTypeTrackingStep::storeStep(rhs, pred, Promises::errorProp()) or // The return-value of a getter G counts as a definition of property G // (Ordinary methods and properties are handled as PropWrite nodes) @@ -1008,11 +1008,11 @@ module API { propDesc = "" ) or - PromiseFlow::loadStep(pred.getALocalUse(), ref, Promises::valueProp()) and + SharedTypeTrackingStep::loadStep(pred.getALocalUse(), ref, Promises::valueProp()) and lbl = Label::promised() and (propDesc = Promises::valueProp() or propDesc = "") or - PromiseFlow::loadStep(pred.getALocalUse(), ref, Promises::errorProp()) and + SharedTypeTrackingStep::loadStep(pred.getALocalUse(), ref, Promises::errorProp()) and lbl = Label::promisedError() and (propDesc = Promises::errorProp() or propDesc = "") } From b5c596b2ce2450e1969ca751fa3ff3ce47155bf9 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 24 Apr 2025 15:32:12 +0200 Subject: [PATCH 152/336] Shared: Split model printing of summaries and sources/sinks into separate param modules. --- .../CaptureTypeBasedSummaryModels.qll | 6 ++-- .../CaptureTypeBasedSummaryModels.qll | 6 ++-- .../internal/ModelGeneratorImpl.qll | 31 +++++++++++-------- .../modelgenerator/internal/ModelPrinting.qll | 28 ++++++++++++----- 4 files changed, 42 insertions(+), 29 deletions(-) diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll index f7b0633ddd39..62286c27888c 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll @@ -177,15 +177,13 @@ private predicate output(Callable callable, TypeParameter tp, string output) { delegateSink(callable, tp, output) } -private module ModelPrintingInput implements ModelPrintingSig { +private module ModelPrintingInput implements ModelPrintingSummarySig { class SummaryApi = TypeBasedFlowTargetApi; - class SourceOrSinkApi = TypeBasedFlowTargetApi; - string getProvenance() { result = "tb-generated" } } -private module Printing = ModelPrinting; +private module Printing = ModelPrintingSummary; /** * A class of callables that are relevant generating summaries for based diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll b/java/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll index 36aec8053196..9145a0779075 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll @@ -284,15 +284,13 @@ private predicate output(Callable callable, TypeVariable tv, string output) { functionalSink(callable, tv, output) } -module ModelPrintingInput implements ModelPrintingSig { +module ModelPrintingInput implements ModelPrintingSummarySig { class SummaryApi = TypeBasedFlowTargetApi; - class SourceOrSinkApi = ModelGeneratorInput::SourceOrSinkTargetApi; - string getProvenance() { result = "tb-generated" } } -private module Printing = ModelPrinting; +private module Printing = ModelPrintingSummary; /** * A class of callables that are relevant generating summaries for based diff --git a/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll b/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll index b9592964f931..59f53c2b1c90 100644 --- a/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll +++ b/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll @@ -370,20 +370,27 @@ module MakeModelGenerator< * based on heuristic data flow. */ module Heuristic { - private module ModelPrintingInput implements Printing::ModelPrintingSig { + private module ModelPrintingSummaryInput implements Printing::ModelPrintingSummarySig { class SummaryApi = DataFlowSummaryTargetApi; + string getProvenance() { result = "df-generated" } + } + + module ModelPrintingSummary = Printing::ModelPrintingSummary; + + private module ModelPrintingSourceOrSinkInput implements Printing::ModelPrintingSourceOrSinkSig { class SourceOrSinkApi = SourceOrSinkTargetApi; string getProvenance() { result = "df-generated" } } - module ModelPrinting = Printing::ModelPrinting; - private string getOutput(ReturnNodeExt node) { result = PrintReturnNodeExt::getOutput(node) } + private module ModelPrintingSourceOrSink = + Printing::ModelPrintingSourceOrSink; + /** * Holds if data can flow from `node1` to `node2` either via a read or a write of an intermediate field `f`. */ @@ -419,7 +426,7 @@ module MakeModelGenerator< api = returnNodeEnclosingCallable(ret) and isOwnInstanceAccessNode(ret) ) and - result = ModelPrinting::asLiftedValueModel(api, qualifierString(), "ReturnValue") + result = ModelPrintingSummary::asLiftedValueModel(api, qualifierString(), "ReturnValue") } private int accessPathLimit0() { result = 2 } @@ -539,7 +546,7 @@ module MakeModelGenerator< input = parameterNodeAsInput(p) and output = getOutput(returnNodeExt) and input != output and - result = ModelPrinting::asLiftedTaintModel(api, input, output) + result = ModelPrintingSummary::asLiftedTaintModel(api, input, output) ) } @@ -572,7 +579,7 @@ module MakeModelGenerator< exists(captureFlow(api0)) and api0.lift() = api.lift() ) and api.isRelevant() and - result = ModelPrinting::asNeutralSummaryModel(api) + result = ModelPrintingSummary::asNeutralSummaryModel(api) } /** @@ -617,7 +624,7 @@ module MakeModelGenerator< sourceNode(source, kind) and api = getEnclosingCallable(sink) and not irrelevantSourceSinkApi(getEnclosingCallable(source), api) and - result = ModelPrinting::asSourceModel(api, getOutput(sink), kind) + result = ModelPrintingSourceOrSink::asSourceModel(api, getOutput(sink), kind) ) } @@ -663,7 +670,7 @@ module MakeModelGenerator< PropagateToSink::flow(src, sink) and sinkNode(sink, kind) and api = getEnclosingCallable(src) and - result = ModelPrinting::asSinkModel(api, asInputArgument(src), kind) + result = ModelPrintingSourceOrSink::asSinkModel(api, asInputArgument(src), kind) ) } } @@ -703,15 +710,13 @@ module MakeModelGenerator< private module PropagateContentFlow = ContentDataFlow::Global; - private module ContentModelPrintingInput implements Printing::ModelPrintingSig { + private module ContentModelPrintingInput implements Printing::ModelPrintingSummarySig { class SummaryApi = DataFlowSummaryTargetApi; - class SourceOrSinkApi = SourceOrSinkTargetApi; - string getProvenance() { result = "dfc-generated" } } - private module ContentModelPrinting = Printing::ModelPrinting; + private module ContentModelPrinting = Printing::ModelPrintingSummary; private string getContentOutput(ReturnNodeExt node) { result = PrintReturnNodeExt::getOutput(node) @@ -1075,6 +1080,6 @@ module MakeModelGenerator< ) ) and api.isRelevant() and - result = Heuristic::ModelPrinting::asNeutralSummaryModel(api) + result = Heuristic::ModelPrintingSummary::asNeutralSummaryModel(api) } } diff --git a/shared/mad/codeql/mad/modelgenerator/internal/ModelPrinting.qll b/shared/mad/codeql/mad/modelgenerator/internal/ModelPrinting.qll index 0ab92f7032b4..fc1e0113d1d0 100644 --- a/shared/mad/codeql/mad/modelgenerator/internal/ModelPrinting.qll +++ b/shared/mad/codeql/mad/modelgenerator/internal/ModelPrinting.qll @@ -16,7 +16,7 @@ signature module ModelPrintingLangSig { } module ModelPrintingImpl { - signature module ModelPrintingSig { + signature module ModelPrintingSummarySig { /** * The class of APIs relevant for model generation. */ @@ -24,22 +24,32 @@ module ModelPrintingImpl { Lang::Callable lift(); } - class SourceOrSinkApi extends Lang::Callable; - /** * Gets the string representation of the provenance of the models. */ string getProvenance(); } - module ModelPrinting { + signature module ModelPrintingSourceOrSinkSig { /** - * Computes the first columns for MaD rows used for summaries, sources and sinks. + * The class of APIs relevant for model generation. */ - private string asPartialModel(Lang::Callable api) { - result = strictconcat(int i | | Lang::partialModelRow(api, i), ";" order by i) + ";" - } + class SourceOrSinkApi extends Lang::Callable; + + /** + * Gets the string representation of the provenance of the models. + */ + string getProvenance(); + } + + /** + * Computes the first columns for MaD rows used for summaries, sources and sinks. + */ + private string asPartialModel(Lang::Callable api) { + result = strictconcat(int i | | Lang::partialModelRow(api, i), ";" order by i) + ";" + } + module ModelPrintingSummary { /** * Computes the first columns for neutral MaD rows. */ @@ -106,7 +116,9 @@ module ModelPrintingImpl { preservesValue = false and result = asSummaryModel(api, input, output, "taint", lift) } + } + module ModelPrintingSourceOrSink { /** * Gets the sink model for `api` with `input` and `kind`. */ From bb6530fcf85e47c696c13f02a3b1f00652d3ff04 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 24 Apr 2025 16:12:01 +0200 Subject: [PATCH 153/336] Shared: Make the summary, source and sink model generation a parameterized module. --- .../internal/ModelGeneratorImpl.qll | 1481 +++++++++-------- 1 file changed, 773 insertions(+), 708 deletions(-) diff --git a/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll b/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll index 59f53c2b1c90..d981ef151fd7 100644 --- a/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll +++ b/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll @@ -15,7 +15,7 @@ private import ModelPrinting /** * Provides language-specific model generator parameters. */ -signature module ModelGeneratorInputSig Lang> { +signature module ModelGeneratorCommonInputSig Lang> { /** * A Type. */ @@ -49,52 +49,6 @@ signature module ModelGeneratorInputSig /** Gets the enclosing callable of `node`. */ Callable getEnclosingCallable(NodeExtended node); - /** - * Gets the enclosing callable of `node`, when considered as an expression. - */ - Callable getAsExprEnclosingCallable(NodeExtended node); - - /** Gets the parameter corresponding to this node, if any. */ - Parameter asParameter(NodeExtended n); - - /** - * A class of callables that are potentially relevant for generating summary or - * neutral models. - * - * In the Standard library and 3rd party libraries it is the callables (or callables that have a - * super implementation) that can be called from outside the library itself. - */ - class SummaryTargetApi extends Callable { - /** - * Gets the callable that a model will be lifted to. - * - * The lifted callable is relevant in terms of model - * generation (this is ensured by `liftedImpl`). - */ - Callable lift(); - - /** - * Holds if `this` is relevant in terms of model generation. - */ - predicate isRelevant(); - } - - /** - * A class of callables that are potentially relevant for generating source or - * sink models. - */ - class SourceOrSinkTargetApi extends Callable; - - /** - * A class of callables that are potentially relevant for generating source models. - */ - class SourceTargetApi extends SourceOrSinkTargetApi; - - /** - * A class of callables that are potentially relevant for generating sink models. - */ - class SinkTargetApi extends SourceOrSinkTargetApi; - /** * An instance parameter node. */ @@ -113,22 +67,6 @@ signature module ModelGeneratorInputSig */ Type getUnderlyingContentType(Lang::ContentSet c); - /** - * Gets the MaD string representation of the qualifier. - */ - string qualifierString(); - - /** - * Gets the MaD string representation of the parameter `p`. - */ - string parameterAccess(Parameter p); - - /** - * Gets the MaD string representation of the parameter `p` - * when used in content flow. - */ - string parameterContentAccess(Parameter p); - /** * Gets the MaD string representation of return through parameter at position * `pos` of callable `c`. @@ -154,69 +92,26 @@ signature module ModelGeneratorInputSig predicate isOwnInstanceAccessNode(Lang::ReturnNode node); /** - * Holds if `node` is a sanitizer for sink model construction. - */ - predicate sinkModelSanitizer(Lang::Node node); - - /** - * Holds if `source` is an api entrypoint relevant for creating sink models. - */ - predicate apiSource(Lang::Node source); - - /** - * Gets the MaD input string representation of `source`. - */ - string getInputArgument(Lang::Node source); - - /** - * Holds if it is not relevant to generate a source model for `api`, even - * if flow is detected from a node within `source` to a sink within `api`. + * Gets the MaD string representation of the parameter `p`. */ - bindingset[sourceEnclosing, api] - predicate irrelevantSourceSinkApi(Callable sourceEnclosing, SourceTargetApi api); + string parameterAccess(Parameter p); /** - * Holds if `kind` is a relevant sink kind for creating sink models. + * Gets the MaD string representation of the parameter `p` + * when used in content flow. */ - bindingset[kind] - predicate isRelevantSinkKind(string kind); + string parameterContentAccess(Parameter p); /** - * Holds if `kind` is a relevant source kind for creating source models. + * Gets the MaD string representation of the qualifier. */ - bindingset[kind] - predicate isRelevantSourceKind(string kind); + string qualifierString(); /** * Holds if the the content `c` is a container. */ predicate containerContent(Lang::ContentSet c); - /** - * Holds if there is a taint step from `node1` to `node2` in content flow. - */ - predicate isAdditionalContentFlowStep(Lang::Node nodeFrom, Lang::Node nodeTo); - - /** - * Holds if the content set `c` is field like. - */ - predicate isField(Lang::ContentSet c); - - /** - * Holds if the content set `c` is callback like. - */ - predicate isCallback(Lang::ContentSet c); - - /** - * Gets the MaD synthetic name string representation for the content set `c`, if any. - */ - string getSyntheticName(Lang::ContentSet c); - - /** - * Gets the MaD string representation of the content set `c`. - */ - string printContent(Lang::ContentSet c); - /** * Gets the parameter position of the return kind, if any. */ @@ -230,22 +125,6 @@ signature module ModelGeneratorInputSig */ default string getReturnValueString(Lang::ReturnKind kind) { result = "ReturnValue" } - /** - * Holds if it is irrelevant to generate models for `api` based on data flow analysis. - * - * This serves as an extra filter for the `relevant` predicate. - */ - predicate isUninterestingForDataFlowModels(Callable api); - - /** - * Holds if it is irrelevant to generate models for `api` based on the heuristic - * (non-content) flow analysis. - * - * This serves as an extra filter for the `relevant` - * and `isUninterestingForDataFlowModels` predicates. - */ - predicate isUninterestingForHeuristicDataFlowModels(Callable api); - /** * Gets the string representation for the `i`th column in the MaD row for `api`. */ @@ -255,23 +134,14 @@ signature module ModelGeneratorInputSig * Gets the string representation for the `i`th column in the neutral MaD row for `api`. */ string partialNeutralModelRow(Callable api, int i); - - /** - * Holds if `node` is specified as a source with the given kind in a MaD flow - * model. - */ - predicate sourceNode(Lang::Node node, string kind); - - /** - * Holds if `node` is specified as a sink with the given kind in a MaD flow - * model. - */ - predicate sinkNode(Lang::Node node, string kind); } -module MakeModelGenerator< +/** + * Make a factory for constructing different model generators. + */ +module MakeModelGeneratorFactory< LocationSig Location, InputSig Lang, Tt::InputSig TaintLang, - ModelGeneratorInputSig ModelGeneratorInput> + ModelGeneratorCommonInputSig ModelGeneratorInput> { private module DataFlow { import Lang @@ -338,16 +208,6 @@ module MakeModelGenerator< } } - final private class SummaryTargetApiFinal = SummaryTargetApi; - - class DataFlowSummaryTargetApi extends SummaryTargetApiFinal { - DataFlowSummaryTargetApi() { not isUninterestingForDataFlowModels(this) } - } - - class DataFlowSourceTargetApi = SourceTargetApi; - - class DataFlowSinkTargetApi = SinkTargetApi; - /** * Holds if `c` is a relevant content kind, where the underlying type is relevant. */ @@ -365,721 +225,926 @@ module MakeModelGenerator< containerContent(c) } + private string getOutput(ReturnNodeExt node) { + result = PrintReturnNodeExt::getOutput(node) + } + /** - * Provides classes and predicates related to capturing models - * based on heuristic data flow. + * Provides language-specific summary model generator parameters. */ - module Heuristic { - private module ModelPrintingSummaryInput implements Printing::ModelPrintingSummarySig { - class SummaryApi = DataFlowSummaryTargetApi; + signature module SummaryModelGeneratorInputSig { + /** + * A class of callables that are potentially relevant for generating summary or + * neutral models. + * + * In the Standard library and 3rd party libraries it is the callables (or callables that have a + * super implementation) that can be called from outside the library itself. + */ + class SummaryTargetApi extends Callable { + /** + * Gets the callable that a model will be lifted to. + * + * The lifted callable is relevant in terms of model + * generation (this is ensured by `liftedImpl`). + */ + Callable lift(); - string getProvenance() { result = "df-generated" } + /** + * Holds if `this` is relevant in terms of model generation. + */ + predicate isRelevant(); } - module ModelPrintingSummary = Printing::ModelPrintingSummary; + /** + * Gets the enclosing callable of `node`, when considered as an expression. + */ + Callable getAsExprEnclosingCallable(NodeExtended node); - private module ModelPrintingSourceOrSinkInput implements Printing::ModelPrintingSourceOrSinkSig { - class SourceOrSinkApi = SourceOrSinkTargetApi; + /** + * Gets the parameter corresponding to this node, if any. + */ + Parameter asParameter(NodeExtended n); - string getProvenance() { result = "df-generated" } - } + /** + * Holds if there is a taint step from `node1` to `node2` in content flow. + */ + predicate isAdditionalContentFlowStep(Lang::Node nodeFrom, Lang::Node nodeTo); - private string getOutput(ReturnNodeExt node) { - result = PrintReturnNodeExt::getOutput(node) - } + /** + * Holds if the content set `c` is field like. + */ + predicate isField(Lang::ContentSet c); - private module ModelPrintingSourceOrSink = - Printing::ModelPrintingSourceOrSink; + /** + * Holds if the content set `c` is callback like. + */ + predicate isCallback(Lang::ContentSet c); /** - * Holds if data can flow from `node1` to `node2` either via a read or a write of an intermediate field `f`. + * Gets the MaD synthetic name string representation for the content set `c`, if any. */ - private predicate isRelevantTaintStep(DataFlow::Node node1, DataFlow::Node node2) { - exists(DataFlow::ContentSet f | - DataFlow::readStep(node1, f, node2) and - // Partially restrict the content types used for intermediate steps. - (not exists(getUnderlyingContentType(f)) or isRelevantTypeInContent(f)) - ) - or - exists(DataFlow::ContentSet f | DataFlow::storeStep(node1, f, node2) | containerContent(f)) - } + string getSyntheticName(Lang::ContentSet c); /** - * Gets the MaD string representation of the parameter node `p`. + * Gets the MaD string representation of the content set `c`. */ - string parameterNodeAsInput(DataFlow::ParameterNode p) { - result = parameterAccess(asParameter(p)) - or - result = qualifierString() and p instanceof InstanceParameterNode - } + string printContent(Lang::ContentSet c); /** - * Gets the MaD input string representation of `source`. + * Holds if it is irrelevant to generate models for `api` based on data flow analysis. + * + * This serves as an extra filter for the `relevant` predicate. */ - private string asInputArgument(NodeExtended source) { result = getInputArgument(source) } + predicate isUninterestingForDataFlowModels(Callable api); /** - * Gets the summary model of `api`, if it follows the `fluent` programming pattern (returns `this`). + * Holds if it is irrelevant to generate models for `api` based on the heuristic + * (non-content) flow analysis. + * + * This serves as an extra filter for the `relevant` + * and `isUninterestingForDataFlowModels` predicates. */ - private string captureQualifierFlow(DataFlowSummaryTargetApi api) { - exists(ReturnNodeExt ret | - api = returnNodeEnclosingCallable(ret) and - isOwnInstanceAccessNode(ret) - ) and - result = ModelPrintingSummary::asLiftedValueModel(api, qualifierString(), "ReturnValue") - } + predicate isUninterestingForHeuristicDataFlowModels(Callable api); + } - private int accessPathLimit0() { result = 2 } + /** + * Make a summary model generator. + */ + module MakeSummaryModelGenerator { + private import SummaryModelGeneratorInput - private newtype TTaintState = - TTaintRead(int n) { n in [0 .. accessPathLimit0()] } or - TTaintStore(int n) { n in [1 .. accessPathLimit0()] } + final private class SummaryTargetApiFinal = SummaryTargetApi; - abstract private class TaintState extends TTaintState { - abstract string toString(); + class DataFlowSummaryTargetApi extends SummaryTargetApiFinal { + DataFlowSummaryTargetApi() { not isUninterestingForDataFlowModels(this) } } /** - * A FlowState representing a tainted read. + * Provides classes and predicates related to capturing summary models + * based on heuristic data flow. */ - private class TaintRead extends TaintState, TTaintRead { - private int step; + module Heuristic { + private module ModelPrintingSummaryInput implements Printing::ModelPrintingSummarySig { + class SummaryApi = DataFlowSummaryTargetApi; + + string getProvenance() { result = "df-generated" } + } + + module ModelPrintingSummary = Printing::ModelPrintingSummary; - TaintRead() { this = TTaintRead(step) } + /** + * Gets the MaD string representation of the parameter node `p`. + */ + string parameterNodeAsInput(DataFlow::ParameterNode p) { + result = parameterAccess(asParameter(p)) + or + result = qualifierString() and p instanceof InstanceParameterNode + } /** - * Gets the flow state step number. + * Gets the summary model of `api`, if it follows the `fluent` programming pattern (returns `this`). */ - int getStep() { result = step } + private string captureQualifierFlow(DataFlowSummaryTargetApi api) { + exists(ReturnNodeExt ret | + api = returnNodeEnclosingCallable(ret) and + isOwnInstanceAccessNode(ret) + ) and + result = ModelPrintingSummary::asLiftedValueModel(api, qualifierString(), "ReturnValue") + } - override string toString() { result = "TaintRead(" + step + ")" } - } + private int accessPathLimit0() { result = 2 } - /** - * A FlowState representing a tainted write. - */ - private class TaintStore extends TaintState, TTaintStore { - private int step; + private newtype TTaintState = + TTaintRead(int n) { n in [0 .. accessPathLimit0()] } or + TTaintStore(int n) { n in [1 .. accessPathLimit0()] } - TaintStore() { this = TTaintStore(step) } + abstract private class TaintState extends TTaintState { + abstract string toString(); + } /** - * Gets the flow state step number. + * A FlowState representing a tainted read. */ - int getStep() { result = step } + private class TaintRead extends TaintState, TTaintRead { + private int step; - override string toString() { result = "TaintStore(" + step + ")" } - } + TaintRead() { this = TTaintRead(step) } - /** - * A data flow configuration for tracking flow through APIs. - * The sources are the parameters of an API and the sinks are the return values (excluding `this`) and parameters. - * - * This can be used to generate Flow summaries for APIs from parameter to return. - */ - private module PropagateFlowConfig implements DataFlow::StateConfigSig { - class FlowState = TaintState; - - predicate isSource(DataFlow::Node source, FlowState state) { - source instanceof DataFlow::ParameterNode and - exists(Callable c | - c = getEnclosingCallable(source) and - c instanceof DataFlowSummaryTargetApi and - not isUninterestingForHeuristicDataFlowModels(c) - ) and - state.(TaintRead).getStep() = 0 + /** + * Gets the flow state step number. + */ + int getStep() { result = step } + + override string toString() { result = "TaintRead(" + step + ")" } } - predicate isSink(DataFlow::Node sink, FlowState state) { - // Sinks are provided by `isSink/1` - none() + /** + * A FlowState representing a tainted write. + */ + private class TaintStore extends TaintState, TTaintStore { + private int step; + + TaintStore() { this = TTaintStore(step) } + + /** + * Gets the flow state step number. + */ + int getStep() { result = step } + + override string toString() { result = "TaintStore(" + step + ")" } } - predicate isSink(DataFlow::Node sink) { - sink instanceof ReturnNodeExt and - not isOwnInstanceAccessNode(sink) and - not exists(captureQualifierFlow(getAsExprEnclosingCallable(sink))) + /** + * A data flow configuration for tracking flow through APIs. + * The sources are the parameters of an API and the sinks are the return values (excluding `this`) and parameters. + * + * This can be used to generate Flow summaries for APIs from parameter to return. + */ + private module PropagateFlowConfig implements DataFlow::StateConfigSig { + class FlowState = TaintState; + + predicate isSource(DataFlow::Node source, FlowState state) { + source instanceof DataFlow::ParameterNode and + exists(Callable c | + c = getEnclosingCallable(source) and + c instanceof DataFlowSummaryTargetApi and + not isUninterestingForHeuristicDataFlowModels(c) + ) and + state.(TaintRead).getStep() = 0 + } + + predicate isSink(DataFlow::Node sink, FlowState state) { + // Sinks are provided by `isSink/1` + none() + } + + predicate isSink(DataFlow::Node sink) { + sink instanceof ReturnNodeExt and + not isOwnInstanceAccessNode(sink) and + not exists(captureQualifierFlow(getAsExprEnclosingCallable(sink))) + } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 + ) { + exists(DataFlow::NodeEx n1, DataFlow::NodeEx n2, DataFlow::ContentSet c | + node1 = n1.asNode() and + node2 = n2.asNode() and + DataFlow::storeEx(n1, c.getAStoreContent(), n2, _, _) and + isRelevantContent0(c) and + ( + state1 instanceof TaintRead and state2.(TaintStore).getStep() = 1 + or + state1.(TaintStore).getStep() + 1 = state2.(TaintStore).getStep() + ) + ) + or + exists(DataFlow::ContentSet c | + DataFlow::readStep(node1, c, node2) and + isRelevantContent0(c) and + state1.(TaintRead).getStep() + 1 = state2.(TaintRead).getStep() + ) + } + + predicate isBarrier(DataFlow::Node n) { + exists(Type t | t = n.(NodeExtended).getType() and not isRelevantType(t)) + } + + DataFlow::FlowFeature getAFeature() { + result instanceof DataFlow::FeatureEqualSourceSinkCallContext + } } - predicate isAdditionalFlowStep( - DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 + module PropagateFlow = TaintTracking::GlobalWithState; + + /** + * Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter. + */ + string captureThroughFlow0( + DataFlowSummaryTargetApi api, DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt ) { - exists(DataFlow::NodeEx n1, DataFlow::NodeEx n2, DataFlow::ContentSet c | - node1 = n1.asNode() and - node2 = n2.asNode() and - DataFlow::storeEx(n1, c.getAStoreContent(), n2, _, _) and - isRelevantContent0(c) and - ( - state1 instanceof TaintRead and state2.(TaintStore).getStep() = 1 - or - state1.(TaintStore).getStep() + 1 = state2.(TaintStore).getStep() - ) - ) - or - exists(DataFlow::ContentSet c | - DataFlow::readStep(node1, c, node2) and - isRelevantContent0(c) and - state1.(TaintRead).getStep() + 1 = state2.(TaintRead).getStep() + exists(string input, string output | + getEnclosingCallable(p) = api and + getEnclosingCallable(returnNodeExt) = api and + input = parameterNodeAsInput(p) and + output = getOutput(returnNodeExt) and + input != output and + result = ModelPrintingSummary::asLiftedTaintModel(api, input, output) ) } - predicate isBarrier(DataFlow::Node n) { - exists(Type t | t = n.(NodeExtended).getType() and not isRelevantType(t)) + /** + * Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter. + */ + private string captureThroughFlow(DataFlowSummaryTargetApi api) { + exists(DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt | + PropagateFlow::flow(p, returnNodeExt) and + result = captureThroughFlow0(api, p, returnNodeExt) + ) } - DataFlow::FlowFeature getAFeature() { - result instanceof DataFlow::FeatureEqualSourceSinkCallContext + /** + * Gets the summary model(s) of `api`, if there is flow from parameters to the + * return value or parameter or if `api` is a fluent API. + */ + string captureFlow(DataFlowSummaryTargetApi api) { + result = captureQualifierFlow(api) or + result = captureThroughFlow(api) } - } - module PropagateFlow = TaintTracking::GlobalWithState; - - /** - * Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter. - */ - string captureThroughFlow0( - DataFlowSummaryTargetApi api, DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt - ) { - exists(string input, string output | - getEnclosingCallable(p) = api and - getEnclosingCallable(returnNodeExt) = api and - input = parameterNodeAsInput(p) and - output = getOutput(returnNodeExt) and - input != output and - result = ModelPrintingSummary::asLiftedTaintModel(api, input, output) - ) + /** + * Gets the neutral summary model for `api`, if any. + * A neutral summary model is generated, if we are not generating + * a summary model that applies to `api`. + */ + string captureNoFlow(DataFlowSummaryTargetApi api) { + not exists(DataFlowSummaryTargetApi api0 | + exists(captureFlow(api0)) and api0.lift() = api.lift() + ) and + api.isRelevant() and + result = ModelPrintingSummary::asNeutralSummaryModel(api) + } } /** - * Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter. + * Provides classes and predicates related to capturing summary models + * based on content data flow. */ - private string captureThroughFlow(DataFlowSummaryTargetApi api) { - exists(DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt | - PropagateFlow::flow(p, returnNodeExt) and - result = captureThroughFlow0(api, p, returnNodeExt) - ) - } + module ContentSensitive { + private import MakeImplContentDataFlow as ContentDataFlow - /** - * Gets the summary model(s) of `api`, if there is flow from parameters to the - * return value or parameter or if `api` is a fluent API. - */ - string captureFlow(DataFlowSummaryTargetApi api) { - result = captureQualifierFlow(api) or - result = captureThroughFlow(api) - } + private module PropagateContentFlowConfig implements ContentDataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source instanceof DataFlow::ParameterNode and + getEnclosingCallable(source) instanceof DataFlowSummaryTargetApi + } - /** - * Gets the neutral summary model for `api`, if any. - * A neutral summary model is generated, if we are not generating - * a summary model that applies to `api`. - */ - string captureNoFlow(DataFlowSummaryTargetApi api) { - not exists(DataFlowSummaryTargetApi api0 | - exists(captureFlow(api0)) and api0.lift() = api.lift() - ) and - api.isRelevant() and - result = ModelPrintingSummary::asNeutralSummaryModel(api) - } + predicate isSink(DataFlow::Node sink) { + sink instanceof ReturnNodeExt and + getEnclosingCallable(sink) instanceof DataFlowSummaryTargetApi + } - /** - * A data flow configuration used for finding new sources. - * The sources are the already known existing sources and the sinks are the API return nodes. - * - * This can be used to generate Source summaries for an API, if the API expose an already known source - * via its return (then the API itself becomes a source). - */ - module PropagateFromSourceConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { - exists(string kind | - isRelevantSourceKind(kind) and - sourceNode(source, kind) - ) - } + predicate isAdditionalFlowStep = isAdditionalContentFlowStep/2; - predicate isSink(DataFlow::Node sink) { - sink instanceof ReturnNodeExt and - getEnclosingCallable(sink) instanceof DataFlowSourceTargetApi - } + predicate isBarrier(DataFlow::Node n) { + exists(Type t | t = n.(NodeExtended).getType() and not isRelevantType(t)) + } - DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSinkCallContext } + int accessPathLimit() { result = 2 } - predicate isBarrier(DataFlow::Node n) { - exists(Type t | t = n.(NodeExtended).getType() and not isRelevantType(t)) - } + predicate isRelevantContent(DataFlow::ContentSet s) { isRelevantContent0(s) } - predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isRelevantTaintStep(node1, node2) + DataFlow::FlowFeature getAFeature() { + result instanceof DataFlow::FeatureEqualSourceSinkCallContext + } } - } - private module PropagateFromSource = TaintTracking::Global; + private module PropagateContentFlow = ContentDataFlow::Global; - /** - * Gets the source model(s) of `api`, if there is flow from an existing known source to the return of `api`. - */ - string captureSource(DataFlowSourceTargetApi api) { - exists(NodeExtended source, ReturnNodeExt sink, string kind | - PropagateFromSource::flow(source, sink) and - sourceNode(source, kind) and - api = getEnclosingCallable(sink) and - not irrelevantSourceSinkApi(getEnclosingCallable(source), api) and - result = ModelPrintingSourceOrSink::asSourceModel(api, getOutput(sink), kind) - ) - } + private module ContentModelPrintingInput implements Printing::ModelPrintingSummarySig { + class SummaryApi = DataFlowSummaryTargetApi; - /** - * A data flow configuration used for finding new sinks. - * The sources are the parameters of the API and the fields of the enclosing type. - * - * This can be used to generate Sink summaries for APIs, if the API propagates a parameter (or enclosing type field) - * into an existing known sink (then the API itself becomes a sink). - */ - module PropagateToSinkConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { - apiSource(source) and - getEnclosingCallable(source) instanceof DataFlowSinkTargetApi + string getProvenance() { result = "dfc-generated" } } - predicate isSink(DataFlow::Node sink) { - exists(string kind | isRelevantSinkKind(kind) and sinkNode(sink, kind)) + private module ContentModelPrinting = + Printing::ModelPrintingSummary; + + private string getContentOutput(ReturnNodeExt node) { + result = PrintReturnNodeExt::getOutput(node) } - predicate isBarrier(DataFlow::Node node) { - exists(Type t | t = node.(NodeExtended).getType() and not isRelevantType(t)) + /** + * Gets the MaD string representation of the parameter `p` + * when used in content flow. + */ + private string parameterNodeAsContentInput(DataFlow::ParameterNode p) { + result = parameterContentAccess(asParameter(p)) or - sinkModelSanitizer(node) + result = qualifierString() and p instanceof InstanceParameterNode } - DataFlow::FlowFeature getAFeature() { - result instanceof DataFlow::FeatureHasSourceCallContext + private string getContent(PropagateContentFlow::AccessPath ap, int i) { + result = "." + printContent(ap.getAtIndex(i)) } - predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - isRelevantTaintStep(node1, node2) + /** + * Gets the MaD string representation of a store step access path. + */ + private string printStoreAccessPath(PropagateContentFlow::AccessPath ap) { + result = concat(int i | | getContent(ap, i), "" order by i) } - } - private module PropagateToSink = TaintTracking::Global; + /** + * Gets the MaD string representation of a read step access path. + */ + private string printReadAccessPath(PropagateContentFlow::AccessPath ap) { + result = concat(int i | | getContent(ap, i), "" order by i desc) + } - /** - * Gets the sink model(s) of `api`, if there is flow from a parameter to an existing known sink. - */ - string captureSink(DataFlowSinkTargetApi api) { - exists(NodeExtended src, NodeExtended sink, string kind | - PropagateToSink::flow(src, sink) and - sinkNode(sink, kind) and - api = getEnclosingCallable(src) and - result = ModelPrintingSourceOrSink::asSinkModel(api, asInputArgument(src), kind) - ) - } - } + /** + * Holds if the access path `ap` contains a field or synthetic field access. + */ + private predicate mentionsField(PropagateContentFlow::AccessPath ap) { + isField(ap.getAtIndex(_)) + } - /** - * Provides classes and predicates related to capturing summary models - * based on content data flow. - */ - module ContentSensitive { - private import MakeImplContentDataFlow as ContentDataFlow + /** + * Holds if this access path `ap` mentions a callback. + */ + private predicate mentionsCallback(PropagateContentFlow::AccessPath ap) { + isCallback(ap.getAtIndex(_)) + } - private module PropagateContentFlowConfig implements ContentDataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { - source instanceof DataFlow::ParameterNode and - getEnclosingCallable(source) instanceof DataFlowSummaryTargetApi + /** + * Holds if the access path `ap` is not a parameter or returnvalue of a callback + * stored in a field. + * + * That is, we currently don't include summaries that rely on parameters or return values + * of callbacks stored in fields. + */ + private predicate validateAccessPath(PropagateContentFlow::AccessPath ap) { + not (mentionsField(ap) and mentionsCallback(ap)) } - predicate isSink(DataFlow::Node sink) { - sink instanceof ReturnNodeExt and - getEnclosingCallable(sink) instanceof DataFlowSummaryTargetApi + private predicate apiFlow( + DataFlowSummaryTargetApi api, DataFlow::ParameterNode p, + PropagateContentFlow::AccessPath reads, ReturnNodeExt returnNodeExt, + PropagateContentFlow::AccessPath stores, boolean preservesValue + ) { + PropagateContentFlow::flow(p, reads, returnNodeExt, stores, preservesValue) and + getEnclosingCallable(returnNodeExt) = api and + getEnclosingCallable(p) = api } - predicate isAdditionalFlowStep = isAdditionalContentFlowStep/2; + /** + * A class of APIs relevant for modeling using content flow. + * The following heuristic is applied: + * Content flow is only relevant for an API on a parameter, if + * #content flow from parameter <= 3 + * If an API produces more content flow on a parameter, it is likely that + * 1. Types are not sufficiently constrained on the parameter leading to a combinatorial + * explosion in dispatch and thus in the generated summaries. + * 2. It is a reasonable approximation to use the heuristic based flow + * detection instead, as reads and stores would use a significant + * part of an objects internal state. + */ + private class ContentDataFlowSummaryTargetApi extends DataFlowSummaryTargetApi { + private DataFlow::ParameterNode parameter; + + ContentDataFlowSummaryTargetApi() { + strictcount(string input, string output | + exists( + PropagateContentFlow::AccessPath reads, ReturnNodeExt returnNodeExt, + PropagateContentFlow::AccessPath stores + | + apiFlow(this, parameter, reads, returnNodeExt, stores, _) and + input = parameterNodeAsContentInput(parameter) + printReadAccessPath(reads) and + output = getContentOutput(returnNodeExt) + printStoreAccessPath(stores) + ) + ) <= 3 + } + + /** + * Gets a parameter node of `this` api, where there are less than 3 possible models, if any. + */ + DataFlow::ParameterNode getARelevantParameterNode() { result = parameter } + } - predicate isBarrier(DataFlow::Node n) { - exists(Type t | t = n.(NodeExtended).getType() and not isRelevantType(t)) + pragma[nomagic] + private predicate apiContentFlow( + ContentDataFlowSummaryTargetApi api, DataFlow::ParameterNode p, + PropagateContentFlow::AccessPath reads, ReturnNodeExt returnNodeExt, + PropagateContentFlow::AccessPath stores, boolean preservesValue + ) { + PropagateContentFlow::flow(p, reads, returnNodeExt, stores, preservesValue) and + getEnclosingCallable(returnNodeExt) = api and + getEnclosingCallable(p) = api and + p = api.getARelevantParameterNode() } - int accessPathLimit() { result = 2 } + /** + * Holds if any of the content sets in `path` translates into a synthetic field. + */ + private predicate hasSyntheticContent(PropagateContentFlow::AccessPath path) { + exists(getSyntheticName(path.getAtIndex(_))) + } - predicate isRelevantContent(DataFlow::ContentSet s) { isRelevantContent0(s) } + private string getHashAtIndex(PropagateContentFlow::AccessPath ap, int i) { + result = getSyntheticName(ap.getAtIndex(i)) + } - DataFlow::FlowFeature getAFeature() { - result instanceof DataFlow::FeatureEqualSourceSinkCallContext + private string getReversedHash(PropagateContentFlow::AccessPath ap) { + result = strictconcat(int i | | getHashAtIndex(ap, i), "." order by i desc) } - } - private module PropagateContentFlow = ContentDataFlow::Global; + private string getHash(PropagateContentFlow::AccessPath ap) { + result = strictconcat(int i | | getHashAtIndex(ap, i), "." order by i) + } - private module ContentModelPrintingInput implements Printing::ModelPrintingSummarySig { - class SummaryApi = DataFlowSummaryTargetApi; + /** + * Gets all access paths that contain the synthetic fields + * from `ap` in reverse order (if `ap` contains at least one synthetic field). + * These are the possible candidates for synthetic path continuations. + */ + private PropagateContentFlow::AccessPath getSyntheticPathCandidate( + PropagateContentFlow::AccessPath ap + ) { + getHash(ap) = getReversedHash(result) + } - string getProvenance() { result = "dfc-generated" } - } + /** + * A module containing predicates for validating access paths containing content sets + * that translates into synthetic fields, when used for generated summary models. + */ + private module AccessPathSyntheticValidation { + /** + * Holds if there exists an API that has content flow from `read` (on type `t1`) + * to `store` (on type `t2`). + */ + private predicate step( + Type t1, PropagateContentFlow::AccessPath read, Type t2, + PropagateContentFlow::AccessPath store + ) { + exists(DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt | + p.(NodeExtended).getType() = t1 and + returnNodeExt.getType() = t2 and + apiContentFlow(_, p, read, returnNodeExt, store, _) + ) + } + + /** + * Holds if there exists an API that has content flow from `read` (on type `t1`) + * to `store` (on type `t2`), where `read` does not have synthetic content and `store` does. + * + * Step A -> Synth. + */ + private predicate synthPathEntry( + Type t1, PropagateContentFlow::AccessPath read, Type t2, + PropagateContentFlow::AccessPath store + ) { + not hasSyntheticContent(read) and + hasSyntheticContent(store) and + step(t1, read, t2, store) + } + + /** + * Holds if there exists an API that has content flow from `read` (on type `t1`) + * to `store` (on type `t2`), where `read` has synthetic content + * and `store` does not. + * + * Step Synth -> A. + */ + private predicate synthPathExit( + Type t1, PropagateContentFlow::AccessPath read, Type t2, + PropagateContentFlow::AccessPath store + ) { + hasSyntheticContent(read) and + not hasSyntheticContent(store) and + step(t1, read, t2, store) + } + + /** + * Holds if there exists a path of steps from `read` to an exit. + * + * read ->* Synth -> A + */ + private predicate reachesSynthExit(Type t, PropagateContentFlow::AccessPath read) { + synthPathExit(t, read, _, _) + or + hasSyntheticContent(read) and + exists(PropagateContentFlow::AccessPath mid, Type midType | + hasSyntheticContent(mid) and + step(t, read, midType, mid) and + reachesSynthExit(midType, getSyntheticPathCandidate(mid)) + ) + } + + /** + * Holds if there exists a path of steps from an entry to `store`. + * + * A -> Synth ->* store + */ + private predicate synthEntryReaches(Type t, PropagateContentFlow::AccessPath store) { + synthPathEntry(_, _, t, store) + or + hasSyntheticContent(store) and + exists(PropagateContentFlow::AccessPath mid, Type midType | + hasSyntheticContent(mid) and + step(midType, mid, t, store) and + synthEntryReaches(midType, getSyntheticPathCandidate(mid)) + ) + } + + /** + * Holds if at least one of the access paths `read` (on type `t1`) and `store` (on type `t2`) + * contain content that will be translated into a synthetic field, when being used in + * a MaD summary model, and if there is a range of APIs, such that + * when chaining their flow access paths, there exists access paths `A` and `B` where + * A ->* read -> store ->* B and where `A` and `B` do not contain content that will + * be translated into a synthetic field. + * + * This is needed because we don't want to include summaries that reads from or + * stores into an "internal" synthetic field. + * + * Example: + * Assume we have a type `t` (in this case `t1` = `t2`) with methods `getX` and + * `setX`, which gets and sets a private field `X` on `t`. + * This would lead to the following content flows + * getX : Argument[this].SyntheticField[t.X] -> ReturnValue. + * setX : Argument[0] -> Argument[this].SyntheticField[t.X] + * As the reads and stores are on synthetic fields we should only make summaries + * if both of these methods exist. + */ + pragma[nomagic] + predicate acceptReadStore( + Type t1, PropagateContentFlow::AccessPath read, Type t2, + PropagateContentFlow::AccessPath store + ) { + synthPathEntry(t1, read, t2, store) and + reachesSynthExit(t2, getSyntheticPathCandidate(store)) + or + exists(PropagateContentFlow::AccessPath store0 | + getSyntheticPathCandidate(store0) = read + | + synthEntryReaches(t1, store0) and synthPathExit(t1, read, t2, store) + or + synthEntryReaches(t1, store0) and + step(t1, read, t2, store) and + reachesSynthExit(t2, getSyntheticPathCandidate(store)) + ) + } + } + + /** + * Holds, if the API `api` has relevant flow from `read` on `p` to `store` on `returnNodeExt`. + * Flow is considered relevant, + * 1. If `read` or `store` do not contain a content set that translates into a synthetic field. + * 2. If `read` or `store` contain a content set that translates into a synthetic field, and if + * the synthetic content is "live" on the relevant declaring type. + */ + private predicate apiRelevantContentFlow( + ContentDataFlowSummaryTargetApi api, DataFlow::ParameterNode p, + PropagateContentFlow::AccessPath read, ReturnNodeExt returnNodeExt, + PropagateContentFlow::AccessPath store, boolean preservesValue + ) { + apiContentFlow(api, p, read, returnNodeExt, store, preservesValue) and + ( + not hasSyntheticContent(read) and not hasSyntheticContent(store) + or + AccessPathSyntheticValidation::acceptReadStore(p.(NodeExtended).getType(), read, + returnNodeExt.getType(), store) + ) + } - private module ContentModelPrinting = Printing::ModelPrintingSummary; + pragma[nomagic] + private predicate captureFlow0( + ContentDataFlowSummaryTargetApi api, string input, string output, boolean preservesValue, + boolean lift + ) { + exists( + DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt, + PropagateContentFlow::AccessPath reads, PropagateContentFlow::AccessPath stores + | + apiRelevantContentFlow(api, p, reads, returnNodeExt, stores, preservesValue) and + input = parameterNodeAsContentInput(p) + printReadAccessPath(reads) and + output = getContentOutput(returnNodeExt) + printStoreAccessPath(stores) and + input != output and + validateAccessPath(reads) and + validateAccessPath(stores) and + ( + if mentionsField(reads) or mentionsField(stores) + then lift = false and api.isRelevant() + else lift = true + ) + ) + } - private string getContentOutput(ReturnNodeExt node) { - result = PrintReturnNodeExt::getOutput(node) + /** + * Gets the content based summary model(s) of the API `api` (if there is flow from a parameter to + * the return value or a parameter). `lift` is true, if the model should be lifted, otherwise false. + * + * Models are lifted to the best type in case the read and store access paths do not + * contain a field or synthetic field access. + */ + string captureFlow(ContentDataFlowSummaryTargetApi api, boolean lift) { + exists(string input, string output, boolean preservesValue | + captureFlow0(api, input, output, _, lift) and + preservesValue = max(boolean p | captureFlow0(api, input, output, p, lift)) and + result = ContentModelPrinting::asModel(api, input, output, preservesValue, lift) + ) + } } /** - * Gets the MaD string representation of the parameter `p` - * when used in content flow. + * Gets the summary model(s) for `api`, if any. `lift` is true if the model is lifted + * otherwise false. + * The following heuristic is applied: + * 1. If content based flow yields at lease one summary for an API, then we use that. + * 2. If content based flow does not yield any summary for an API, then we try and + * generate flow summaries using the heuristic based summary generator. */ - private string parameterNodeAsContentInput(DataFlow::ParameterNode p) { - result = parameterContentAccess(asParameter(p)) + string captureFlow(DataFlowSummaryTargetApi api, boolean lift) { + result = ContentSensitive::captureFlow(api, lift) or - result = qualifierString() and p instanceof InstanceParameterNode - } - - private string getContent(PropagateContentFlow::AccessPath ap, int i) { - result = "." + printContent(ap.getAtIndex(i)) + not exists(DataFlowSummaryTargetApi api0 | + (api0 = api or api.lift() = api0) and + exists(ContentSensitive::captureFlow(api0, false)) + or + api0.lift() = api.lift() and + exists(ContentSensitive::captureFlow(api0, true)) + ) and + result = Heuristic::captureFlow(api) and + lift = true } /** - * Gets the MaD string representation of a store step access path. + * Gets the neutral summary model for `api`, if any. + * A neutral summary model is generated, if we are not generating + * a mixed summary model that applies to `api`. */ - private string printStoreAccessPath(PropagateContentFlow::AccessPath ap) { - result = concat(int i | | getContent(ap, i), "" order by i) + string captureNeutral(DataFlowSummaryTargetApi api) { + not exists(DataFlowSummaryTargetApi api0, boolean lift | + exists(captureFlow(api0, lift)) and + ( + lift = false and + (api0 = api or api0 = api.lift()) + or + lift = true and api0.lift() = api.lift() + ) + ) and + api.isRelevant() and + result = Heuristic::ModelPrintingSummary::asNeutralSummaryModel(api) } + } + + /** + * Holds if data can flow from `node1` to `node2` either via a read or a write of an intermediate field `f`. + */ + private predicate isRelevantTaintStep(DataFlow::Node node1, DataFlow::Node node2) { + exists(DataFlow::ContentSet f | + DataFlow::readStep(node1, f, node2) and + // Partially restrict the content types used for intermediate steps. + (not exists(getUnderlyingContentType(f)) or isRelevantTypeInContent(f)) + ) + or + exists(DataFlow::ContentSet f | DataFlow::storeStep(node1, f, node2) | containerContent(f)) + } + /** + * Provides language-specific source model generator parameters. + */ + signature module SourceModelGeneratorInputSig { /** - * Gets the MaD string representation of a read step access path. + * A class of callables that are potentially relevant for generating source models. */ - private string printReadAccessPath(PropagateContentFlow::AccessPath ap) { - result = concat(int i | | getContent(ap, i), "" order by i desc) - } + class SourceTargetApi extends Callable; /** - * Holds if the access path `ap` contains a field or synthetic field access. + * Holds if it is not relevant to generate a source model for `api`, even + * if flow is detected from a node within `source` to a sink within `api`. */ - private predicate mentionsField(PropagateContentFlow::AccessPath ap) { - isField(ap.getAtIndex(_)) - } + bindingset[sourceEnclosing, api] + predicate irrelevantSourceSinkApi(Callable sourceEnclosing, SourceTargetApi api); /** - * Holds if this access path `ap` mentions a callback. + * Holds if `kind` is a relevant source kind for creating source models. */ - private predicate mentionsCallback(PropagateContentFlow::AccessPath ap) { - isCallback(ap.getAtIndex(_)) - } + bindingset[kind] + predicate isRelevantSourceKind(string kind); /** - * Holds if the access path `ap` is not a parameter or returnvalue of a callback - * stored in a field. - * - * That is, we currently don't include summaries that rely on parameters or return values - * of callbacks stored in fields. + * Holds if `node` is specified as a source with the given kind in a MaD flow + * model. */ - private predicate validateAccessPath(PropagateContentFlow::AccessPath ap) { - not (mentionsField(ap) and mentionsCallback(ap)) - } + predicate sourceNode(Lang::Node node, string kind); + } - private predicate apiFlow( - DataFlowSummaryTargetApi api, DataFlow::ParameterNode p, - PropagateContentFlow::AccessPath reads, ReturnNodeExt returnNodeExt, - PropagateContentFlow::AccessPath stores, boolean preservesValue - ) { - PropagateContentFlow::flow(p, reads, returnNodeExt, stores, preservesValue) and - getEnclosingCallable(returnNodeExt) = api and - getEnclosingCallable(p) = api - } + /** + * Provides language-specific sink model generator parameters. + */ + signature module SinkModelGeneratorInputSig { + /** + * A class of callables that are potentially relevant for generating sink models. + */ + class SinkTargetApi extends Callable; /** - * A class of APIs relevant for modeling using content flow. - * The following heuristic is applied: - * Content flow is only relevant for an API on a parameter, if - * #content flow from parameter <= 3 - * If an API produces more content flow on a parameter, it is likely that - * 1. Types are not sufficiently constrained on the parameter leading to a combinatorial - * explosion in dispatch and thus in the generated summaries. - * 2. It is a reasonable approximation to use the heuristic based flow - * detection instead, as reads and stores would use a significant - * part of an objects internal state. + * Gets the MaD input string representation of `source`. */ - private class ContentDataFlowSummaryTargetApi extends DataFlowSummaryTargetApi { - private DataFlow::ParameterNode parameter; - - ContentDataFlowSummaryTargetApi() { - strictcount(string input, string output | - exists( - PropagateContentFlow::AccessPath reads, ReturnNodeExt returnNodeExt, - PropagateContentFlow::AccessPath stores - | - apiFlow(this, parameter, reads, returnNodeExt, stores, _) and - input = parameterNodeAsContentInput(parameter) + printReadAccessPath(reads) and - output = getContentOutput(returnNodeExt) + printStoreAccessPath(stores) - ) - ) <= 3 - } + string getInputArgument(Lang::Node source); - /** - * Gets a parameter node of `this` api, where there are less than 3 possible models, if any. - */ - DataFlow::ParameterNode getARelevantParameterNode() { result = parameter } - } + /** + * Holds if `node` is a sanitizer for sink model construction. + */ + predicate sinkModelSanitizer(Lang::Node node); - pragma[nomagic] - private predicate apiContentFlow( - ContentDataFlowSummaryTargetApi api, DataFlow::ParameterNode p, - PropagateContentFlow::AccessPath reads, ReturnNodeExt returnNodeExt, - PropagateContentFlow::AccessPath stores, boolean preservesValue - ) { - PropagateContentFlow::flow(p, reads, returnNodeExt, stores, preservesValue) and - getEnclosingCallable(returnNodeExt) = api and - getEnclosingCallable(p) = api and - p = api.getARelevantParameterNode() - } + /** + * Holds if `source` is an api entrypoint relevant for creating sink models. + */ + predicate apiSource(Lang::Node source); /** - * Holds if any of the content sets in `path` translates into a synthetic field. + * Holds if `kind` is a relevant sink kind for creating sink models. */ - private predicate hasSyntheticContent(PropagateContentFlow::AccessPath path) { - exists(getSyntheticName(path.getAtIndex(_))) - } + bindingset[kind] + predicate isRelevantSinkKind(string kind); - private string getHashAtIndex(PropagateContentFlow::AccessPath ap, int i) { - result = getSyntheticName(ap.getAtIndex(i)) - } + /** + * Holds if `node` is specified as a sink with the given kind in a MaD flow + * model. + */ + predicate sinkNode(Lang::Node node, string kind); + } - private string getReversedHash(PropagateContentFlow::AccessPath ap) { - result = strictconcat(int i | | getHashAtIndex(ap, i), "." order by i desc) - } + /** + * Make a source model generator. + */ + module MakeSourceModelGenerator { + private import SourceModelGeneratorInput - private string getHash(PropagateContentFlow::AccessPath ap) { - result = strictconcat(int i | | getHashAtIndex(ap, i), "." order by i) - } + class DataFlowSourceTargetApi = SourceTargetApi; /** - * Gets all access paths that contain the synthetic fields - * from `ap` in reverse order (if `ap` contains at least one synthetic field). - * These are the possible candidates for synthetic path continuations. + * Provides classes and predicates related to capturing source models + * based on heuristic data flow. */ - private PropagateContentFlow::AccessPath getSyntheticPathCandidate( - PropagateContentFlow::AccessPath ap - ) { - getHash(ap) = getReversedHash(result) - } + module Heuristic { + private module ModelPrintingSourceOrSinkInput implements + Printing::ModelPrintingSourceOrSinkSig + { + class SourceOrSinkApi = DataFlowSourceTargetApi; - /** - * A module containing predicates for validating access paths containing content sets - * that translates into synthetic fields, when used for generated summary models. - */ - private module AccessPathSyntheticValidation { - /** - * Holds if there exists an API that has content flow from `read` (on type `t1`) - * to `store` (on type `t2`). - */ - private predicate step( - Type t1, PropagateContentFlow::AccessPath read, Type t2, - PropagateContentFlow::AccessPath store - ) { - exists(DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt | - p.(NodeExtended).getType() = t1 and - returnNodeExt.getType() = t2 and - apiContentFlow(_, p, read, returnNodeExt, store, _) - ) + string getProvenance() { result = "df-generated" } } - /** - * Holds if there exists an API that has content flow from `read` (on type `t1`) - * to `store` (on type `t2`), where `read` does not have synthetic content and `store` does. - * - * Step A -> Synth. - */ - private predicate synthPathEntry( - Type t1, PropagateContentFlow::AccessPath read, Type t2, - PropagateContentFlow::AccessPath store - ) { - not hasSyntheticContent(read) and - hasSyntheticContent(store) and - step(t1, read, t2, store) - } + private module ModelPrintingSourceOrSink = + Printing::ModelPrintingSourceOrSink; /** - * Holds if there exists an API that has content flow from `read` (on type `t1`) - * to `store` (on type `t2`), where `read` has synthetic content - * and `store` does not. + * A data flow configuration used for finding new sources. + * The sources are the already known existing sources and the sinks are the API return nodes. * - * Step Synth -> A. + * This can be used to generate Source summaries for an API, if the API expose an already known source + * via its return (then the API itself becomes a source). */ - private predicate synthPathExit( - Type t1, PropagateContentFlow::AccessPath read, Type t2, - PropagateContentFlow::AccessPath store - ) { - hasSyntheticContent(read) and - not hasSyntheticContent(store) and - step(t1, read, t2, store) + module PropagateFromSourceConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + exists(string kind | + isRelevantSourceKind(kind) and + sourceNode(source, kind) + ) + } + + predicate isSink(DataFlow::Node sink) { + sink instanceof ReturnNodeExt and + getEnclosingCallable(sink) instanceof DataFlowSourceTargetApi + } + + DataFlow::FlowFeature getAFeature() { + result instanceof DataFlow::FeatureHasSinkCallContext + } + + predicate isBarrier(DataFlow::Node n) { + exists(Type t | t = n.(NodeExtended).getType() and not isRelevantType(t)) + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + isRelevantTaintStep(node1, node2) + } } + private module PropagateFromSource = TaintTracking::Global; + /** - * Holds if there exists a path of steps from `read` to an exit. - * - * read ->* Synth -> A + * Gets the source model(s) of `api`, if there is flow from an existing known source to the return of `api`. */ - private predicate reachesSynthExit(Type t, PropagateContentFlow::AccessPath read) { - synthPathExit(t, read, _, _) - or - hasSyntheticContent(read) and - exists(PropagateContentFlow::AccessPath mid, Type midType | - hasSyntheticContent(mid) and - step(t, read, midType, mid) and - reachesSynthExit(midType, getSyntheticPathCandidate(mid)) + string captureSource(DataFlowSourceTargetApi api) { + exists(NodeExtended source, ReturnNodeExt sink, string kind | + PropagateFromSource::flow(source, sink) and + sourceNode(source, kind) and + api = getEnclosingCallable(sink) and + not irrelevantSourceSinkApi(getEnclosingCallable(source), api) and + result = ModelPrintingSourceOrSink::asSourceModel(api, getOutput(sink), kind) ) } + } + } + + /** + * Make a sink model generator. + */ + module MakeSinkModelGenerator { + private import SinkModelGeneratorInput + + class DataFlowSinkTargetApi = SinkTargetApi; + + /** + * Provides classes and predicates related to capturing sink models + * based on heuristic data flow. + */ + module Heuristic { + private module ModelPrintingSourceOrSinkInput implements + Printing::ModelPrintingSourceOrSinkSig + { + class SourceOrSinkApi = DataFlowSinkTargetApi; + + string getProvenance() { result = "df-generated" } + } + + private module ModelPrintingSourceOrSink = + Printing::ModelPrintingSourceOrSink; /** - * Holds if there exists a path of steps from an entry to `store`. - * - * A -> Synth ->* store + * Gets the MaD input string representation of `source`. */ - private predicate synthEntryReaches(Type t, PropagateContentFlow::AccessPath store) { - synthPathEntry(_, _, t, store) - or - hasSyntheticContent(store) and - exists(PropagateContentFlow::AccessPath mid, Type midType | - hasSyntheticContent(mid) and - step(midType, mid, t, store) and - synthEntryReaches(midType, getSyntheticPathCandidate(mid)) - ) - } + private string asInputArgument(NodeExtended source) { result = getInputArgument(source) } /** - * Holds if at least one of the access paths `read` (on type `t1`) and `store` (on type `t2`) - * contain content that will be translated into a synthetic field, when being used in - * a MaD summary model, and if there is a range of APIs, such that - * when chaining their flow access paths, there exists access paths `A` and `B` where - * A ->* read -> store ->* B and where `A` and `B` do not contain content that will - * be translated into a synthetic field. + * A data flow configuration used for finding new sinks. + * The sources are the parameters of the API and the fields of the enclosing type. * - * This is needed because we don't want to include summaries that reads from or - * stores into an "internal" synthetic field. - * - * Example: - * Assume we have a type `t` (in this case `t1` = `t2`) with methods `getX` and - * `setX`, which gets and sets a private field `X` on `t`. - * This would lead to the following content flows - * getX : Argument[this].SyntheticField[t.X] -> ReturnValue. - * setX : Argument[0] -> Argument[this].SyntheticField[t.X] - * As the reads and stores are on synthetic fields we should only make summaries - * if both of these methods exist. + * This can be used to generate Sink summaries for APIs, if the API propagates a parameter (or enclosing type field) + * into an existing known sink (then the API itself becomes a sink). */ - pragma[nomagic] - predicate acceptReadStore( - Type t1, PropagateContentFlow::AccessPath read, Type t2, - PropagateContentFlow::AccessPath store - ) { - synthPathEntry(t1, read, t2, store) and - reachesSynthExit(t2, getSyntheticPathCandidate(store)) - or - exists(PropagateContentFlow::AccessPath store0 | getSyntheticPathCandidate(store0) = read | - synthEntryReaches(t1, store0) and synthPathExit(t1, read, t2, store) + module PropagateToSinkConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + apiSource(source) and + getEnclosingCallable(source) instanceof DataFlowSinkTargetApi + } + + predicate isSink(DataFlow::Node sink) { + exists(string kind | isRelevantSinkKind(kind) and sinkNode(sink, kind)) + } + + predicate isBarrier(DataFlow::Node node) { + exists(Type t | t = node.(NodeExtended).getType() and not isRelevantType(t)) or - synthEntryReaches(t1, store0) and - step(t1, read, t2, store) and - reachesSynthExit(t2, getSyntheticPathCandidate(store)) - ) + sinkModelSanitizer(node) + } + + DataFlow::FlowFeature getAFeature() { + result instanceof DataFlow::FeatureHasSourceCallContext + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + isRelevantTaintStep(node1, node2) + } } - } - /** - * Holds, if the API `api` has relevant flow from `read` on `p` to `store` on `returnNodeExt`. - * Flow is considered relevant, - * 1. If `read` or `store` do not contain a content set that translates into a synthetic field. - * 2. If `read` or `store` contain a content set that translates into a synthetic field, and if - * the synthetic content is "live" on the relevant declaring type. - */ - private predicate apiRelevantContentFlow( - ContentDataFlowSummaryTargetApi api, DataFlow::ParameterNode p, - PropagateContentFlow::AccessPath read, ReturnNodeExt returnNodeExt, - PropagateContentFlow::AccessPath store, boolean preservesValue - ) { - apiContentFlow(api, p, read, returnNodeExt, store, preservesValue) and - ( - not hasSyntheticContent(read) and not hasSyntheticContent(store) - or - AccessPathSyntheticValidation::acceptReadStore(p.(NodeExtended).getType(), read, - returnNodeExt.getType(), store) - ) - } + private module PropagateToSink = TaintTracking::Global; - pragma[nomagic] - private predicate captureFlow0( - ContentDataFlowSummaryTargetApi api, string input, string output, boolean preservesValue, - boolean lift - ) { - exists( - DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt, - PropagateContentFlow::AccessPath reads, PropagateContentFlow::AccessPath stores - | - apiRelevantContentFlow(api, p, reads, returnNodeExt, stores, preservesValue) and - input = parameterNodeAsContentInput(p) + printReadAccessPath(reads) and - output = getContentOutput(returnNodeExt) + printStoreAccessPath(stores) and - input != output and - validateAccessPath(reads) and - validateAccessPath(stores) and - ( - if mentionsField(reads) or mentionsField(stores) - then lift = false and api.isRelevant() - else lift = true + /** + * Gets the sink model(s) of `api`, if there is flow from a parameter to an existing known sink. + */ + string captureSink(DataFlowSinkTargetApi api) { + exists(NodeExtended src, NodeExtended sink, string kind | + PropagateToSink::flow(src, sink) and + sinkNode(sink, kind) and + api = getEnclosingCallable(src) and + result = ModelPrintingSourceOrSink::asSinkModel(api, asInputArgument(src), kind) ) - ) - } - - /** - * Gets the content based summary model(s) of the API `api` (if there is flow from a parameter to - * the return value or a parameter). `lift` is true, if the model should be lifted, otherwise false. - * - * Models are lifted to the best type in case the read and store access paths do not - * contain a field or synthetic field access. - */ - string captureFlow(ContentDataFlowSummaryTargetApi api, boolean lift) { - exists(string input, string output, boolean preservesValue | - captureFlow0(api, input, output, _, lift) and - preservesValue = max(boolean p | captureFlow0(api, input, output, p, lift)) and - result = ContentModelPrinting::asModel(api, input, output, preservesValue, lift) - ) + } } } - - /** - * Gets the summary model(s) for `api`, if any. `lift` is true if the model is lifted - * otherwise false. - * The following heuristic is applied: - * 1. If content based flow yields at lease one summary for an API, then we use that. - * 2. If content based flow does not yield any summary for an API, then we try and - * generate flow summaries using the heuristic based summary generator. - */ - string captureFlow(DataFlowSummaryTargetApi api, boolean lift) { - result = ContentSensitive::captureFlow(api, lift) - or - not exists(DataFlowSummaryTargetApi api0 | - (api0 = api or api.lift() = api0) and - exists(ContentSensitive::captureFlow(api0, false)) - or - api0.lift() = api.lift() and - exists(ContentSensitive::captureFlow(api0, true)) - ) and - result = Heuristic::captureFlow(api) and - lift = true - } - - /** - * Gets the neutral summary model for `api`, if any. - * A neutral summary model is generated, if we are not generating - * a mixed summary model that applies to `api`. - */ - string captureNeutral(DataFlowSummaryTargetApi api) { - not exists(DataFlowSummaryTargetApi api0, boolean lift | - exists(captureFlow(api0, lift)) and - ( - lift = false and - (api0 = api or api0 = api.lift()) - or - lift = true and api0.lift() = api.lift() - ) - ) and - api.isRelevant() and - result = Heuristic::ModelPrintingSummary::asNeutralSummaryModel(api) - } } From 0016fbfa213c4bc04d9239cab76c6233e7ac5982 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Fri, 25 Apr 2025 09:34:33 +0200 Subject: [PATCH 154/336] C#: Re-factor implementation to use the new model generator interface. --- .../CaptureContentSummaryModels.ql | 1 + .../modelgenerator/CaptureNeutralModels.ql | 1 + .../utils/modelgenerator/CaptureSinkModels.ql | 1 + .../modelgenerator/CaptureSourceModels.ql | 1 + .../modelgenerator/CaptureSummaryModels.ql | 1 + .../debug/CaptureSummaryModelsPartialPath.ql | 1 + .../debug/CaptureSummaryModelsPath.ql | 1 + .../modelgenerator/internal/CaptureModels.qll | 376 +++++++++--------- .../internal/CaptureModelsPrinting.qll | 2 +- .../CaptureTypeBasedSummaryModels.qll | 5 +- .../dataflow/CaptureContentSummaryModels.ql | 1 + .../dataflow/CaptureHeuristicSummaryModels.ql | 1 + .../dataflow/CaptureNeutralModels.ql | 1 + .../dataflow/CaptureSinkModels.ql | 1 + .../dataflow/CaptureSourceModels.ql | 1 + 15 files changed, 208 insertions(+), 187 deletions(-) diff --git a/csharp/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql b/csharp/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql index 039c96a9a0bc..4d56c922a397 100644 --- a/csharp/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql +++ b/csharp/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SummaryModels from DataFlowSummaryTargetApi api, string flow where flow = ContentSensitive::captureFlow(api, _) diff --git a/csharp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql b/csharp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql index 2afb0ea02845..c74240bedea5 100644 --- a/csharp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql +++ b/csharp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SummaryModels from DataFlowSummaryTargetApi api, string noflow where noflow = captureNeutral(api) diff --git a/csharp/ql/src/utils/modelgenerator/CaptureSinkModels.ql b/csharp/ql/src/utils/modelgenerator/CaptureSinkModels.ql index f4c9405c96a7..f0d3294cd8ac 100644 --- a/csharp/ql/src/utils/modelgenerator/CaptureSinkModels.ql +++ b/csharp/ql/src/utils/modelgenerator/CaptureSinkModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SinkModels from DataFlowSinkTargetApi api, string sink where sink = Heuristic::captureSink(api) diff --git a/csharp/ql/src/utils/modelgenerator/CaptureSourceModels.ql b/csharp/ql/src/utils/modelgenerator/CaptureSourceModels.ql index 70f853b35a95..97688d6eb423 100644 --- a/csharp/ql/src/utils/modelgenerator/CaptureSourceModels.ql +++ b/csharp/ql/src/utils/modelgenerator/CaptureSourceModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SourceModels from DataFlowSourceTargetApi api, string source where source = Heuristic::captureSource(api) diff --git a/csharp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql b/csharp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql index a0193397eb2e..61656c200adf 100644 --- a/csharp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql +++ b/csharp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SummaryModels from DataFlowSummaryTargetApi api, string flow where flow = captureFlow(api, _) diff --git a/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql b/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql index beb14cd8e627..60d7b42a46df 100644 --- a/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql +++ b/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql @@ -10,6 +10,7 @@ import csharp import utils.modelgenerator.internal.CaptureModels +import SummaryModels import PartialFlow::PartialPathGraph int explorationLimit() { result = 3 } diff --git a/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql b/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql index e3de78767eaa..a53958ad0e6d 100644 --- a/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql +++ b/csharp/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql @@ -10,6 +10,7 @@ import csharp import utils.modelgenerator.internal.CaptureModels +import SummaryModels import Heuristic import PropagateFlow::PathGraph diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll index ce83369df077..7bf8a248a6f2 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -15,7 +15,41 @@ private import semmle.code.csharp.frameworks.System private import semmle.code.csharp.Location private import codeql.mad.modelgenerator.internal.ModelGeneratorImpl -module ModelGeneratorInput implements ModelGeneratorInputSig { +private predicate irrelevantAccessor(CS::Accessor a) { + a.getDeclaration().(CS::Property).isReadWrite() +} + +private predicate isUninterestingForModels(Callable api) { + api.getDeclaringType().getNamespace().getFullName() = "" + or + api instanceof CS::ConversionOperator + or + api instanceof Util::MainMethod + or + api instanceof CS::Destructor + or + api instanceof CS::AnonymousFunctionExpr + or + api.(CS::Constructor).isParameterless() + or + exists(Type decl | decl = api.getDeclaringType() | + decl instanceof SystemObjectClass or + decl instanceof SystemValueTypeClass + ) + or + // Disregard properties that have both a get and a set accessor, + // which implicitly means auto implemented properties. + irrelevantAccessor(api) +} + +private predicate relevant(Callable api) { + [api.(CS::Modifiable), api.(CS::Accessor).getDeclaration()].isEffectivelyPublic() and + api.fromSource() and + api.isUnboundDeclaration() and + not isUninterestingForModels(api) +} + +module ModelGeneratorCommonInput implements ModelGeneratorCommonInputSig { class Type = CS::Type; class Parameter = CS::Parameter; @@ -24,127 +58,8 @@ module ModelGeneratorInput implements ModelGeneratorInputSig`. - */ - private predicate isHigherOrder(Callable api) { - exists(Type t | t = api.getAParameter().getType().getUnboundDeclaration() | - t instanceof SystemLinqExpressions::DelegateExtType - ) - } - - private predicate irrelevantAccessor(CS::Accessor a) { - a.getDeclaration().(CS::Property).isReadWrite() - } - - private predicate isUninterestingForModels(Callable api) { - api.getDeclaringType().getNamespace().getFullName() = "" - or - api instanceof CS::ConversionOperator - or - api instanceof Util::MainMethod - or - api instanceof CS::Destructor - or - api instanceof CS::AnonymousFunctionExpr - or - api.(CS::Constructor).isParameterless() - or - exists(Type decl | decl = api.getDeclaringType() | - decl instanceof SystemObjectClass or - decl instanceof SystemValueTypeClass - ) - or - // Disregard properties that have both a get and a set accessor, - // which implicitly means auto implemented properties. - irrelevantAccessor(api) - } - - private predicate relevant(Callable api) { - [api.(CS::Modifiable), api.(CS::Accessor).getDeclaration()].isEffectivelyPublic() and - api.fromSource() and - api.isUnboundDeclaration() and - not isUninterestingForModels(api) - } - - private Callable getARelevantOverrideeOrImplementee(Overridable m) { - m.overridesOrImplements(result) and relevant(result) - } - - /** - * Gets the super implementation of `api` if it is relevant. - * If such a super implementation does not exist, returns `api` if it is relevant. - */ - private Callable liftedImpl(Callable api) { - ( - result = getARelevantOverrideeOrImplementee(api) - or - result = api and relevant(api) - ) and - not exists(getARelevantOverrideeOrImplementee(result)) - } - - private predicate hasManualSummaryModel(Callable api) { - api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()) or - api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel()) - } - - private predicate hasManualSourceModel(Callable api) { - api = any(ExternalFlow::SourceCallable sc | sc.hasManualModel()) or - api = any(FlowSummaryImpl::Public::NeutralSourceCallable sc | sc.hasManualModel()) - } - - private predicate hasManualSinkModel(Callable api) { - api = any(ExternalFlow::SinkCallable sc | sc.hasManualModel()) or - api = any(FlowSummaryImpl::Public::NeutralSinkCallable sc | sc.hasManualModel()) - } - - predicate isUninterestingForDataFlowModels(Callable api) { none() } - - predicate isUninterestingForHeuristicDataFlowModels(Callable api) { isHigherOrder(api) } - - class SourceOrSinkTargetApi extends Callable { - SourceOrSinkTargetApi() { relevant(this) } - } - - class SinkTargetApi extends SourceOrSinkTargetApi { - SinkTargetApi() { not hasManualSinkModel(this) } - } - - class SourceTargetApi extends SourceOrSinkTargetApi { - SourceTargetApi() { - not hasManualSourceModel(this) and - // Do not generate source models for overridable callables - // as virtual dispatch implies that too many methods - // will be considered sources. - not this.(Overridable).overridesOrImplements(_) - } - } - - class SummaryTargetApi extends Callable { - private Callable lift; - - SummaryTargetApi() { - lift = liftedImpl(this) and - not hasManualSummaryModel(lift) - } - - Callable lift() { result = lift } - - predicate isRelevant() { - relevant(this) and - not hasManualSummaryModel(this) - } - } - /** * Holds if `t` is a type that is generally used for bulk data in collection types. * Eg. char[] is roughly equivalent to string and thus a highly @@ -205,6 +120,8 @@ module ModelGeneratorInput implements ModelGeneratorInputSig { @@ -251,62 +166,93 @@ module ModelGeneratorInput implements ModelGeneratorInputSig + +module SummaryModelGeneratorInput implements SummaryModelGeneratorInputSig { + Callable getAsExprEnclosingCallable(NodeExtended node) { + result = node.asExpr().getEnclosingCallable() } - private predicate uniquelyCalls(DataFlowCallable dc1, DataFlowCallable dc2) { - exists(DataFlowCall call | - dc1 = call.getEnclosingCallable() and - dc2 = unique(DataFlowCallable dc0 | dc0 = viableCallable(call) | dc0) + Parameter asParameter(NodeExtended node) { result = node.asParameter() } + + /** + * Holds if any of the parameters of `api` are `System.Func<>`. + */ + private predicate isHigherOrder(Callable api) { + exists(Type t | t = api.getAParameter().getType().getUnboundDeclaration() | + t instanceof SystemLinqExpressions::DelegateExtType ) } - bindingset[dc1, dc2] - private predicate uniquelyCallsPlus(DataFlowCallable dc1, DataFlowCallable dc2) = - fastTC(uniquelyCalls/2)(dc1, dc2) + private Callable getARelevantOverrideeOrImplementee(Overridable m) { + m.overridesOrImplements(result) and relevant(result) + } - bindingset[sourceEnclosing, api] - predicate irrelevantSourceSinkApi(Callable sourceEnclosing, SourceTargetApi api) { - not exists(DataFlowCallable dc1, DataFlowCallable dc2 | - uniquelyCallsPlus(dc1, dc2) or dc1 = dc2 - | - dc1.getUnderlyingCallable() = api and - dc2.getUnderlyingCallable() = sourceEnclosing - ) + /** + * Gets the super implementation of `api` if it is relevant. + * If such a super implementation does not exist, returns `api` if it is relevant. + */ + private Callable liftedImpl(Callable api) { + ( + result = getARelevantOverrideeOrImplementee(api) + or + result = api and relevant(api) + ) and + not exists(getARelevantOverrideeOrImplementee(result)) } - string getInputArgument(DataFlow::Node source) { - exists(int pos | - pos = source.(DataFlow::ParameterNode).getParameter().getPosition() and - result = "Argument[" + pos + "]" - ) - or - source.asExpr() instanceof DataFlowPrivate::FieldOrPropertyAccess and - result = qualifierString() + private predicate hasManualSummaryModel(Callable api) { + api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()) or + api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel()) } - bindingset[kind] - predicate isRelevantSinkKind(string kind) { any() } + predicate isUninterestingForDataFlowModels(Callable api) { none() } - bindingset[kind] - predicate isRelevantSourceKind(string kind) { any() } + predicate isUninterestingForHeuristicDataFlowModels(Callable api) { isHigherOrder(api) } - predicate containerContent(DataFlow::ContentSet c) { c.isElement() } + class SummaryTargetApi extends Callable { + private Callable lift; + + SummaryTargetApi() { + lift = liftedImpl(this) and + not hasManualSummaryModel(lift) + } + + Callable lift() { result = lift } + + predicate isRelevant() { + relevant(this) and + not hasManualSummaryModel(this) + } + } predicate isAdditionalContentFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { TaintTrackingPrivate::defaultAdditionalTaintStep(nodeFrom, nodeTo, _) and @@ -370,34 +316,96 @@ module ModelGeneratorInput implements ModelGeneratorInputSig +import MakeSummaryModelGenerator as SummaryModels +import MakeSourceModelGenerator as SourceModels +import MakeSinkModelGenerator as SinkModels diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll index 97e58d439f0c..52611279b273 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll @@ -1,6 +1,6 @@ private import csharp as CS private import codeql.mad.modelgenerator.internal.ModelPrinting -private import CaptureModels::ModelGeneratorInput as ModelGeneratorInput +private import CaptureModels::ModelGeneratorCommonInput as ModelGeneratorInput private module ModelPrintingLang implements ModelPrintingLangSig { class Callable = CS::Callable; diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll index 62286c27888c..baba462c8a24 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll @@ -2,7 +2,8 @@ private import csharp private import semmle.code.csharp.frameworks.system.collections.Generic as GenericCollections private import semmle.code.csharp.dataflow.internal.DataFlowPrivate private import semmle.code.csharp.frameworks.system.linq.Expressions -private import CaptureModels::ModelGeneratorInput as ModelGeneratorInput +private import CaptureModels::ModelGeneratorCommonInput as ModelGeneratorInput +private import CaptureModels::SummaryModelGeneratorInput as SummaryModelGeneratorInput private import CaptureModelsPrinting /** @@ -189,7 +190,7 @@ private module Printing = ModelPrintingSummary; * A class of callables that are relevant generating summaries for based * on the Theorems for Free approach. */ -class TypeBasedFlowTargetApi extends ModelGeneratorInput::SummaryTargetApi { +class TypeBasedFlowTargetApi extends SummaryModelGeneratorInput::SummaryTargetApi { /** * Gets the string representation of all type based summaries for `this` * inspired by the Theorems for Free approach. diff --git a/csharp/ql/test/utils/modelgenerator/dataflow/CaptureContentSummaryModels.ql b/csharp/ql/test/utils/modelgenerator/dataflow/CaptureContentSummaryModels.ql index 0d9e4cd52d9f..0c8134546d24 100644 --- a/csharp/ql/test/utils/modelgenerator/dataflow/CaptureContentSummaryModels.ql +++ b/csharp/ql/test/utils/modelgenerator/dataflow/CaptureContentSummaryModels.ql @@ -1,5 +1,6 @@ import csharp import utils.modelgenerator.internal.CaptureModels +import SummaryModels import utils.test.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { diff --git a/csharp/ql/test/utils/modelgenerator/dataflow/CaptureHeuristicSummaryModels.ql b/csharp/ql/test/utils/modelgenerator/dataflow/CaptureHeuristicSummaryModels.ql index 24cb66e427e7..b5a3b31a0354 100644 --- a/csharp/ql/test/utils/modelgenerator/dataflow/CaptureHeuristicSummaryModels.ql +++ b/csharp/ql/test/utils/modelgenerator/dataflow/CaptureHeuristicSummaryModels.ql @@ -1,5 +1,6 @@ import csharp import utils.modelgenerator.internal.CaptureModels +import SummaryModels import utils.test.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { diff --git a/csharp/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql b/csharp/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql index d5aa685bfe31..e79cab74560c 100644 --- a/csharp/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql +++ b/csharp/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql @@ -1,5 +1,6 @@ import csharp import utils.modelgenerator.internal.CaptureModels +import SummaryModels import utils.test.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { diff --git a/csharp/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql b/csharp/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql index cc84ede4235e..0cc8dd6d08d3 100644 --- a/csharp/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql +++ b/csharp/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql @@ -1,5 +1,6 @@ import csharp import utils.modelgenerator.internal.CaptureModels +import SinkModels import utils.test.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { diff --git a/csharp/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql b/csharp/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql index 4c10362960a2..2a54abf9b72d 100644 --- a/csharp/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql +++ b/csharp/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql @@ -1,5 +1,6 @@ import csharp import utils.modelgenerator.internal.CaptureModels +import SourceModels import utils.test.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { From 2535055de054b8fa0d92510dfa56c813efe4ae30 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Fri, 25 Apr 2025 11:36:03 +0200 Subject: [PATCH 155/336] Java: Re-factor implementation to use the new model generator interface. --- .../CaptureContentSummaryModels.ql | 1 + .../modelgenerator/CaptureNeutralModels.ql | 1 + .../utils/modelgenerator/CaptureSinkModels.ql | 1 + .../modelgenerator/CaptureSourceModels.ql | 1 + .../modelgenerator/CaptureSummaryModels.ql | 1 + .../debug/CaptureSummaryModelsPartialPath.ql | 1 + .../debug/CaptureSummaryModelsPath.ql | 1 + .../modelgenerator/internal/CaptureModels.qll | 291 +++++++++--------- .../internal/CaptureModelsPrinting.qll | 2 +- .../CaptureTypeBasedSummaryModels.qll | 5 +- .../dataflow/CaptureContentSummaryModels.ql | 1 + .../dataflow/CaptureHeuristicSummaryModels.ql | 1 + .../dataflow/CaptureNeutralModels.ql | 1 + .../dataflow/CaptureSinkModels.ql | 1 + .../dataflow/CaptureSourceModels.ql | 1 + 15 files changed, 165 insertions(+), 145 deletions(-) diff --git a/java/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql b/java/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql index b1340e2c0d33..1fe70bae0b5b 100644 --- a/java/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql +++ b/java/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SummaryModels from DataFlowSummaryTargetApi api, string flow where flow = ContentSensitive::captureFlow(api, _) diff --git a/java/ql/src/utils/modelgenerator/CaptureNeutralModels.ql b/java/ql/src/utils/modelgenerator/CaptureNeutralModels.ql index d17c11d4a7b0..6008c3bfb8c4 100644 --- a/java/ql/src/utils/modelgenerator/CaptureNeutralModels.ql +++ b/java/ql/src/utils/modelgenerator/CaptureNeutralModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SummaryModels from DataFlowSummaryTargetApi api, string noflow where noflow = captureNeutral(api) diff --git a/java/ql/src/utils/modelgenerator/CaptureSinkModels.ql b/java/ql/src/utils/modelgenerator/CaptureSinkModels.ql index 7c316a02b090..7fcba8850d6d 100644 --- a/java/ql/src/utils/modelgenerator/CaptureSinkModels.ql +++ b/java/ql/src/utils/modelgenerator/CaptureSinkModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SinkModels from DataFlowSinkTargetApi api, string sink where sink = Heuristic::captureSink(api) diff --git a/java/ql/src/utils/modelgenerator/CaptureSourceModels.ql b/java/ql/src/utils/modelgenerator/CaptureSourceModels.ql index 4a955d4614b7..c623645820b6 100644 --- a/java/ql/src/utils/modelgenerator/CaptureSourceModels.ql +++ b/java/ql/src/utils/modelgenerator/CaptureSourceModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SourceModels from DataFlowSourceTargetApi api, string source where source = Heuristic::captureSource(api) diff --git a/java/ql/src/utils/modelgenerator/CaptureSummaryModels.ql b/java/ql/src/utils/modelgenerator/CaptureSummaryModels.ql index 34b6521e7b22..3bc49c31df27 100644 --- a/java/ql/src/utils/modelgenerator/CaptureSummaryModels.ql +++ b/java/ql/src/utils/modelgenerator/CaptureSummaryModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SummaryModels from DataFlowSummaryTargetApi api, string flow where flow = captureFlow(api, _) diff --git a/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql b/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql index 8895fdaefbb3..b9dc9ea236a0 100644 --- a/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql +++ b/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql @@ -11,6 +11,7 @@ import java import semmle.code.java.dataflow.DataFlow import utils.modelgenerator.internal.CaptureModels +import SummaryModels import PartialFlow::PartialPathGraph int explorationLimit() { result = 3 } diff --git a/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql b/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql index 8f6bf1c1f531..5925364800c9 100644 --- a/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql +++ b/java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql @@ -11,6 +11,7 @@ import java import semmle.code.java.dataflow.DataFlow import utils.modelgenerator.internal.CaptureModels +import SummaryModels import Heuristic import PropagateFlow::PathGraph diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll index 9dd317b30067..cff4e97d8d33 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -25,7 +25,20 @@ predicate isPrimitiveTypeUsedForBulkData(J::Type t) { t.hasName(["byte", "char", "Byte", "Character"]) } -module ModelGeneratorInput implements ModelGeneratorInputSig { +private predicate isInfrequentlyUsed(J::CompilationUnit cu) { + cu.getPackage().getName().matches("javax.swing%") or + cu.getPackage().getName().matches("java.awt%") +} + +private predicate relevant(Callable api) { + api.isPublic() and + api.getDeclaringType().isPublic() and + api.fromSource() and + not isUninterestingForModels(api) and + not isInfrequentlyUsed(api.getCompilationUnit()) +} + +module ModelGeneratorCommonInput implements ModelGeneratorCommonInputSig { class Type = J::Type; class Parameter = J::Parameter; @@ -34,96 +47,8 @@ module ModelGeneratorInput implements ModelGeneratorInputSig + +module SummaryModelGeneratorInput implements SummaryModelGeneratorInputSig { + Callable getAsExprEnclosingCallable(NodeExtended node) { + result = node.asExpr().getEnclosingCallable() + } + + Parameter asParameter(NodeExtended node) { result = node.asParameter() } + + private J::Method getARelevantOverride(J::Method m) { + result = m.getAnOverride() and + relevant(result) and + // Other exclusions for overrides. + not m instanceof J::ToStringMethod + } + + /** + * Gets the super implementation of `m` if it is relevant. + * If such a super implementations does not exist, returns `m` if it is relevant. + */ + private J::Callable liftedImpl(J::Callable m) { ( - source.asExpr().(J::FieldAccess).isOwnFieldAccess() or - source instanceof DataFlow::ParameterNode + result = getARelevantOverride(m) + or + result = m and relevant(m) ) and - exists(J::RefType t | - t = source.getEnclosingCallable().getDeclaringType().getAnAncestor() and - not t instanceof J::TypeObject and - t.isPublic() - ) + not exists(getARelevantOverride(result)) } - predicate irrelevantSourceSinkApi(Callable source, SourceTargetApi api) { none() } - - string getInputArgument(DataFlow::Node source) { - exists(int pos | - source.(DataFlow::ParameterNode).isParameterOf(_, pos) and - if pos >= 0 then result = "Argument[" + pos + "]" else result = qualifierString() - ) - or - source.asExpr() instanceof J::FieldAccess and - result = qualifierString() + private predicate hasManualSummaryModel(Callable api) { + api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()).asCallable() or + api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel()).asCallable() } - bindingset[kind] - predicate isRelevantSinkKind(string kind) { - not kind = "log-injection" and - not kind.matches("regex-use%") and - not kind = "file-content-store" + class SummaryTargetApi extends Callable { + private Callable lift; + + SummaryTargetApi() { + lift = liftedImpl(this) and + not hasManualSummaryModel(lift) + } + + Callable lift() { result = lift } + + predicate isRelevant() { + relevant(this) and + not hasManualSummaryModel(this) + } } - bindingset[kind] - predicate isRelevantSourceKind(string kind) { any() } + predicate isUninterestingForDataFlowModels(Callable api) { + api.getDeclaringType() instanceof J::Interface and not exists(api.getBody()) + } - predicate containerContent = DataFlowPrivate::containerContent/1; + predicate isUninterestingForHeuristicDataFlowModels(Callable api) { none() } predicate isAdditionalContentFlowStep(DataFlow::Node node1, DataFlow::Node node2) { TaintTracking::defaultAdditionalTaintStep(node1, node2, _) and @@ -287,34 +252,76 @@ module ModelGeneratorInput implements ModelGeneratorInputSig= 0 then result = "Argument[" + pos + "]" else result = qualifierString() + ) + or + source.asExpr() instanceof J::FieldAccess and + result = qualifierString() + } + + bindingset[kind] + predicate isRelevantSinkKind(string kind) { + not kind = "log-injection" and + not kind.matches("regex-use%") and + not kind = "file-content-store" + } predicate sinkNode = ExternalFlow::sinkNode/2; } -import MakeModelGenerator +import MakeSummaryModelGenerator as SummaryModels +import MakeSourceModelGenerator as SourceModels +import MakeSinkModelGenerator as SinkModels diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll index 4b376654afbe..0d26f36c690a 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll @@ -1,6 +1,6 @@ private import java as J private import codeql.mad.modelgenerator.internal.ModelPrinting -private import CaptureModels::ModelGeneratorInput as ModelGeneratorInput +private import CaptureModels::ModelGeneratorCommonInput as ModelGeneratorInput private module ModelPrintingLang implements ModelPrintingLangSig { class Callable = J::Callable; diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll b/java/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll index 9145a0779075..00c8c686c2d1 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureTypeBasedSummaryModels.qll @@ -2,7 +2,8 @@ private import java private import semmle.code.java.Collections private import semmle.code.java.dataflow.internal.ContainerFlow private import CaptureModels as CaptureModels -private import CaptureModels::ModelGeneratorInput as ModelGeneratorInput +private import CaptureModels::ModelGeneratorCommonInput as ModelGeneratorInput +private import CaptureModels::SummaryModelGeneratorInput as SummaryModelGeneratorInput private import CaptureModelsPrinting /** @@ -296,7 +297,7 @@ private module Printing = ModelPrintingSummary; * A class of callables that are relevant generating summaries for based * on the Theorems for Free approach. */ -class TypeBasedFlowTargetApi extends ModelGeneratorInput::SummaryTargetApi { +class TypeBasedFlowTargetApi extends SummaryModelGeneratorInput::SummaryTargetApi { /** * Gets the string representation of all type based summaries for `this` * inspired by the Theorems for Free approach. diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureContentSummaryModels.ql b/java/ql/test/utils/modelgenerator/dataflow/CaptureContentSummaryModels.ql index 8dd23714fb79..b3d9101633b8 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureContentSummaryModels.ql +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureContentSummaryModels.ql @@ -1,5 +1,6 @@ import java import utils.modelgenerator.internal.CaptureModels +import SummaryModels import utils.test.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureHeuristicSummaryModels.ql b/java/ql/test/utils/modelgenerator/dataflow/CaptureHeuristicSummaryModels.ql index 45485a8009a5..8d6021ab42e4 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureHeuristicSummaryModels.ql +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureHeuristicSummaryModels.ql @@ -1,5 +1,6 @@ import java import utils.modelgenerator.internal.CaptureModels +import SummaryModels import utils.test.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql b/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql index 3578153ddb82..ad567051922d 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureNeutralModels.ql @@ -1,5 +1,6 @@ import java import utils.modelgenerator.internal.CaptureModels +import SummaryModels import utils.test.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql b/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql index 027670316c33..3d21b2e4f7d6 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureSinkModels.ql @@ -1,5 +1,6 @@ import java import utils.modelgenerator.internal.CaptureModels +import SinkModels import utils.test.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { diff --git a/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql b/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql index d8346f0e3dca..bc95ecf3f2de 100644 --- a/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql +++ b/java/ql/test/utils/modelgenerator/dataflow/CaptureSourceModels.ql @@ -1,5 +1,6 @@ import java import utils.modelgenerator.internal.CaptureModels +import SourceModels import utils.test.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { From c16d913f8a586daa995449a00651427d475466c0 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Fri, 25 Apr 2025 12:49:05 +0200 Subject: [PATCH 156/336] C++: Re-factor implementation to use the new model generator interface. --- .../CaptureContentSummaryModels.ql | 1 + .../modelgenerator/CaptureNeutralModels.ql | 1 + .../utils/modelgenerator/CaptureSinkModels.ql | 4 +- .../modelgenerator/CaptureSourceModels.ql | 4 +- .../modelgenerator/CaptureSummaryModels.ql | 1 + .../modelgenerator/internal/CaptureModels.qll | 311 +++++++++--------- .../internal/CaptureModelsPrinting.qll | 2 +- .../dataflow/CaptureContentSummaryModels.ql | 1 + .../dataflow/CaptureHeuristicSummaryModels.ql | 1 + 9 files changed, 173 insertions(+), 153 deletions(-) diff --git a/cpp/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql b/cpp/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql index 8dc0c3d7f6b1..be0cf4434311 100644 --- a/cpp/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql +++ b/cpp/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SummaryModels from DataFlowSummaryTargetApi api, string flow where flow = ContentSensitive::captureFlow(api, _) diff --git a/cpp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql b/cpp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql index e9a5ea24deca..813eece65b96 100644 --- a/cpp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql +++ b/cpp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SummaryModels from DataFlowSummaryTargetApi api, string noflow where noflow = captureNeutral(api) diff --git a/cpp/ql/src/utils/modelgenerator/CaptureSinkModels.ql b/cpp/ql/src/utils/modelgenerator/CaptureSinkModels.ql index 5485a2645bcb..1ed9b0320709 100644 --- a/cpp/ql/src/utils/modelgenerator/CaptureSinkModels.ql +++ b/cpp/ql/src/utils/modelgenerator/CaptureSinkModels.ql @@ -7,8 +7,8 @@ */ import internal.CaptureModels -import Heuristic +import SinkModels from DataFlowSinkTargetApi api, string sink -where sink = captureSink(api) +where sink = Heuristic::captureSink(api) select sink order by sink diff --git a/cpp/ql/src/utils/modelgenerator/CaptureSourceModels.ql b/cpp/ql/src/utils/modelgenerator/CaptureSourceModels.ql index c2240c646886..4f86fb6b6fb1 100644 --- a/cpp/ql/src/utils/modelgenerator/CaptureSourceModels.ql +++ b/cpp/ql/src/utils/modelgenerator/CaptureSourceModels.ql @@ -7,8 +7,8 @@ */ import internal.CaptureModels -import Heuristic +import SourceModels from DataFlowSourceTargetApi api, string source -where source = captureSource(api) +where source = Heuristic::captureSource(api) select source order by source diff --git a/cpp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql b/cpp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql index 60341abc0b59..a023afabd31c 100644 --- a/cpp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql +++ b/cpp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SummaryModels from DataFlowSummaryTargetApi api, string flow where flow = captureFlow(api, _) diff --git a/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll index 58acfa011186..5b3beac34539 100644 --- a/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -2,7 +2,7 @@ * Provides predicates related to capturing summary models of the Standard or a 3rd party library. */ -private import cpp +private import cpp as Cpp private import semmle.code.cpp.ir.IR private import semmle.code.cpp.dataflow.ExternalFlow as ExternalFlow private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon @@ -10,113 +10,67 @@ private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate as DataFlowPrivate private import semmle.code.cpp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl private import semmle.code.cpp.ir.dataflow.internal.TaintTrackingImplSpecific -private import semmle.code.cpp.dataflow.new.TaintTracking +private import semmle.code.cpp.dataflow.new.TaintTracking as Tt +private import semmle.code.cpp.dataflow.new.DataFlow as Df private import codeql.mad.modelgenerator.internal.ModelGeneratorImpl -module ModelGeneratorInput implements ModelGeneratorInputSig { +/** + * Holds if `f` is a "private" function. + * + * A "private" function does not contribute any models as it is assumed + * to be an implementation detail of some other "public" function for which + * we will generate a summary. + */ +private predicate isPrivateOrProtected(Cpp::Function f) { + f.getNamespace().getParentNamespace*().isAnonymous() + or + exists(Cpp::MemberFunction mf | mf = f | + mf.isPrivate() + or + mf.isProtected() + ) + or + f.isStatic() +} + +private predicate isUninterestingForModels(Callable api) { + // Note: This also makes all global/static-local variables + // not relevant (which is good!) + not api.(Cpp::Function).hasDefinition() + or + isPrivateOrProtected(api) + or + api instanceof Cpp::Destructor + or + api = any(Cpp::LambdaExpression lambda).getLambdaFunction() + or + api.isFromUninstantiatedTemplate(_) +} + +private predicate relevant(Callable api) { + api.fromSource() and + not isUninterestingForModels(api) +} + +module ModelGeneratorCommonInput implements ModelGeneratorCommonInputSig +{ + private module DataFlow = Df::DataFlow; + class Type = DataFlowPrivate::DataFlowType; // Note: This also includes `this` class Parameter = DataFlow::ParameterNode; - class Callable = Declaration; + class Callable = Cpp::Declaration; class NodeExtended extends DataFlow::Node { Callable getAsExprEnclosingCallable() { result = this.asExpr().getEnclosingDeclaration() } } - Parameter asParameter(NodeExtended n) { result = n } - Callable getEnclosingCallable(NodeExtended n) { result = n.getEnclosingCallable().asSourceCallable() } - Callable getAsExprEnclosingCallable(NodeExtended n) { - result = n.asExpr().getEnclosingDeclaration() - } - - /** Gets `api` if it is relevant. */ - private Callable liftedImpl(Callable api) { result = api and relevant(api) } - - private predicate hasManualSummaryModel(Callable api) { - api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()) or - api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel()) - } - - private predicate hasManualSourceModel(Callable api) { - api = any(FlowSummaryImpl::Public::NeutralSourceCallable sc | sc.hasManualModel()) - } - - private predicate hasManualSinkModel(Callable api) { - api = any(FlowSummaryImpl::Public::NeutralSinkCallable sc | sc.hasManualModel()) - } - - /** - * Holds if `f` is a "private" function. - * - * A "private" function does not contribute any models as it is assumed - * to be an implementation detail of some other "public" function for which - * we will generate a summary. - */ - private predicate isPrivateOrProtected(Function f) { - f.getNamespace().getParentNamespace*().isAnonymous() - or - exists(MemberFunction mf | mf = f | - mf.isPrivate() - or - mf.isProtected() - ) - or - f.isStatic() - } - - private predicate isUninterestingForModels(Callable api) { - // Note: This also makes all global/static-local variables - // not relevant (which is good!) - not api.(Function).hasDefinition() - or - isPrivateOrProtected(api) - or - api instanceof Destructor - or - api = any(LambdaExpression lambda).getLambdaFunction() - or - api.isFromUninstantiatedTemplate(_) - } - - private predicate relevant(Callable api) { - api.fromSource() and - not isUninterestingForModels(api) - } - - class SummaryTargetApi extends Callable { - private Callable lift; - - SummaryTargetApi() { - lift = liftedImpl(this) and - not hasManualSummaryModel(lift) - } - - Callable lift() { result = lift } - - predicate isRelevant() { - relevant(this) and - not hasManualSummaryModel(this) - } - } - - class SourceOrSinkTargetApi extends Callable { - SourceOrSinkTargetApi() { relevant(this) } - } - - class SinkTargetApi extends SourceOrSinkTargetApi { - SinkTargetApi() { not hasManualSinkModel(this) } - } - - class SourceTargetApi extends SourceOrSinkTargetApi { - SourceTargetApi() { not hasManualSourceModel(this) } - } - class InstanceParameterNode extends DataFlow::ParameterNode { InstanceParameterNode() { DataFlowPrivate::nodeHasInstruction(this, @@ -124,7 +78,7 @@ module ModelGeneratorInput implements ModelGeneratorInputSig" @@ -166,7 +120,7 @@ module ModelGeneratorInput implements ModelGeneratorInputSig + +private module SummaryModelGeneratorInput implements SummaryModelGeneratorInputSig { + private module DataFlow = Df::DataFlow; + + Parameter asParameter(NodeExtended n) { result = n } + + Callable getAsExprEnclosingCallable(NodeExtended n) { + result = n.asExpr().getEnclosingDeclaration() + } + + private predicate hasManualSummaryModel(Callable api) { + api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()) or + api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel()) + } + + /** Gets `api` if it is relevant. */ + private Callable liftedImpl(Callable api) { result = api and relevant(api) } + + class SummaryTargetApi extends Callable { + private Callable lift; + + SummaryTargetApi() { + lift = liftedImpl(this) and + not hasManualSummaryModel(lift) + } + + Callable lift() { result = lift } + + predicate isRelevant() { + relevant(this) and + not hasManualSummaryModel(this) + } + } predicate isAdditionalContentFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - TaintTracking::defaultAdditionalTaintStep(node1, node2, _) and + Tt::TaintTracking::defaultAdditionalTaintStep(node1, node2, _) and not exists(DataFlow::Content f | DataFlowPrivate::readStep(node1, f, node2) and containerContent(f) ) @@ -341,7 +328,7 @@ module ModelGeneratorInput implements ModelGeneratorInputSig +import MakeSummaryModelGenerator as SummaryModels +import MakeSourceModelGenerator as SourceModels +import MakeSinkModelGenerator as SinkModels diff --git a/cpp/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll b/cpp/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll index 7841f8ed1a44..43342aa671ee 100644 --- a/cpp/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll +++ b/cpp/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll @@ -1,6 +1,6 @@ private import cpp as Cpp private import codeql.mad.modelgenerator.internal.ModelPrinting -private import CaptureModels::ModelGeneratorInput as ModelGeneratorInput +private import CaptureModels::ModelGeneratorCommonInput as ModelGeneratorInput private module ModelPrintingLang implements ModelPrintingLangSig { class Callable = Cpp::Declaration; diff --git a/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/CaptureContentSummaryModels.ql b/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/CaptureContentSummaryModels.ql index 0156eaaeb988..8196f6329cc9 100644 --- a/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/CaptureContentSummaryModels.ql +++ b/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/CaptureContentSummaryModels.ql @@ -1,5 +1,6 @@ import cpp import utils.modelgenerator.internal.CaptureModels +import SummaryModels import InlineModelsAsDataTest module InlineMadTestConfig implements InlineMadTestConfigSig { diff --git a/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/CaptureHeuristicSummaryModels.ql b/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/CaptureHeuristicSummaryModels.ql index 3ab1dc6c4710..fc05c4fe434f 100644 --- a/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/CaptureHeuristicSummaryModels.ql +++ b/cpp/ql/test/library-tests/dataflow/modelgenerator/dataflow/CaptureHeuristicSummaryModels.ql @@ -1,5 +1,6 @@ import cpp import utils.modelgenerator.internal.CaptureModels +import SummaryModels import InlineModelsAsDataTest module InlineMadTestConfig implements InlineMadTestConfigSig { From a6b5645b139350a5527959492eeb7aa784b9cfc7 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Fri, 25 Apr 2025 13:09:13 +0200 Subject: [PATCH 157/336] Rust: Re-factor implementation to use the new model generator interface. --- .../CaptureContentSummaryModels.ql | 1 + .../modelgenerator/CaptureNeutralModels.ql | 1 + .../utils/modelgenerator/CaptureSinkModels.ql | 1 + .../modelgenerator/CaptureSourceModels.ql | 1 + .../modelgenerator/CaptureSummaryModels.ql | 1 + .../debug/CaptureSummaryModelsPartialPath.ql | 1 + .../debug/CaptureSummaryModelsPath.ql | 1 + .../modelgenerator/internal/CaptureModels.qll | 169 ++++++++++-------- .../internal/CaptureModelsPrinting.qll | 2 +- .../modelgenerator/CaptureSinkModels.ql | 1 + .../modelgenerator/CaptureSourceModels.ql | 1 + .../modelgenerator/CaptureSummaryModels.ql | 1 + 12 files changed, 103 insertions(+), 78 deletions(-) diff --git a/rust/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql b/rust/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql index da90465197e5..4b672e74da59 100644 --- a/rust/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql +++ b/rust/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SummaryModels from DataFlowSummaryTargetApi api, string flow where flow = ContentSensitive::captureFlow(api, _) diff --git a/rust/ql/src/utils/modelgenerator/CaptureNeutralModels.ql b/rust/ql/src/utils/modelgenerator/CaptureNeutralModels.ql index 8efc8a485e12..556d1624f39d 100644 --- a/rust/ql/src/utils/modelgenerator/CaptureNeutralModels.ql +++ b/rust/ql/src/utils/modelgenerator/CaptureNeutralModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SummaryModels from DataFlowSummaryTargetApi api, string noflow where noflow = Heuristic::captureNoFlow(api) diff --git a/rust/ql/src/utils/modelgenerator/CaptureSinkModels.ql b/rust/ql/src/utils/modelgenerator/CaptureSinkModels.ql index 36b1b8132977..989637a867e3 100644 --- a/rust/ql/src/utils/modelgenerator/CaptureSinkModels.ql +++ b/rust/ql/src/utils/modelgenerator/CaptureSinkModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SinkModels from DataFlowSinkTargetApi api, string sink where sink = Heuristic::captureSink(api) diff --git a/rust/ql/src/utils/modelgenerator/CaptureSourceModels.ql b/rust/ql/src/utils/modelgenerator/CaptureSourceModels.ql index 7086f719b2d8..2ffc4894b18c 100644 --- a/rust/ql/src/utils/modelgenerator/CaptureSourceModels.ql +++ b/rust/ql/src/utils/modelgenerator/CaptureSourceModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SourceModels from DataFlowSourceTargetApi api, string source where source = Heuristic::captureSource(api) diff --git a/rust/ql/src/utils/modelgenerator/CaptureSummaryModels.ql b/rust/ql/src/utils/modelgenerator/CaptureSummaryModels.ql index 8947dd015310..d0b3152c9be2 100644 --- a/rust/ql/src/utils/modelgenerator/CaptureSummaryModels.ql +++ b/rust/ql/src/utils/modelgenerator/CaptureSummaryModels.ql @@ -7,6 +7,7 @@ */ import internal.CaptureModels +import SummaryModels from DataFlowSummaryTargetApi api, string flow where flow = captureFlow(api, _) diff --git a/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql b/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql index eb0cd638b534..b8855b94bf2a 100644 --- a/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql +++ b/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql @@ -10,6 +10,7 @@ private import codeql.rust.dataflow.DataFlow import utils.modelgenerator.internal.CaptureModels +import SummaryModels import PartialFlow::PartialPathGraph int explorationLimit() { result = 3 } diff --git a/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql b/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql index 1ddec1ff618b..ac25306ceeee 100644 --- a/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql +++ b/rust/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql @@ -10,6 +10,7 @@ private import codeql.rust.dataflow.DataFlow import utils.modelgenerator.internal.CaptureModels +import SummaryModels import Heuristic import PropagateFlow::PathGraph diff --git a/rust/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/rust/ql/src/utils/modelgenerator/internal/CaptureModels.qll index 237da46750bd..6aeae06bbdb9 100644 --- a/rust/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/rust/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -2,7 +2,7 @@ private import codeql.util.Unit private import rust private import rust as R private import codeql.rust.dataflow.DataFlow -private import codeql.rust.dataflow.internal.DataFlowImpl +private import codeql.rust.dataflow.internal.DataFlowImpl as DataFlowImpl private import codeql.rust.dataflow.internal.Node as Node private import codeql.rust.dataflow.internal.Content private import codeql.rust.dataflow.FlowSource as FlowSource @@ -11,7 +11,25 @@ private import codeql.rust.dataflow.internal.TaintTrackingImpl private import codeql.mad.modelgenerator.internal.ModelGeneratorImpl private import codeql.rust.dataflow.internal.FlowSummaryImpl as FlowSummary -module ModelGeneratorInput implements ModelGeneratorInputSig { +private predicate relevant(Function api) { + // Only include functions that have a resolved path. + api.hasCrateOrigin() and + api.hasExtendedCanonicalPath() and + ( + // This excludes closures (these are not exported API endpoints) and + // functions without a `pub` visiblity. A function can be `pub` without + // ultimately being exported by a crate, so this is an overapproximation. + api.hasVisibility() + or + // If a method implements a public trait it is exposed through the trait. + // We overapproximate this by including all trait method implementations. + exists(Impl impl | impl.hasTrait() and impl.getAssocItemList().getAssocItem(_) = api) + ) +} + +module ModelGeneratorCommonInput implements + ModelGeneratorCommonInputSig +{ // NOTE: We are not using type information for now. class Type = Unit; @@ -23,55 +41,10 @@ module ModelGeneratorInput implements ModelGeneratorInputSig - bindingset[kind] - predicate isRelevantSinkKind(string kind) { any() } +private module SummaryModelGeneratorInput implements SummaryModelGeneratorInputSig { + class SummaryTargetApi extends Callable { + private Callable lift; - bindingset[kind] - predicate isRelevantSourceKind(string kind) { any() } + SummaryTargetApi() { + lift = this and + relevant(this) + } - predicate containerContent(DataFlow::ContentSet c) { - c.(SingletonContentSet).getContent() instanceof ElementContent + Callable lift() { result = lift } + + predicate isRelevant() { relevant(this) } } + Callable getAsExprEnclosingCallable(NodeExtended node) { result = node.asExpr().getScope() } + + Parameter asParameter(NodeExtended node) { result = node.asParameter() } + + predicate isUninterestingForDataFlowModels(Callable api) { none() } + + predicate isUninterestingForHeuristicDataFlowModels(Callable api) { none() } + predicate isAdditionalContentFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { none() } predicate isField(DataFlow::ContentSet c) { @@ -159,7 +145,7 @@ module ModelGeneratorInput implements ModelGeneratorInputSig +import MakeSummaryModelGenerator as SummaryModels +import MakeSourceModelGenerator as SourceModels +import MakeSinkModelGenerator as SinkModels diff --git a/rust/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll b/rust/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll index 4c2da918f739..789113f7580d 100644 --- a/rust/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll +++ b/rust/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll @@ -1,6 +1,6 @@ private import rust as R private import codeql.mad.modelgenerator.internal.ModelPrinting -private import CaptureModels::ModelGeneratorInput as ModelGeneratorInput +private import CaptureModels::ModelGeneratorCommonInput as ModelGeneratorInput private module ModelPrintingLang implements ModelPrintingLangSig { class Callable = R::Callable; diff --git a/rust/ql/test/utils-tests/modelgenerator/CaptureSinkModels.ql b/rust/ql/test/utils-tests/modelgenerator/CaptureSinkModels.ql index 14edea3af8a1..4b8041fb4447 100644 --- a/rust/ql/test/utils-tests/modelgenerator/CaptureSinkModels.ql +++ b/rust/ql/test/utils-tests/modelgenerator/CaptureSinkModels.ql @@ -1,5 +1,6 @@ import rust import utils.modelgenerator.internal.CaptureModels +import SinkModels import utils.test.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { diff --git a/rust/ql/test/utils-tests/modelgenerator/CaptureSourceModels.ql b/rust/ql/test/utils-tests/modelgenerator/CaptureSourceModels.ql index 66f0780448c7..c535ce787043 100644 --- a/rust/ql/test/utils-tests/modelgenerator/CaptureSourceModels.ql +++ b/rust/ql/test/utils-tests/modelgenerator/CaptureSourceModels.ql @@ -1,5 +1,6 @@ import rust import utils.modelgenerator.internal.CaptureModels +import SourceModels import utils.test.InlineMadTest import codeql.rust.dataflow.internal.ModelsAsData diff --git a/rust/ql/test/utils-tests/modelgenerator/CaptureSummaryModels.ql b/rust/ql/test/utils-tests/modelgenerator/CaptureSummaryModels.ql index 002689a20390..e0788253f43e 100644 --- a/rust/ql/test/utils-tests/modelgenerator/CaptureSummaryModels.ql +++ b/rust/ql/test/utils-tests/modelgenerator/CaptureSummaryModels.ql @@ -1,5 +1,6 @@ import rust import utils.modelgenerator.internal.CaptureModels +import SummaryModels import utils.test.InlineMadTest module InlineMadTestConfig implements InlineMadTestConfigSig { From c9d01bc6079e4e698e90c82ba1099d11a8df5881 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Fri, 25 Apr 2025 14:06:04 +0200 Subject: [PATCH 158/336] Shared: Sprinkle some predicate defaults and clean up. --- .../modelgenerator/internal/CaptureModels.qll | 16 ------ .../modelgenerator/internal/CaptureModels.qll | 10 ---- .../modelgenerator/internal/CaptureModels.qll | 7 --- .../modelgenerator/internal/CaptureModels.qll | 15 ------ .../internal/ModelGeneratorImpl.qll | 53 ++++++++----------- 5 files changed, 22 insertions(+), 79 deletions(-) diff --git a/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll index 5b3beac34539..93abe205f1a6 100644 --- a/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -360,12 +360,6 @@ private module SummaryModelGeneratorInput implements SummaryModelGeneratorInputS result = "Element[" + ec.getIndirectionIndex() + "]" ) } - - predicate isUninterestingForDataFlowModels(Callable api) { none() } - - predicate isUninterestingForHeuristicDataFlowModels(Callable api) { - isUninterestingForDataFlowModels(api) - } } private module SourceModelGeneratorInput implements SourceModelGeneratorInputSig { @@ -377,11 +371,6 @@ private module SourceModelGeneratorInput implements SourceModelGeneratorInputSig SourceTargetApi() { relevant(this) and not hasManualSourceModel(this) } } - predicate irrelevantSourceSinkApi(Callable source, SourceTargetApi api) { none() } - - bindingset[kind] - predicate isRelevantSourceKind(string kind) { any() } - predicate sourceNode = ExternalFlow::sourceNode/2; } @@ -396,8 +385,6 @@ private module SinkModelGeneratorInput implements SinkModelGeneratorInputSig { SinkTargetApi() { relevant(this) and not hasManualSinkModel(this) } } - predicate sinkModelSanitizer(DataFlow::Node node) { none() } - predicate apiSource(DataFlow::Node source) { DataFlowPrivate::nodeHasOperand(source, any(DataFlow::FieldAddress fa), 1) or @@ -416,9 +403,6 @@ private module SinkModelGeneratorInput implements SinkModelGeneratorInputSig { result = qualifierString() } - bindingset[kind] - predicate isRelevantSinkKind(string kind) { any() } - predicate sinkNode = ExternalFlow::sinkNode/2; } diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll index 7bf8a248a6f2..b0300e4a87f1 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -234,8 +234,6 @@ module SummaryModelGeneratorInput implements SummaryModelGeneratorInputSig { api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel()) } - predicate isUninterestingForDataFlowModels(Callable api) { none() } - predicate isUninterestingForHeuristicDataFlowModels(Callable api) { isHigherOrder(api) } class SummaryTargetApi extends Callable { @@ -356,9 +354,6 @@ private module SourceModelGeneratorInput implements SourceModelGeneratorInputSig ) } - bindingset[kind] - predicate isRelevantSourceKind(string kind) { any() } - predicate sourceNode = ExternalFlow::sourceNode/2; } @@ -372,8 +367,6 @@ private module SinkModelGeneratorInput implements SinkModelGeneratorInputSig { SinkTargetApi() { relevant(this) and not hasManualSinkModel(this) } } - predicate sinkModelSanitizer(DataFlow::Node node) { none() } - private predicate isRelevantMemberAccess(DataFlow::Node node) { exists(CS::MemberAccess access | access = node.asExpr() | access.hasThisQualifier() and @@ -400,9 +393,6 @@ private module SinkModelGeneratorInput implements SinkModelGeneratorInputSig { result = qualifierString() } - bindingset[kind] - predicate isRelevantSinkKind(string kind) { any() } - predicate sinkNode = ExternalFlow::sinkNode/2; } diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll index cff4e97d8d33..09223d23b1c5 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -211,8 +211,6 @@ module SummaryModelGeneratorInput implements SummaryModelGeneratorInputSig { api.getDeclaringType() instanceof J::Interface and not exists(api.getBody()) } - predicate isUninterestingForHeuristicDataFlowModels(Callable api) { none() } - predicate isAdditionalContentFlowStep(DataFlow::Node node1, DataFlow::Node node2) { TaintTracking::defaultAdditionalTaintStep(node1, node2, _) and not exists(DataFlow::Content f | @@ -264,11 +262,6 @@ private module SourceModelGeneratorInput implements SourceModelGeneratorInputSig SourceTargetApi() { relevant(this) and not hasManualSourceModel(this) } } - predicate irrelevantSourceSinkApi(Callable source, SourceTargetApi api) { none() } - - bindingset[kind] - predicate isRelevantSourceKind(string kind) { any() } - predicate sourceNode = ExternalFlow::sourceNode/2; } diff --git a/rust/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/rust/ql/src/utils/modelgenerator/internal/CaptureModels.qll index 6aeae06bbdb9..99e1c527b546 100644 --- a/rust/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/rust/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -123,10 +123,6 @@ private module SummaryModelGeneratorInput implements SummaryModelGeneratorInputS Parameter asParameter(NodeExtended node) { result = node.asParameter() } - predicate isUninterestingForDataFlowModels(Callable api) { none() } - - predicate isUninterestingForHeuristicDataFlowModels(Callable api) { none() } - predicate isAdditionalContentFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { none() } predicate isField(DataFlow::ContentSet c) { @@ -169,12 +165,6 @@ private module SourceModelGeneratorInput implements SourceModelGeneratorInputSig SourceTargetApi() { relevant(this) } } - bindingset[sourceEnclosing, api] - predicate irrelevantSourceSinkApi(Callable sourceEnclosing, SourceTargetApi api) { none() } - - bindingset[kind] - predicate isRelevantSourceKind(string kind) { any() } - predicate sourceNode(DataFlow::Node node, string kind) { FlowSource::sourceNode(node, kind) } } @@ -183,8 +173,6 @@ private module SinkModelGeneratorInput implements SinkModelGeneratorInputSig { SinkTargetApi() { relevant(this) } } - predicate sinkModelSanitizer(DataFlow::Node node) { none() } - /** * Holds if `source` is an API entrypoint, i.e., a source of input where data * can flow in to a library. This is used for creating sink models, as we @@ -197,9 +185,6 @@ private module SinkModelGeneratorInput implements SinkModelGeneratorInputSig { result = "Argument[" + source.(Node::SourceParameterNode).getPosition().toString() + "]" } - bindingset[kind] - predicate isRelevantSinkKind(string kind) { any() } - predicate sinkNode(DataFlow::Node node, string kind) { FlowSink::sinkNode(node, kind) } } diff --git a/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll b/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll index d981ef151fd7..dabd687b52b9 100644 --- a/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll +++ b/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll @@ -295,7 +295,7 @@ module MakeModelGeneratorFactory< * * This serves as an extra filter for the `relevant` predicate. */ - predicate isUninterestingForDataFlowModels(Callable api); + default predicate isUninterestingForDataFlowModels(Callable api) { none() } /** * Holds if it is irrelevant to generate models for `api` based on the heuristic @@ -304,7 +304,7 @@ module MakeModelGeneratorFactory< * This serves as an extra filter for the `relevant` * and `isUninterestingForDataFlowModels` predicates. */ - predicate isUninterestingForHeuristicDataFlowModels(Callable api); + default predicate isUninterestingForHeuristicDataFlowModels(Callable api) { none() } } /** @@ -940,24 +940,20 @@ module MakeModelGeneratorFactory< */ class SourceTargetApi extends Callable; - /** - * Holds if it is not relevant to generate a source model for `api`, even - * if flow is detected from a node within `source` to a sink within `api`. - */ - bindingset[sourceEnclosing, api] - predicate irrelevantSourceSinkApi(Callable sourceEnclosing, SourceTargetApi api); - - /** - * Holds if `kind` is a relevant source kind for creating source models. - */ - bindingset[kind] - predicate isRelevantSourceKind(string kind); - /** * Holds if `node` is specified as a source with the given kind in a MaD flow * model. */ predicate sourceNode(Lang::Node node, string kind); + + /** + * Holds if it is not relevant to generate a source model for `api`, even + * if flow is detected from a node within `source` to a sink within `api`. + */ + bindingset[sourceEnclosing, api] + default predicate irrelevantSourceSinkApi(Callable sourceEnclosing, SourceTargetApi api) { + none() + } } /** @@ -970,14 +966,15 @@ module MakeModelGeneratorFactory< class SinkTargetApi extends Callable; /** - * Gets the MaD input string representation of `source`. + * Holds if `node` is specified as a sink with the given kind in a MaD flow + * model. */ - string getInputArgument(Lang::Node source); + predicate sinkNode(Lang::Node node, string kind); /** - * Holds if `node` is a sanitizer for sink model construction. + * Gets the MaD input string representation of `source`. */ - predicate sinkModelSanitizer(Lang::Node node); + string getInputArgument(Lang::Node source); /** * Holds if `source` is an api entrypoint relevant for creating sink models. @@ -985,16 +982,15 @@ module MakeModelGeneratorFactory< predicate apiSource(Lang::Node source); /** - * Holds if `kind` is a relevant sink kind for creating sink models. + * Holds if `node` is a sanitizer for sink model construction. */ - bindingset[kind] - predicate isRelevantSinkKind(string kind); + default predicate sinkModelSanitizer(Lang::Node node) { none() } /** - * Holds if `node` is specified as a sink with the given kind in a MaD flow - * model. + * Holds if `kind` is a relevant sink kind for creating sink models. */ - predicate sinkNode(Lang::Node node, string kind); + bindingset[kind] + default predicate isRelevantSinkKind(string kind) { any() } } /** @@ -1029,12 +1025,7 @@ module MakeModelGeneratorFactory< * via its return (then the API itself becomes a source). */ module PropagateFromSourceConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { - exists(string kind | - isRelevantSourceKind(kind) and - sourceNode(source, kind) - ) - } + predicate isSource(DataFlow::Node source) { sourceNode(source, _) } predicate isSink(DataFlow::Node sink) { sink instanceof ReturnNodeExt and From e3a66811825fa6d588494ac8486ba3913685725b Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 29 Apr 2025 16:02:21 +0200 Subject: [PATCH 159/336] Add code quality suite selector --- misc/suite-helpers/code-quality-selectors.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 misc/suite-helpers/code-quality-selectors.yml diff --git a/misc/suite-helpers/code-quality-selectors.yml b/misc/suite-helpers/code-quality-selectors.yml new file mode 100644 index 000000000000..ddaf33665991 --- /dev/null +++ b/misc/suite-helpers/code-quality-selectors.yml @@ -0,0 +1,10 @@ +- description: Selectors for selecting the Code-Quality-relevant queries for a language +- include: + kind: + - problem + - path-problem + precision: + - high + - very-high + tags contain: + - quality From ea9b95790bb099fa756bbaf54e797bc0394085df Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 29 Apr 2025 16:02:46 +0200 Subject: [PATCH 160/336] Use code-quality-selectors in C# suite --- csharp/ql/src/API Abuse/FormatInvalid.ql | 1 + .../NoDisposeCallOnLocalIDisposable.ql | 1 + .../Control-Flow/ConstantCondition.ql | 1 + csharp/ql/src/Dead Code/DeadStoreOfLocal.ql | 1 + .../Collections/ContainerLengthCmpOffByOne.ql | 1 + .../Collections/ContainerSizeCmpZero.ql | 1 + .../DangerousNonShortCircuitLogic.ql | 1 + .../src/Likely Bugs/EqualityCheckOnFloats.ql | 1 + .../Likely Bugs/ReferenceEqualsOnValueTypes.ql | 1 + csharp/ql/src/Likely Bugs/SelfAssignment.ql | 1 + .../src/Likely Bugs/UncheckedCastInEquals.ql | 1 + csharp/ql/src/Performance/UseTryGetValue.ql | 4 +++- csharp/ql/src/Useless code/DefaultToString.ql | 1 + csharp/ql/src/Useless code/IntGetHashCode.ql | 1 + .../src/codeql-suites/csharp-code-quality.qls | 18 ++---------------- 15 files changed, 18 insertions(+), 17 deletions(-) diff --git a/csharp/ql/src/API Abuse/FormatInvalid.ql b/csharp/ql/src/API Abuse/FormatInvalid.ql index a2b8ef5e2220..056730a577df 100644 --- a/csharp/ql/src/API Abuse/FormatInvalid.ql +++ b/csharp/ql/src/API Abuse/FormatInvalid.ql @@ -8,6 +8,7 @@ * @id cs/invalid-string-formatting * @tags reliability * maintainability + * quality */ import csharp diff --git a/csharp/ql/src/API Abuse/NoDisposeCallOnLocalIDisposable.ql b/csharp/ql/src/API Abuse/NoDisposeCallOnLocalIDisposable.ql index e5826c423427..f02b0d49b542 100644 --- a/csharp/ql/src/API Abuse/NoDisposeCallOnLocalIDisposable.ql +++ b/csharp/ql/src/API Abuse/NoDisposeCallOnLocalIDisposable.ql @@ -8,6 +8,7 @@ * @id cs/local-not-disposed * @tags efficiency * maintainability + * quality * external/cwe/cwe-404 * external/cwe/cwe-459 * external/cwe/cwe-460 diff --git a/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql b/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql index 88d938e399fe..7bfdea1e9064 100644 --- a/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql +++ b/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql @@ -9,6 +9,7 @@ * @id cs/constant-condition * @tags maintainability * readability + * quality * external/cwe/cwe-835 */ diff --git a/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql b/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql index 1e2eaad1aa15..5be820ee74c0 100644 --- a/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql +++ b/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql @@ -6,6 +6,7 @@ * @problem.severity warning * @id cs/useless-assignment-to-local * @tags maintainability + * quality * external/cwe/cwe-563 * @precision very-high */ diff --git a/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql b/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql index 615f0634f167..754ed8ad773e 100644 --- a/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql +++ b/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql @@ -9,6 +9,7 @@ * @tags reliability * correctness * logic + * quality * external/cwe/cwe-193 */ diff --git a/csharp/ql/src/Likely Bugs/Collections/ContainerSizeCmpZero.ql b/csharp/ql/src/Likely Bugs/Collections/ContainerSizeCmpZero.ql index 6ba109713ae5..90f5b981e24b 100644 --- a/csharp/ql/src/Likely Bugs/Collections/ContainerSizeCmpZero.ql +++ b/csharp/ql/src/Likely Bugs/Collections/ContainerSizeCmpZero.ql @@ -8,6 +8,7 @@ * @tags reliability * correctness * logic + * quality */ import csharp diff --git a/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql b/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql index 6091b0f79a33..f3defa47a430 100644 --- a/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql +++ b/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql @@ -9,6 +9,7 @@ * @tags reliability * correctness * logic + * quality * external/cwe/cwe-480 * external/cwe/cwe-691 */ diff --git a/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql b/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql index 1109201fbe19..108e6f45f94f 100644 --- a/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql +++ b/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql @@ -9,6 +9,7 @@ * @id cs/equality-on-floats * @tags reliability * correctness + * quality */ import csharp diff --git a/csharp/ql/src/Likely Bugs/ReferenceEqualsOnValueTypes.ql b/csharp/ql/src/Likely Bugs/ReferenceEqualsOnValueTypes.ql index f038117aff37..de29f6109ad3 100644 --- a/csharp/ql/src/Likely Bugs/ReferenceEqualsOnValueTypes.ql +++ b/csharp/ql/src/Likely Bugs/ReferenceEqualsOnValueTypes.ql @@ -7,6 +7,7 @@ * @id cs/reference-equality-on-valuetypes * @tags reliability * correctness + * quality * external/cwe/cwe-595 */ diff --git a/csharp/ql/src/Likely Bugs/SelfAssignment.ql b/csharp/ql/src/Likely Bugs/SelfAssignment.ql index dd63ba876279..e010d18292cd 100644 --- a/csharp/ql/src/Likely Bugs/SelfAssignment.ql +++ b/csharp/ql/src/Likely Bugs/SelfAssignment.ql @@ -8,6 +8,7 @@ * @tags reliability * correctness * logic + * quality */ import csharp diff --git a/csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql b/csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql index aa244147e3ed..d1e2dbdf0563 100644 --- a/csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql +++ b/csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql @@ -7,6 +7,7 @@ * @id cs/unchecked-cast-in-equals * @tags reliability * maintainability + * quality */ import csharp diff --git a/csharp/ql/src/Performance/UseTryGetValue.ql b/csharp/ql/src/Performance/UseTryGetValue.ql index 67b57e903477..c33c0d1e8d7c 100644 --- a/csharp/ql/src/Performance/UseTryGetValue.ql +++ b/csharp/ql/src/Performance/UseTryGetValue.ql @@ -6,7 +6,9 @@ * @problem.severity recommendation * @precision high * @id cs/inefficient-containskey - * @tags maintainability efficiency + * @tags maintainability + * efficiency + * quality */ import csharp diff --git a/csharp/ql/src/Useless code/DefaultToString.ql b/csharp/ql/src/Useless code/DefaultToString.ql index 544347576fe6..ea33fe7874b6 100644 --- a/csharp/ql/src/Useless code/DefaultToString.ql +++ b/csharp/ql/src/Useless code/DefaultToString.ql @@ -8,6 +8,7 @@ * @id cs/call-to-object-tostring * @tags reliability * maintainability + * quality */ import DefaultToStringQuery diff --git a/csharp/ql/src/Useless code/IntGetHashCode.ql b/csharp/ql/src/Useless code/IntGetHashCode.ql index 85d0f56aae0e..847443d018e6 100644 --- a/csharp/ql/src/Useless code/IntGetHashCode.ql +++ b/csharp/ql/src/Useless code/IntGetHashCode.ql @@ -8,6 +8,7 @@ * @id cs/useless-gethashcode-call * @tags readability * useless-code + * quality */ import csharp diff --git a/csharp/ql/src/codeql-suites/csharp-code-quality.qls b/csharp/ql/src/codeql-suites/csharp-code-quality.qls index 85bbe4db683d..2074f9378cfd 100644 --- a/csharp/ql/src/codeql-suites/csharp-code-quality.qls +++ b/csharp/ql/src/codeql-suites/csharp-code-quality.qls @@ -1,17 +1,3 @@ - queries: . -- include: - id: - - cs/index-out-of-bounds - - cs/test-for-negative-container-size - - cs/unchecked-cast-in-equals - - cs/reference-equality-on-valuetypes - - cs/self-assignment - - cs/inefficient-containskey - - cs/call-to-object-tostring - - cs/local-not-disposed - - cs/constant-condition - - cs/useless-gethashcode-call - - cs/non-short-circuit - - cs/useless-assignment-to-local - - cs/invalid-string-formatting - - cs/equality-on-floats +- apply: code-quality-selectors.yml + from: codeql/suite-helpers From be5de9c08019e8d03ed7e992480d96293ee083c7 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Apr 2025 16:06:11 +0200 Subject: [PATCH 161/336] JS: Update test output path.resolve() and template expressions are now working. Previously they could not be resolved because Import.getImportedPath() returned a PathExpr, and these were not instances of PathExpr. --- .../test/library-tests/PathResolution/DirnameImports/main.js | 4 ++-- javascript/ql/test/library-tests/PathResolution/test.expected | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/javascript/ql/test/library-tests/PathResolution/DirnameImports/main.js b/javascript/ql/test/library-tests/PathResolution/DirnameImports/main.js index 7303809541ce..154f4e47f6a2 100644 --- a/javascript/ql/test/library-tests/PathResolution/DirnameImports/main.js +++ b/javascript/ql/test/library-tests/PathResolution/DirnameImports/main.js @@ -7,9 +7,9 @@ require(__dirname + '/../import-packages.ts'); // $ importTarget=import-packages require(__dirname + '/' + 'target.js'); // $ importTarget=DirnameImports/target.js require(path.join(__dirname, 'target.js')); // $ importTarget=DirnameImports/target.js -require(path.resolve(__dirname, 'target.js')); // $ MISSING: importTarget=DirnameImports/target.js +require(path.resolve(__dirname, 'target.js')); // $ importTarget=DirnameImports/target.js const subdir = 'nested'; require(__dirname + '/' + subdir + '/target.js'); // $ importTarget=DirnameImports/nested/target.js -require(`${__dirname}/target.js`); // $ MISSING: importTarget=DirnameImports/target.js +require(`${__dirname}/target.js`); // $ importTarget=DirnameImports/target.js diff --git a/javascript/ql/test/library-tests/PathResolution/test.expected b/javascript/ql/test/library-tests/PathResolution/test.expected index fb546892af12..4e1d2506e618 100644 --- a/javascript/ql/test/library-tests/PathResolution/test.expected +++ b/javascript/ql/test/library-tests/PathResolution/test.expected @@ -52,7 +52,9 @@ | DirnameImports/main.js:6:1:6:45 | require ... es.ts') | import-packages.ts | | DirnameImports/main.js:7:1:7:38 | require ... et.js') | DirnameImports/target.js | | DirnameImports/main.js:9:1:9:42 | require ... t.js')) | DirnameImports/target.js | +| DirnameImports/main.js:10:1:10:45 | require ... t.js')) | DirnameImports/target.js | | DirnameImports/main.js:13:1:13:48 | require ... et.js') | DirnameImports/nested/target.js | +| DirnameImports/main.js:15:1:15:33 | require ... et.js`) | DirnameImports/target.js | | Extended/src/main.ts:2:1:2:21 | import ... /file"; | Extended/lib/file.ts | | Extended/src/main.ts:3:1:3:24 | import ... le.ts"; | Extended/lib/file.ts | | Extended/src/main.ts:4:1:4:24 | import ... le.js"; | Extended/lib/file.ts | From 5de2c938d8f689be498e917b69525717ffe6532f Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Apr 2025 11:36:44 +0200 Subject: [PATCH 162/336] JS: Rename getTargetFile to getImportedFile and remove its deprecated name clash 'getTargetFile' was originally named to avoid the clash with 'getImportedFile' from a subclass. But we now just merge the two predicates. --- .../ql/lib/semmle/javascript/Modules.qll | 4 +- .../ql/lib/semmle/javascript/NodeJS.qll | 72 ------------------- .../lib/semmle/javascript/frameworks/Vue.qll | 4 +- 3 files changed, 4 insertions(+), 76 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/Modules.qll b/javascript/ql/lib/semmle/javascript/Modules.qll index 1949abe4cdcb..3ddd5132d05d 100644 --- a/javascript/ql/lib/semmle/javascript/Modules.qll +++ b/javascript/ql/lib/semmle/javascript/Modules.qll @@ -145,12 +145,12 @@ abstract class Import extends AstNode { /** * Gets the module the path of this import resolves to. */ - Module resolveImportedPath() { result.getFile() = this.getTargetFile() } + Module resolveImportedPath() { result.getFile() = this.getImportedFile() } /** * Gets the module the path of this import resolves to. */ - File getTargetFile() { result = ImportPathResolver::resolveExpr(this.getImportedPathExpr()) } + File getImportedFile() { result = ImportPathResolver::resolveExpr(this.getImportedPathExpr()) } /** * DEPRECATED. Use `getImportedModule()` instead. diff --git a/javascript/ql/lib/semmle/javascript/NodeJS.qll b/javascript/ql/lib/semmle/javascript/NodeJS.qll index 175991ffa5eb..7e9e2fdea904 100644 --- a/javascript/ql/lib/semmle/javascript/NodeJS.qll +++ b/javascript/ql/lib/semmle/javascript/NodeJS.qll @@ -327,78 +327,6 @@ class Require extends CallExpr, Import { override Module getEnclosingModule() { this = result.getAnImport() } - /** - * Gets the file that is imported by this `require`. - * - * The result can be a JavaScript file, a JSON file or a `.node` file. - * Externs files are not treated differently from other files by this predicate. - */ - deprecated File getImportedFile() { result = this.load(min(int prio | exists(this.load(prio)))) } - - /** - * Gets the file that this `require` refers to (which may not be a JavaScript file), - * using the root folder of priority `priority`. - * - * This predicate implements the specification of - * [`require.resolve`](https://nodejs.org/api/modules.html#modules_all_together), - * modified to allow additional JavaScript file extensions, such as `ts` and `jsx`. - * - * Module resolution order is modeled using the `priority` parameter as follows. - * - * Each candidate folder in which the path may be resolved is assigned - * a priority (this is actually done by `Module.searchRoot`, but we explain it - * here for completeness): - * - * - if the path starts with `'./'`, `'../'`, or `/`, it has a single candidate - * folder (the enclosing folder of the module for the former two, the file - * system root for the latter) of priority 0 - * - otherwise, candidate folders are folders of the form `/node_modules` - * such that `` is a (not necessarily proper) ancestor of the enclosing - * folder of the module which is not itself named `node_modules`; the priority - * of a candidate folder is the number of steps from the enclosing folder of - * the module to ``. - * - * To resolve an import of a path `p`, we consider each candidate folder `c` with - * priority `r` and resolve the import to the following files if they exist - * (in order of priority): - * - *
    - *
  • the file `c/p`; - *
  • the file `c/p.{tsx,ts,jsx,es6,es,mjs,cjs}`; - *
  • the file `c/p.js`; - *
  • the file `c/p.json`; - *
  • the file `c/p.node`; - *
  • if `c/p` is a folder: - *
      - *
    • if `c/p/package.json` exists and specifies a `main` module `m`: - *
        - *
      • the file `c/p/m`; - *
      • the file `c/p/m.{tsx,ts,jsx,es6,es,mjs,cjs}`; - *
      • the file `c/p/m.js`; - *
      • the file `c/p/m.json`; - *
      • the file `c/p/m.node`; - *
      - *
    • the file `c/p/index.{tsx,ts,jsx,es6,es,mjs,cjs}`; - *
    • the file `c/p/index.js`; - *
    • the file `c/p/index.json`; - *
    • the file `c/p/index.node`. - *
    - *
- * - * The first four steps are factored out into predicate `loadAsFile`, - * the remainder into `loadAsDirectory`; both make use of an auxiliary - * predicate `tryExtensions` that handles the repeated distinction between - * `.js`, `.json` and `.node`. - */ - deprecated private File load(int priority) { - exists(int r | this.getEnclosingModule().searchRoot(this.getImportedPathExpr(), _, r) | - result = loadAsFile(this, r, priority - prioritiesPerCandidate() * r) or - result = - loadAsDirectory(this, r, - priority - (prioritiesPerCandidate() * r + numberOfExtensions() + 1)) - ) - } - override DataFlow::Node getImportedModuleNode() { result = DataFlow::valueNode(this) } } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll index 2465ec668201..f571648294c2 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll @@ -442,7 +442,7 @@ module Vue { override DataFlow::SourceNode getASource() { exists(Import imprt | - imprt.getTargetFile() instanceof VueFile and + imprt.getImportedFile() instanceof VueFile and result = imprt.getImportedModuleNode() ) } @@ -494,7 +494,7 @@ module Vue { // There is no explicit `new Vue()` call in .vue files, so instead get all the imports // of the .vue file. exists(Import imprt | - imprt.getTargetFile() = file and + imprt.getImportedFile() = file and result.asSource() = imprt.getImportedModuleNode() ) } From 70a5ec56077fbfd3ea720222db8b60bfe8e75946 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Apr 2025 11:56:21 +0200 Subject: [PATCH 163/336] JS: Add package.json files in tests relying on node_modules We don't extract node_modules folders by default so these tests aren't that relevant anymore, and we no longer follow node_modules resolution rules directly. Instead, these imports are resolved based on the monorepo support which simply requires a package.json file to exist. There is not a good enough reason to support node_modules directly, so we're accepting some minor regression in these tests. --- .../library-tests/NPM/src/node_modules/a/package.json | 4 ++++ .../node_modules/nested/node_modules/a/package.json | 5 +++++ .../NPM/src/node_modules/nested/package.json | 3 +++ javascript/ql/test/library-tests/NPM/tests.expected | 10 ++++++++++ .../UnresolvableImport/UnresolvableImport.expected | 1 - .../src/sub/node_modules/mod/package.json | 3 +++ .../query-tests/NodeJS/UnresolvableImport/src/tst.js | 4 ++-- .../NodeJS/UnusedDependency/UnusedDependency.expected | 1 + 8 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 javascript/ql/test/library-tests/NPM/src/node_modules/a/package.json create mode 100644 javascript/ql/test/library-tests/NPM/src/node_modules/nested/node_modules/a/package.json create mode 100644 javascript/ql/test/library-tests/NPM/src/node_modules/nested/package.json create mode 100644 javascript/ql/test/query-tests/NodeJS/UnresolvableImport/src/sub/node_modules/mod/package.json diff --git a/javascript/ql/test/library-tests/NPM/src/node_modules/a/package.json b/javascript/ql/test/library-tests/NPM/src/node_modules/a/package.json new file mode 100644 index 000000000000..03b4185fbe2b --- /dev/null +++ b/javascript/ql/test/library-tests/NPM/src/node_modules/a/package.json @@ -0,0 +1,4 @@ +{ + "name": "a", + "main": "index.js" +} diff --git a/javascript/ql/test/library-tests/NPM/src/node_modules/nested/node_modules/a/package.json b/javascript/ql/test/library-tests/NPM/src/node_modules/nested/node_modules/a/package.json new file mode 100644 index 000000000000..5742f54f95c1 --- /dev/null +++ b/javascript/ql/test/library-tests/NPM/src/node_modules/nested/node_modules/a/package.json @@ -0,0 +1,5 @@ +{ + "name": "a", + "main": "index.js", + "description": "Nested version of package A" +} diff --git a/javascript/ql/test/library-tests/NPM/src/node_modules/nested/package.json b/javascript/ql/test/library-tests/NPM/src/node_modules/nested/package.json new file mode 100644 index 000000000000..9978c83c9fcc --- /dev/null +++ b/javascript/ql/test/library-tests/NPM/src/node_modules/nested/package.json @@ -0,0 +1,3 @@ +{ + "name": "nested" +} diff --git a/javascript/ql/test/library-tests/NPM/tests.expected b/javascript/ql/test/library-tests/NPM/tests.expected index a75c705be266..568bd0a7a821 100644 --- a/javascript/ql/test/library-tests/NPM/tests.expected +++ b/javascript/ql/test/library-tests/NPM/tests.expected @@ -6,6 +6,7 @@ dependencies importedFile | src/lib/tst2.js:1:1:1:13 | require("..") | src/index.js:0:0:0:0 | src/index.js | | src/node_modules/nested/tst3.js:1:1:1:29 | require ... odule') | src/node_modules/third-party-module/fancy.js:0:0:0:0 | src/node_modules/third-party-module/fancy.js | +| src/node_modules/nested/tst3.js:2:1:2:12 | require('a') | src/node_modules/a/index.js:0:0:0:0 | src/node_modules/a/index.js | | src/node_modules/nested/tst3.js:2:1:2:12 | require('a') | src/node_modules/nested/node_modules/a/index.js:0:0:0:0 | src/node_modules/nested/node_modules/a/index.js | | src/node_modules/tst2.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:0:0:0:0 | src/node_modules/third-party-module/fancy.js | | src/test-submodule.js:1:1:1:24 | require ... odule") | src/node_modules/parent-module/main.js:0:0:0:0 | src/node_modules/parent-module/main.js | @@ -16,6 +17,7 @@ importedFile importedModule | src/lib/tst2.js:1:1:1:13 | require("..") | src/index.js:1:1:4:0 | | | src/node_modules/nested/tst3.js:1:1:1:29 | require ... odule') | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | +| src/node_modules/nested/tst3.js:2:1:2:12 | require('a') | src/node_modules/a/index.js:1:1:1:25 | | | src/node_modules/nested/tst3.js:2:1:2:12 | require('a') | src/node_modules/nested/node_modules/a/index.js:1:1:1:25 | | | src/node_modules/tst2.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | | src/test-submodule.js:1:1:1:24 | require ... odule") | src/node_modules/parent-module/main.js:1:1:2:0 | | @@ -29,10 +31,13 @@ modules | src | test-package | src/test-submodule.js:1:1:3:0 | | | src | test-package | src/tst2.js:1:1:1:13 | | | src | test-package | src/tst.js:1:1:2:38 | | +| src/node_modules/a | a | src/node_modules/a/index.js:1:1:1:25 | | | src/node_modules/b | b | src/node_modules/b/lib/index.js:1:1:2:0 | | | src/node_modules/b | b | src/node_modules/b/lib/util.ts:1:1:2:0 | | | src/node_modules/c | c | src/node_modules/c/src/index.js:1:1:2:0 | | | src/node_modules/d | d | src/node_modules/d/main.js:1:1:2:0 | | +| src/node_modules/nested | nested | src/node_modules/nested/tst3.js:1:1:2:13 | | +| src/node_modules/nested/node_modules/a | a | src/node_modules/nested/node_modules/a/index.js:1:1:1:25 | | | src/node_modules/parent-module | parent-module | src/node_modules/parent-module/main.js:1:1:2:0 | | | src/node_modules/parent-module | parent-module | src/node_modules/parent-module/sub-module/main.js:1:1:2:0 | | | src/node_modules/parent-module/sub-module | parent-module/sub-module | src/node_modules/parent-module/sub-module/main.js:1:1:2:0 | | @@ -41,17 +46,22 @@ npm | src/node_modules/third-party-module/package.json:1:1:5:1 | {\\n "na ... y.js"\\n} | third-party-module | 23.4.0 | | src/package.json:1:1:20:1 | {\\n "na ... "\\n }\\n} | test-package | 0.1.0 | getMainModule +| src/node_modules/a/package.json:1:1:4:1 | {\\n " ... x.js"\\n} | a | src/node_modules/a/index.js:1:1:1:25 | | | src/node_modules/b/package.json:1:1:4:1 | {\\n "na ... "lib"\\n} | b | src/node_modules/b/lib/index.js:1:1:2:0 | | | src/node_modules/c/package.json:1:1:4:1 | {\\n "na ... src/"\\n} | c | src/node_modules/c/src/index.js:1:1:2:0 | | | src/node_modules/d/package.json:1:1:4:1 | {\\n "na ... main"\\n} | d | src/node_modules/d/main.js:1:1:2:0 | | +| src/node_modules/nested/node_modules/a/package.json:1:1:5:1 | {\\n " ... ge A"\\n} | a | src/node_modules/nested/node_modules/a/index.js:1:1:1:25 | | | src/node_modules/parent-module/package.json:1:1:4:1 | {\\n "na ... n.js"\\n} | parent-module | src/node_modules/parent-module/main.js:1:1:2:0 | | | src/node_modules/parent-module/sub-module/package.json:1:1:3:1 | {\\n "ma ... n.js"\\n} | parent-module/sub-module | src/node_modules/parent-module/sub-module/main.js:1:1:2:0 | | | src/node_modules/third-party-module/package.json:1:1:5:1 | {\\n "na ... y.js"\\n} | third-party-module | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | | src/package.json:1:1:20:1 | {\\n "na ... "\\n }\\n} | test-package | src/index.js:1:1:4:0 | | packageJson +| src/node_modules/a/package.json:1:1:4:1 | {\\n " ... x.js"\\n} | | src/node_modules/b/package.json:1:1:4:1 | {\\n "na ... "lib"\\n} | | src/node_modules/c/package.json:1:1:4:1 | {\\n "na ... src/"\\n} | | src/node_modules/d/package.json:1:1:4:1 | {\\n "na ... main"\\n} | +| src/node_modules/nested/node_modules/a/package.json:1:1:5:1 | {\\n " ... ge A"\\n} | +| src/node_modules/nested/package.json:1:1:3:1 | {\\n " ... sted"\\n} | | src/node_modules/parent-module/package.json:1:1:4:1 | {\\n "na ... n.js"\\n} | | src/node_modules/parent-module/sub-module/package.json:1:1:3:1 | {\\n "ma ... n.js"\\n} | | src/node_modules/third-party-module/package.json:1:1:5:1 | {\\n "na ... y.js"\\n} | diff --git a/javascript/ql/test/query-tests/NodeJS/UnresolvableImport/UnresolvableImport.expected b/javascript/ql/test/query-tests/NodeJS/UnresolvableImport/UnresolvableImport.expected index c2f977b89758..deb6b931aaaf 100644 --- a/javascript/ql/test/query-tests/NodeJS/UnresolvableImport/UnresolvableImport.expected +++ b/javascript/ql/test/query-tests/NodeJS/UnresolvableImport/UnresolvableImport.expected @@ -1,3 +1,2 @@ | src/tst.js:2:1:2:16 | require('other') | Module other cannot be resolved, and is not declared as a dependency in $@. | src/package.json:1:1:15:1 | {\\n "na ... "\\n }\\n} | package.json | -| src/tst.js:7:1:7:14 | require('mod') | Module mod cannot be resolved, and is not declared as a dependency in $@. | src/package.json:1:1:15:1 | {\\n "na ... "\\n }\\n} | package.json | | src/tst.js:8:1:8:21 | require ... lared') | Module undeclared cannot be resolved, and is not declared as a dependency in $@. | src/package.json:1:1:15:1 | {\\n "na ... "\\n }\\n} | package.json | diff --git a/javascript/ql/test/query-tests/NodeJS/UnresolvableImport/src/sub/node_modules/mod/package.json b/javascript/ql/test/query-tests/NodeJS/UnresolvableImport/src/sub/node_modules/mod/package.json new file mode 100644 index 000000000000..235a7607a8d6 --- /dev/null +++ b/javascript/ql/test/query-tests/NodeJS/UnresolvableImport/src/sub/node_modules/mod/package.json @@ -0,0 +1,3 @@ +{ + "name": "mod" +} diff --git a/javascript/ql/test/query-tests/NodeJS/UnresolvableImport/src/tst.js b/javascript/ql/test/query-tests/NodeJS/UnresolvableImport/src/tst.js index b5d9982bd4e0..e1d19155b549 100644 --- a/javascript/ql/test/query-tests/NodeJS/UnresolvableImport/src/tst.js +++ b/javascript/ql/test/query-tests/NodeJS/UnresolvableImport/src/tst.js @@ -4,8 +4,8 @@ require('foo'); // OK - declared as a dependency require('bar/sub'); // OK - 'bar' declared as a dependency require('./local'); // OK - local import require('/global'); // OK - global import -require('mod'); // $ Alert +require('mod'); // $ MISSING: Alert // this is resolved due to the package.json file named "mod", but Node.js would not find it require('undeclared'); // $ Alert require('jade!./template.jade'); // OK - WebPack loader require('imports?$=jquery!./m.js'); // OK - WebPack shim -require('react'); // OK - peer dependency \ No newline at end of file +require('react'); // OK - peer dependency diff --git a/javascript/ql/test/query-tests/NodeJS/UnusedDependency/UnusedDependency.expected b/javascript/ql/test/query-tests/NodeJS/UnusedDependency/UnusedDependency.expected index 766f71c09779..b5ffdcb40d89 100644 --- a/javascript/ql/test/query-tests/NodeJS/UnusedDependency/UnusedDependency.expected +++ b/javascript/ql/test/query-tests/NodeJS/UnusedDependency/UnusedDependency.expected @@ -3,5 +3,6 @@ | src/package.json:24:63:24:65 | "*" | Unused dependency 'not-really-used-in-install-script-because-of-substring'. | | src/package.json:28:28:28:30 | "*" | Unused dependency 'used-in-test-script'. | | src/package.json:29:30:29:32 | "*" | Unused dependency 'used-in-custom-script'. | +| src/package.json:30:56:30:58 | "*" | Unused dependency 'used-in-require-with-exclamation-mark-separator'. | | src/package.json:32:28:32:30 | "*" | Unused dependency 'used-in-mjs-require'. | | src/package.json:36:48:36:50 | "*" | Unused dependency 'used-in-dynamic-template-require-string'. | From b0f73f1cbd0912995211eb47bf02e4d5a09c7ef3 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Apr 2025 12:52:07 +0200 Subject: [PATCH 164/336] JS: Update test output now that we import .d.ts files more liberally --- .../TypeScript/RegressionTests/ImportDtsFile/test.expected | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/ql/test/library-tests/TypeScript/RegressionTests/ImportDtsFile/test.expected b/javascript/ql/test/library-tests/TypeScript/RegressionTests/ImportDtsFile/test.expected index fdbbf878689a..d8bf886588a6 100644 --- a/javascript/ql/test/library-tests/TypeScript/RegressionTests/ImportDtsFile/test.expected +++ b/javascript/ql/test/library-tests/TypeScript/RegressionTests/ImportDtsFile/test.expected @@ -1,2 +1,3 @@ | main.ts:1:1:1:52 | import ... -file"; | ./only-declaration-file | only-declaration-file.d.ts:3:1:4:0 | | +| main.ts:2:1:2:48 | import ... -file"; | ./has-javascript-file | has-javascript-file.d.ts:3:1:4:0 | | | main.ts:2:1:2:48 | import ... -file"; | ./has-javascript-file | has-javascript-file.js:1:1:2:0 | | From 425e020d6c2269bfd3db5d4260adfae38d32ab02 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 29 Apr 2025 16:09:51 +0200 Subject: [PATCH 165/336] Use code-quality-selectors in Java suite --- .../query-suite/java-code-quality.qls.expected | 1 - .../Language Abuse/TypeVariableHidesType.ql | 1 + .../Likely Bugs/Arithmetic/IntMultToLong.ql | 1 + .../Collections/WriteOnlyContainer.ql | 1 + .../Comparison/IncomparableEquals.ql | 1 + .../Comparison/InconsistentEqualsHashCode.ql | 1 + .../Comparison/MissingInstanceofInEquals.ql | 1 + .../src/Likely Bugs/Comparison/RefEqBoxed.ql | 1 + .../Likely Typos/ContradictoryTypeChecks.ql | 1 + .../Likely Typos/SuspiciousDateFormat.ql | 1 + .../Likely Bugs/Resource Leaks/CloseReader.ql | 1 + .../Likely Bugs/Resource Leaks/CloseWriter.ql | 1 + .../ql/src/codeql-suites/java-code-quality.qls | 18 ++---------------- 13 files changed, 13 insertions(+), 17 deletions(-) diff --git a/java/ql/integration-tests/java/query-suite/java-code-quality.qls.expected b/java/ql/integration-tests/java/query-suite/java-code-quality.qls.expected index 0934d4cf9966..4af6a4dd5db2 100644 --- a/java/ql/integration-tests/java/query-suite/java-code-quality.qls.expected +++ b/java/ql/integration-tests/java/query-suite/java-code-quality.qls.expected @@ -1,4 +1,3 @@ -ql/java/ql/src/Language Abuse/TypeVariableHidesType.ql ql/java/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql ql/java/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql ql/java/ql/src/Likely Bugs/Comparison/IncomparableEquals.ql diff --git a/java/ql/src/Language Abuse/TypeVariableHidesType.ql b/java/ql/src/Language Abuse/TypeVariableHidesType.ql index d411c3848e29..81da0e9703e6 100644 --- a/java/ql/src/Language Abuse/TypeVariableHidesType.ql +++ b/java/ql/src/Language Abuse/TypeVariableHidesType.ql @@ -9,6 +9,7 @@ * @tags reliability * readability * types + * quality */ import java diff --git a/java/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql b/java/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql index 31a1d8a20a13..026096b63a70 100644 --- a/java/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql +++ b/java/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql @@ -9,6 +9,7 @@ * @tags reliability * correctness * types + * quality * external/cwe/cwe-190 * external/cwe/cwe-192 * external/cwe/cwe-197 diff --git a/java/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql b/java/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql index 8c8cb6105b3e..1f4ebb3403d0 100644 --- a/java/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql +++ b/java/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql @@ -7,6 +7,7 @@ * @id java/unused-container * @tags maintainability * useless-code + * quality * external/cwe/cwe-561 */ diff --git a/java/ql/src/Likely Bugs/Comparison/IncomparableEquals.ql b/java/ql/src/Likely Bugs/Comparison/IncomparableEquals.ql index 2326ae5dd3d9..f5019373b65e 100644 --- a/java/ql/src/Likely Bugs/Comparison/IncomparableEquals.ql +++ b/java/ql/src/Likely Bugs/Comparison/IncomparableEquals.ql @@ -8,6 +8,7 @@ * @id java/equals-on-unrelated-types * @tags reliability * correctness + * quality */ import java diff --git a/java/ql/src/Likely Bugs/Comparison/InconsistentEqualsHashCode.ql b/java/ql/src/Likely Bugs/Comparison/InconsistentEqualsHashCode.ql index b788caec0e14..2fce3397346a 100644 --- a/java/ql/src/Likely Bugs/Comparison/InconsistentEqualsHashCode.ql +++ b/java/ql/src/Likely Bugs/Comparison/InconsistentEqualsHashCode.ql @@ -8,6 +8,7 @@ * @id java/inconsistent-equals-and-hashcode * @tags reliability * correctness + * quality * external/cwe/cwe-581 */ diff --git a/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql b/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql index 455ca22d6e3f..413a88bb0083 100644 --- a/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql +++ b/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql @@ -8,6 +8,7 @@ * @id java/unchecked-cast-in-equals * @tags reliability * correctness + * quality */ import java diff --git a/java/ql/src/Likely Bugs/Comparison/RefEqBoxed.ql b/java/ql/src/Likely Bugs/Comparison/RefEqBoxed.ql index b5c679f67e70..811edd9e2d7a 100644 --- a/java/ql/src/Likely Bugs/Comparison/RefEqBoxed.ql +++ b/java/ql/src/Likely Bugs/Comparison/RefEqBoxed.ql @@ -8,6 +8,7 @@ * @id java/reference-equality-of-boxed-types * @tags reliability * correctness + * quality * external/cwe/cwe-595 */ diff --git a/java/ql/src/Likely Bugs/Likely Typos/ContradictoryTypeChecks.ql b/java/ql/src/Likely Bugs/Likely Typos/ContradictoryTypeChecks.ql index 9608ec937671..a8ff61f481d9 100644 --- a/java/ql/src/Likely Bugs/Likely Typos/ContradictoryTypeChecks.ql +++ b/java/ql/src/Likely Bugs/Likely Typos/ContradictoryTypeChecks.ql @@ -9,6 +9,7 @@ * @id java/contradictory-type-checks * @tags correctness * logic + * quality */ import java diff --git a/java/ql/src/Likely Bugs/Likely Typos/SuspiciousDateFormat.ql b/java/ql/src/Likely Bugs/Likely Typos/SuspiciousDateFormat.ql index b39da1aa870d..9e24a3b7b4ec 100644 --- a/java/ql/src/Likely Bugs/Likely Typos/SuspiciousDateFormat.ql +++ b/java/ql/src/Likely Bugs/Likely Typos/SuspiciousDateFormat.ql @@ -6,6 +6,7 @@ * @precision high * @id java/suspicious-date-format * @tags correctness + * quality */ import java diff --git a/java/ql/src/Likely Bugs/Resource Leaks/CloseReader.ql b/java/ql/src/Likely Bugs/Resource Leaks/CloseReader.ql index 92da62633d8a..d210581d20c0 100644 --- a/java/ql/src/Likely Bugs/Resource Leaks/CloseReader.ql +++ b/java/ql/src/Likely Bugs/Resource Leaks/CloseReader.ql @@ -9,6 +9,7 @@ * @tags efficiency * correctness * resources + * quality * external/cwe/cwe-404 * external/cwe/cwe-772 */ diff --git a/java/ql/src/Likely Bugs/Resource Leaks/CloseWriter.ql b/java/ql/src/Likely Bugs/Resource Leaks/CloseWriter.ql index fa04de220bf4..fe23286b2e00 100644 --- a/java/ql/src/Likely Bugs/Resource Leaks/CloseWriter.ql +++ b/java/ql/src/Likely Bugs/Resource Leaks/CloseWriter.ql @@ -9,6 +9,7 @@ * @tags efficiency * correctness * resources + * quality * external/cwe/cwe-404 * external/cwe/cwe-772 */ diff --git a/java/ql/src/codeql-suites/java-code-quality.qls b/java/ql/src/codeql-suites/java-code-quality.qls index 847864606ca0..2074f9378cfd 100644 --- a/java/ql/src/codeql-suites/java-code-quality.qls +++ b/java/ql/src/codeql-suites/java-code-quality.qls @@ -1,17 +1,3 @@ - queries: . -- include: - id: - - java/contradictory-type-checks - - java/do-not-call-finalize - - java/equals-on-unrelated-types - - java/inconsistent-equals-and-hashcode - - java/input-resource-leak - - java/integer-multiplication-cast-to-long - - java/junit5-missing-nested-annotation - - java/output-resource-leak - - java/reference-equality-of-boxed-types - - java/string-replace-all-with-non-regex - - java/suspicious-date-format - - java/type-variable-hides-type - - java/unchecked-cast-in-equals - - java/unused-container \ No newline at end of file +- apply: code-quality-selectors.yml + from: codeql/suite-helpers From bb46ca7a6423669ccfe27fc35fe3af3ca8029fae Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 29 Apr 2025 16:22:37 +0200 Subject: [PATCH 166/336] Modify quality query suite selector for actions, cpp, rust and swift --- actions/ql/src/codeql-suites/actions-code-quality.qls | 4 +++- cpp/ql/src/codeql-suites/cpp-code-quality.qls | 4 +++- rust/ql/src/codeql-suites/rust-code-quality.qls | 4 +++- swift/ql/src/codeql-suites/swift-code-quality.qls | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/actions/ql/src/codeql-suites/actions-code-quality.qls b/actions/ql/src/codeql-suites/actions-code-quality.qls index 0637a088a01e..2074f9378cfd 100644 --- a/actions/ql/src/codeql-suites/actions-code-quality.qls +++ b/actions/ql/src/codeql-suites/actions-code-quality.qls @@ -1 +1,3 @@ -[] \ No newline at end of file +- queries: . +- apply: code-quality-selectors.yml + from: codeql/suite-helpers diff --git a/cpp/ql/src/codeql-suites/cpp-code-quality.qls b/cpp/ql/src/codeql-suites/cpp-code-quality.qls index 0637a088a01e..2074f9378cfd 100644 --- a/cpp/ql/src/codeql-suites/cpp-code-quality.qls +++ b/cpp/ql/src/codeql-suites/cpp-code-quality.qls @@ -1 +1,3 @@ -[] \ No newline at end of file +- queries: . +- apply: code-quality-selectors.yml + from: codeql/suite-helpers diff --git a/rust/ql/src/codeql-suites/rust-code-quality.qls b/rust/ql/src/codeql-suites/rust-code-quality.qls index 0637a088a01e..2074f9378cfd 100644 --- a/rust/ql/src/codeql-suites/rust-code-quality.qls +++ b/rust/ql/src/codeql-suites/rust-code-quality.qls @@ -1 +1,3 @@ -[] \ No newline at end of file +- queries: . +- apply: code-quality-selectors.yml + from: codeql/suite-helpers diff --git a/swift/ql/src/codeql-suites/swift-code-quality.qls b/swift/ql/src/codeql-suites/swift-code-quality.qls index 0637a088a01e..2074f9378cfd 100644 --- a/swift/ql/src/codeql-suites/swift-code-quality.qls +++ b/swift/ql/src/codeql-suites/swift-code-quality.qls @@ -1 +1,3 @@ -[] \ No newline at end of file +- queries: . +- apply: code-quality-selectors.yml + from: codeql/suite-helpers From 2515b06b2afef5c61245406401fd13dc6ed354c2 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 29 Apr 2025 16:22:57 +0200 Subject: [PATCH 167/336] Use code-quality-selectors in Go suite --- go/ql/src/InconsistentCode/LengthComparisonOffByOne.ql | 1 + go/ql/src/InconsistentCode/MissingErrorCheck.ql | 1 + .../InconsistentCode/UnhandledCloseWritableHandle.ql | 1 + go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql | 1 + go/ql/src/RedundantCode/NegativeLengthCheck.ql | 1 + go/ql/src/RedundantCode/RedundantRecover.ql | 1 + go/ql/src/codeql-suites/go-code-quality.qls | 10 ++-------- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/go/ql/src/InconsistentCode/LengthComparisonOffByOne.ql b/go/ql/src/InconsistentCode/LengthComparisonOffByOne.ql index 05a468b85179..436eb8a8fe51 100644 --- a/go/ql/src/InconsistentCode/LengthComparisonOffByOne.ql +++ b/go/ql/src/InconsistentCode/LengthComparisonOffByOne.ql @@ -8,6 +8,7 @@ * @tags reliability * correctness * logic + * quality * external/cwe/cwe-193 * @precision high */ diff --git a/go/ql/src/InconsistentCode/MissingErrorCheck.ql b/go/ql/src/InconsistentCode/MissingErrorCheck.ql index d20215172674..9acd7e136022 100644 --- a/go/ql/src/InconsistentCode/MissingErrorCheck.ql +++ b/go/ql/src/InconsistentCode/MissingErrorCheck.ql @@ -8,6 +8,7 @@ * @tags reliability * correctness * logic + * quality * @precision high */ diff --git a/go/ql/src/InconsistentCode/UnhandledCloseWritableHandle.ql b/go/ql/src/InconsistentCode/UnhandledCloseWritableHandle.ql index 211cf4b3985e..051e4644cc7c 100644 --- a/go/ql/src/InconsistentCode/UnhandledCloseWritableHandle.ql +++ b/go/ql/src/InconsistentCode/UnhandledCloseWritableHandle.ql @@ -11,6 +11,7 @@ * correctness * call * defer + * quality */ import go diff --git a/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql b/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql index 48df6a9297d6..fac236c7f036 100644 --- a/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql +++ b/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql @@ -7,6 +7,7 @@ * @tags reliability * correctness * logic + * quality * @precision high */ diff --git a/go/ql/src/RedundantCode/NegativeLengthCheck.ql b/go/ql/src/RedundantCode/NegativeLengthCheck.ql index f1ae5409c2d0..adac6fe78d97 100644 --- a/go/ql/src/RedundantCode/NegativeLengthCheck.ql +++ b/go/ql/src/RedundantCode/NegativeLengthCheck.ql @@ -9,6 +9,7 @@ * @precision very-high * @id go/negative-length-check * @tags correctness + * quality */ import go diff --git a/go/ql/src/RedundantCode/RedundantRecover.ql b/go/ql/src/RedundantCode/RedundantRecover.ql index d2138068515d..08fc06727e5c 100644 --- a/go/ql/src/RedundantCode/RedundantRecover.ql +++ b/go/ql/src/RedundantCode/RedundantRecover.ql @@ -8,6 +8,7 @@ * @id go/redundant-recover * @tags maintainability * correctness + * quality * @precision high */ diff --git a/go/ql/src/codeql-suites/go-code-quality.qls b/go/ql/src/codeql-suites/go-code-quality.qls index 84c0fe6b35b8..2074f9378cfd 100644 --- a/go/ql/src/codeql-suites/go-code-quality.qls +++ b/go/ql/src/codeql-suites/go-code-quality.qls @@ -1,9 +1,3 @@ - queries: . -- include: - id: - - go/unhandled-writable-file-close - - go/unexpected-nil-value - - go/negative-length-check - - go/redundant-recover - - go/missing-error-check - - go/index-out-of-bounds \ No newline at end of file +- apply: code-quality-selectors.yml + from: codeql/suite-helpers From d56c5225f6c0dc4c8df6560c0f293de24d8a2499 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 29 Apr 2025 16:23:08 +0200 Subject: [PATCH 168/336] Use code-quality-selectors in JS suite --- .../ql/src/Declarations/IneffectiveParameterType.ql | 1 + javascript/ql/src/Expressions/MissingAwait.ql | 1 + javascript/ql/src/LanguageFeatures/SpuriousArguments.ql | 1 + javascript/ql/src/RegExp/RegExpAlwaysMatches.ql | 1 + .../ql/src/codeql-suites/javascript-code-quality.qls | 9 ++------- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/javascript/ql/src/Declarations/IneffectiveParameterType.ql b/javascript/ql/src/Declarations/IneffectiveParameterType.ql index da8d610c974d..18899bd0c4e6 100644 --- a/javascript/ql/src/Declarations/IneffectiveParameterType.ql +++ b/javascript/ql/src/Declarations/IneffectiveParameterType.ql @@ -7,6 +7,7 @@ * @precision high * @tags correctness * typescript + * quality */ import javascript diff --git a/javascript/ql/src/Expressions/MissingAwait.ql b/javascript/ql/src/Expressions/MissingAwait.ql index 08b6c7af0bb6..d97c006a7bd1 100644 --- a/javascript/ql/src/Expressions/MissingAwait.ql +++ b/javascript/ql/src/Expressions/MissingAwait.ql @@ -5,6 +5,7 @@ * @problem.severity warning * @id js/missing-await * @tags correctness + * quality * @precision high */ diff --git a/javascript/ql/src/LanguageFeatures/SpuriousArguments.ql b/javascript/ql/src/LanguageFeatures/SpuriousArguments.ql index fd3914c90232..fd493a247a4c 100644 --- a/javascript/ql/src/LanguageFeatures/SpuriousArguments.ql +++ b/javascript/ql/src/LanguageFeatures/SpuriousArguments.ql @@ -7,6 +7,7 @@ * @tags maintainability * correctness * language-features + * quality * external/cwe/cwe-685 * @precision very-high */ diff --git a/javascript/ql/src/RegExp/RegExpAlwaysMatches.ql b/javascript/ql/src/RegExp/RegExpAlwaysMatches.ql index 04756158f555..1d063534903e 100644 --- a/javascript/ql/src/RegExp/RegExpAlwaysMatches.ql +++ b/javascript/ql/src/RegExp/RegExpAlwaysMatches.ql @@ -6,6 +6,7 @@ * @id js/regex/always-matches * @tags correctness * regular-expressions + * quality * @precision high */ diff --git a/javascript/ql/src/codeql-suites/javascript-code-quality.qls b/javascript/ql/src/codeql-suites/javascript-code-quality.qls index 5570d91c4f79..2074f9378cfd 100644 --- a/javascript/ql/src/codeql-suites/javascript-code-quality.qls +++ b/javascript/ql/src/codeql-suites/javascript-code-quality.qls @@ -1,8 +1,3 @@ - queries: . -- include: - id: - - js/missing-await - - js/regex/always-matches - - js/superfluous-trailing-arguments - - js/useless-expression - - js/ineffective-parameter-type \ No newline at end of file +- apply: code-quality-selectors.yml + from: codeql/suite-helpers From fdeac95714f4db728fe64c23e53ff6b8aee4d66f Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 29 Apr 2025 16:23:22 +0200 Subject: [PATCH 169/336] Use code-quality-selectors in Python suite --- .../query-suite/python-code-quality.qls.expected | 2 ++ python/ql/src/Functions/NonCls.ql | 1 + python/ql/src/Functions/NonSelf.ql | 1 + python/ql/src/codeql-suites/python-code-quality.qls | 8 ++------ 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/python/ql/integration-tests/query-suite/python-code-quality.qls.expected b/python/ql/integration-tests/query-suite/python-code-quality.qls.expected index 47643f6a3196..b81d300d0241 100644 --- a/python/ql/integration-tests/query-suite/python-code-quality.qls.expected +++ b/python/ql/integration-tests/query-suite/python-code-quality.qls.expected @@ -1,4 +1,6 @@ ql/python/ql/src/Functions/NonCls.ql ql/python/ql/src/Functions/NonSelf.ql +ql/python/ql/src/Functions/ReturnConsistentTupleSizes.ql ql/python/ql/src/Functions/SignatureSpecialMethods.ql ql/python/ql/src/Resources/FileNotAlwaysClosed.ql +ql/python/ql/src/Variables/LoopVariableCapture/LoopVariableCapture.ql diff --git a/python/ql/src/Functions/NonCls.ql b/python/ql/src/Functions/NonCls.ql index d36eeb9a6ec4..0808da00e0af 100644 --- a/python/ql/src/Functions/NonCls.ql +++ b/python/ql/src/Functions/NonCls.ql @@ -5,6 +5,7 @@ * @tags maintainability * readability * convention + * quality * @problem.severity recommendation * @sub-severity high * @precision high diff --git a/python/ql/src/Functions/NonSelf.ql b/python/ql/src/Functions/NonSelf.ql index cea15d3661a8..35b7af9b800a 100644 --- a/python/ql/src/Functions/NonSelf.ql +++ b/python/ql/src/Functions/NonSelf.ql @@ -5,6 +5,7 @@ * @tags maintainability * readability * convention + * quality * @problem.severity recommendation * @sub-severity high * @precision very-high diff --git a/python/ql/src/codeql-suites/python-code-quality.qls b/python/ql/src/codeql-suites/python-code-quality.qls index 3ada7e8eb4ca..2074f9378cfd 100644 --- a/python/ql/src/codeql-suites/python-code-quality.qls +++ b/python/ql/src/codeql-suites/python-code-quality.qls @@ -1,7 +1,3 @@ - queries: . -- include: - id: - - py/not-named-self - - py/not-named-cls - - py/file-not-closed - - py/special-method-wrong-signature +- apply: code-quality-selectors.yml + from: codeql/suite-helpers From e9e6d68a6ebaa4a2a9827b3c5f9fbcf50df1caca Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 29 Apr 2025 16:23:33 +0200 Subject: [PATCH 170/336] Use code-quality-selectors in Ruby suite --- .../query-suite/ruby-code-quality.qls.expected | 1 - ruby/ql/src/codeql-suites/ruby-code-quality.qls | 7 ++----- ruby/ql/src/queries/performance/DatabaseQueryInLoop.ql | 1 + ruby/ql/src/queries/variables/DeadStoreOfLocal.ql | 1 + 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/ruby/ql/integration-tests/query-suite/ruby-code-quality.qls.expected b/ruby/ql/integration-tests/query-suite/ruby-code-quality.qls.expected index 94b2f19caaa8..db6b75902201 100644 --- a/ruby/ql/integration-tests/query-suite/ruby-code-quality.qls.expected +++ b/ruby/ql/integration-tests/query-suite/ruby-code-quality.qls.expected @@ -1,3 +1,2 @@ ql/ruby/ql/src/queries/performance/DatabaseQueryInLoop.ql -ql/ruby/ql/src/queries/variables/DeadStoreOfLocal.ql ql/ruby/ql/src/queries/variables/UninitializedLocal.ql diff --git a/ruby/ql/src/codeql-suites/ruby-code-quality.qls b/ruby/ql/src/codeql-suites/ruby-code-quality.qls index 2111c6979ef9..2074f9378cfd 100644 --- a/ruby/ql/src/codeql-suites/ruby-code-quality.qls +++ b/ruby/ql/src/codeql-suites/ruby-code-quality.qls @@ -1,6 +1,3 @@ - queries: . -- include: - id: - - rb/database-query-in-loop - - rb/useless-assignment-to-local - - rb/uninitialized-local-variable \ No newline at end of file +- apply: code-quality-selectors.yml + from: codeql/suite-helpers diff --git a/ruby/ql/src/queries/performance/DatabaseQueryInLoop.ql b/ruby/ql/src/queries/performance/DatabaseQueryInLoop.ql index b17c5ecd9ba3..835fe620984d 100644 --- a/ruby/ql/src/queries/performance/DatabaseQueryInLoop.ql +++ b/ruby/ql/src/queries/performance/DatabaseQueryInLoop.ql @@ -6,6 +6,7 @@ * @precision high * @id rb/database-query-in-loop * @tags performance + * quality */ import ruby diff --git a/ruby/ql/src/queries/variables/DeadStoreOfLocal.ql b/ruby/ql/src/queries/variables/DeadStoreOfLocal.ql index 547d7d3cd899..a7b37515d7fe 100644 --- a/ruby/ql/src/queries/variables/DeadStoreOfLocal.ql +++ b/ruby/ql/src/queries/variables/DeadStoreOfLocal.ql @@ -6,6 +6,7 @@ * @problem.severity warning * @id rb/useless-assignment-to-local * @tags maintainability + * quality * external/cwe/cwe-563 * @precision medium */ From 280ce058a934640b06c1dffcf6e0e478e06be189 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Tue, 29 Apr 2025 17:38:33 +0200 Subject: [PATCH 171/336] Revert "Bazel: update `rules_kotlin` to 2.1.3" --- MODULE.bazel | 2 +- .../{2.1.3-codeql.1 => 2.0.0-codeql.1}/MODULE.bazel | 4 ++-- .../patches/codeql_add_language_version_option.patch | 12 +++++++----- .../patches/codeql_do_not_emit_jdeps.patch | 0 .../modules/rules_kotlin/2.0.0-codeql.1/source.json | 9 +++++++++ .../modules/rules_kotlin/2.1.3-codeql.1/source.json | 9 --------- .../registry/modules/rules_kotlin/metadata.json | 2 +- 7 files changed, 20 insertions(+), 18 deletions(-) rename misc/bazel/registry/modules/rules_kotlin/{2.1.3-codeql.1 => 2.0.0-codeql.1}/MODULE.bazel (93%) rename misc/bazel/registry/modules/rules_kotlin/{2.1.3-codeql.1 => 2.0.0-codeql.1}/patches/codeql_add_language_version_option.patch (77%) rename misc/bazel/registry/modules/rules_kotlin/{2.1.3-codeql.1 => 2.0.0-codeql.1}/patches/codeql_do_not_emit_jdeps.patch (100%) create mode 100644 misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/source.json delete mode 100644 misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/source.json diff --git a/MODULE.bazel b/MODULE.bazel index 7e8e36b53092..ae00bca4390d 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -24,7 +24,7 @@ bazel_dep(name = "bazel_skylib", version = "1.7.1") bazel_dep(name = "abseil-cpp", version = "20240116.1", repo_name = "absl") bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json") bazel_dep(name = "fmt", version = "10.0.0") -bazel_dep(name = "rules_kotlin", version = "2.1.3-codeql.1") +bazel_dep(name = "rules_kotlin", version = "2.0.0-codeql.1") bazel_dep(name = "gazelle", version = "0.40.0") bazel_dep(name = "rules_dotnet", version = "0.17.4") bazel_dep(name = "googletest", version = "1.14.0.bcr.1") diff --git a/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/MODULE.bazel b/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/MODULE.bazel similarity index 93% rename from misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/MODULE.bazel rename to misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/MODULE.bazel index 41bef52cf9f6..6c11301e2340 100644 --- a/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/MODULE.bazel +++ b/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/MODULE.bazel @@ -1,11 +1,11 @@ module( name = "rules_kotlin", - version = "2.1.3-codeql.1", + version = "2.0.0-codeql.1", compatibility_level = 1, repo_name = "rules_kotlin", ) -bazel_dep(name = "platforms", version = "0.0.11") +bazel_dep(name = "platforms", version = "0.0.10") bazel_dep(name = "bazel_skylib", version = "1.7.1") bazel_dep(name = "rules_java", version = "7.2.0") bazel_dep(name = "rules_python", version = "0.23.1") diff --git a/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_add_language_version_option.patch b/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_add_language_version_option.patch similarity index 77% rename from misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_add_language_version_option.patch rename to misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_add_language_version_option.patch index b0bf85d4faef..d5716daba07b 100644 --- a/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_add_language_version_option.patch +++ b/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_add_language_version_option.patch @@ -1,11 +1,13 @@ +We need to build different extractor variants with different -language-version options, which is not allowed +in current kotlin_rules diff --git a/src/main/starlark/core/options/opts.kotlinc.bzl b/src/main/starlark/core/options/opts.kotlinc.bzl -index 76df826..ef2d6ca 100644 +index 5e1461b..b93e6aa 100644 --- a/src/main/starlark/core/options/opts.kotlinc.bzl +++ b/src/main/starlark/core/options/opts.kotlinc.bzl @@ -33,6 +33,11 @@ def _map_jdk_release_to_flag(version): return None return ["-Xjdk-release=%s" % version] - + +def _map_language_version_to_flag(version): + if not version: + return None @@ -14,7 +16,7 @@ index 76df826..ef2d6ca 100644 _KOPTS_ALL = { "warn": struct( args = dict( -@@ -429,6 +434,15 @@ _KOPTS_ALL = { +@@ -417,6 +422,15 @@ _KOPTS_ALL = { value_to_flag = None, map_value_to_flag = _map_jdk_release_to_flag, ), @@ -28,5 +30,5 @@ index 76df826..ef2d6ca 100644 + map_value_to_flag = _map_language_version_to_flag, + ), } - - def _merge(key, rule_defined): + + # Filters out options that are not available in current compiler release \ No newline at end of file diff --git a/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_do_not_emit_jdeps.patch b/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_do_not_emit_jdeps.patch similarity index 100% rename from misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_do_not_emit_jdeps.patch rename to misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_do_not_emit_jdeps.patch diff --git a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/source.json b/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/source.json new file mode 100644 index 000000000000..96d828e3455a --- /dev/null +++ b/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/source.json @@ -0,0 +1,9 @@ +{ + "integrity": "sha256-2JcjzJ67t72y66yhr30jg+B0YVZDz5ejZrdYp2t9xEM=", + "url": "https://github.com/bazelbuild/rules_kotlin/releases/download/v2.0.0/rules_kotlin-v2.0.0.tar.gz", + "patches": { + "codeql_do_not_emit_jdeps.patch": "sha256-1ir4Aio1SICxnj1wafQ0GefT/m7bwn2n+SQwq19V3A8=", + "codeql_add_language_version_option.patch": "sha256-t8Fm0bYZ4Q4vTqcoXZjyK4WPEoAafjE4whJLNnrnRbg=" + }, + "patch_strip": 1 +} diff --git a/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/source.json b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/source.json deleted file mode 100644 index 8abac8eb4bd1..000000000000 --- a/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/source.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "integrity": "sha256-4USKVrJGJAeyaI3qht9cN1s2oJkb1HjC3dlMlxaBJeI=", - "url": "https://github.com/bazelbuild/rules_kotlin/releases/download/v2.1.3/rules_kotlin-v2.1.3.tar.gz", - "patches": { - "codeql_do_not_emit_jdeps.patch": "sha256-1ir4Aio1SICxnj1wafQ0GefT/m7bwn2n+SQwq19V3A8=", - "codeql_add_language_version_option.patch": "sha256-F7RthnrO6kJlCNcQ76L1Utqll2OwyeFZ/HmT82NwgB4=" - }, - "patch_strip": 1 -} diff --git a/misc/bazel/registry/modules/rules_kotlin/metadata.json b/misc/bazel/registry/modules/rules_kotlin/metadata.json index dace87c72d1c..ac259b2e729a 100644 --- a/misc/bazel/registry/modules/rules_kotlin/metadata.json +++ b/misc/bazel/registry/modules/rules_kotlin/metadata.json @@ -21,7 +21,7 @@ "github:bazelbuild/rules_kotlin" ], "versions": [ - "2.1.3-codeql.1" + "2.0.0-codeql.1" ], "yanked_versions": {} } From eb7cd3d221919d99fd8443c7b99d7eb160b2d1a5 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 30 Apr 2025 08:54:57 +0200 Subject: [PATCH 172/336] Ruby: disable diff-informed mode on regex queries These queries were failing in `codeql test run --check-diff-informed` because they can select locations inside the regex. Until that can be fixed, diff-informed mode is disabled for these queries. --- .../ruby/security/regexp/MissingFullAnchorQuery.qll | 10 ---------- .../ruby/security/regexp/PolynomialReDoSQuery.qll | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/security/regexp/MissingFullAnchorQuery.qll b/ruby/ql/lib/codeql/ruby/security/regexp/MissingFullAnchorQuery.qll index d511c6f3fbf8..febfa0712d9b 100644 --- a/ruby/ql/lib/codeql/ruby/security/regexp/MissingFullAnchorQuery.qll +++ b/ruby/ql/lib/codeql/ruby/security/regexp/MissingFullAnchorQuery.qll @@ -17,16 +17,6 @@ private module MissingFullAnchorConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink instanceof Sink } predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } - - predicate observeDiffInformedIncrementalMode() { any() } - - Location getASelectedSinkLocation(DataFlow::Node sink) { - result = sink.(Sink).getLocation() - or - result = sink.(Sink).getCallNode().getLocation() - or - result = sink.(Sink).getRegex().getLocation() - } } /** diff --git a/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSQuery.qll b/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSQuery.qll index 562b5dad37bf..98a42fcf5e7c 100644 --- a/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSQuery.qll +++ b/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSQuery.qll @@ -18,16 +18,6 @@ private module PolynomialReDoSConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink instanceof Sink } predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } - - predicate observeDiffInformedIncrementalMode() { any() } - - Location getASelectedSinkLocation(DataFlow::Node sink) { - result = sink.(Sink).getLocation() - or - result = sink.(Sink).getHighlight().getLocation() - or - result = sink.(Sink).getRegExp().getLocation() - } } /** From 97532525d85c838d58625247905ca2f881cac144 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 24 Apr 2025 11:03:59 +0200 Subject: [PATCH 173/336] Rust: Crate graph extraction workarounds --- .../codeql/rust/internal/PathResolution.qll | 35 +++++++++++++++-- rust/ql/lib/codeql/rust/internal/Type.qll | 39 ++++++++++++++----- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index a6cc51a21c54..37a895c0dcd4 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -323,7 +323,16 @@ abstract private class AssocItemNode extends ItemNode, AssocItem { private class ConstItemNode extends AssocItemNode instanceof Const { override string getName() { result = Const.super.getName().getText() } - override predicate hasImplementation() { super.hasBody() } + override predicate hasImplementation() { + super.hasBody() + or + // for trait items from library code, we do not currently know if they + // have default implementations or not, so we assume they do + exists(TraitItemNode t | + this = t.getAnAssocItem() and + not this.fromSource() + ) + } override Namespace getNamespace() { result.isValue() } @@ -359,7 +368,16 @@ private class VariantItemNode extends ItemNode instanceof Variant { class FunctionItemNode extends AssocItemNode instanceof Function { override string getName() { result = Function.super.getName().getText() } - override predicate hasImplementation() { super.hasBody() } + override predicate hasImplementation() { + super.hasBody() + or + // for trait items from library code, we do not currently know if they + // have default implementations or not, so we assume they do + exists(TraitItemNode t | + this = t.getAnAssocItem() and + not this.fromSource() + ) + } override Namespace getNamespace() { result.isValue() } @@ -862,6 +880,12 @@ class RelevantPath extends Path { this.getQualifier().(RelevantPath).isCratePath("$crate", _) and this.getText() = name } + + // TODO: Remove once the crate graph extractor generates publicly visible paths + predicate requiresExtractorWorkaround() { + not this.fromSource() and + this = any(RelevantPath p).getQualifier() + } } private predicate isModule(ItemNode m) { m instanceof Module } @@ -1029,6 +1053,7 @@ pragma[nomagic] private ItemNode resolvePathPrivate( RelevantPath path, ModuleLikeNode itemParent, ModuleLikeNode pathParent ) { + not path.requiresExtractorWorkaround() and result = resolvePath1(path) and itemParent = result.getImmediateParentModule() and not result.isPublic() and @@ -1062,7 +1087,11 @@ private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) { cached ItemNode resolvePath(RelevantPath path) { result = resolvePath1(path) and - result.isPublic() + ( + result.isPublic() + or + path.requiresExtractorWorkaround() + ) or exists(ModuleLikeNode itemParent, ModuleLikeNode pathParent | result = resolvePathPrivate(path, itemParent, pathParent) and diff --git a/rust/ql/lib/codeql/rust/internal/Type.qll b/rust/ql/lib/codeql/rust/internal/Type.qll index 9e063d215161..5abada5726d3 100644 --- a/rust/ql/lib/codeql/rust/internal/Type.qll +++ b/rust/ql/lib/codeql/rust/internal/Type.qll @@ -29,7 +29,26 @@ newtype TType = abstract class Type extends TType { /** Gets the method `name` belonging to this type, if any. */ pragma[nomagic] - abstract Function getMethod(string name); + final Function getMethod(string name) { + result = this.getAMethod(name) and + ( + // when a method exists in both source code and in library code, it is because + // we also extracted the source code as library code, and hence we only want + // the method from source code + result.fromSource() + or + not this.getAMethod(name).fromSource() + ) + } + + /** + * Gets a method `name` belonging to this type, if any. + * + * Multiple methods may exist with the same name when it exists in both + * source code and in library code. + */ + pragma[nomagic] + abstract Function getAMethod(string name); /** Gets the struct field `name` belonging to this type, if any. */ pragma[nomagic] @@ -74,7 +93,7 @@ abstract class Type extends TType { abstract private class StructOrEnumType extends Type { abstract ItemNode asItemNode(); - final override Function getMethod(string name) { + final override Function getAMethod(string name) { result = this.asItemNode().getASuccessor(name) and exists(ImplOrTraitItemNode impl | result = impl.getAnAssocItem() | impl instanceof Trait @@ -138,7 +157,7 @@ class TraitType extends Type, TTrait { TraitType() { this = TTrait(trait) } - override Function getMethod(string name) { result = trait.(ItemNode).getASuccessor(name) } + override Function getAMethod(string name) { result = trait.(ItemNode).getASuccessor(name) } override StructField getStructField(string name) { none() } @@ -220,7 +239,7 @@ class ImplType extends Type, TImpl { ImplType() { this = TImpl(impl) } - override Function getMethod(string name) { result = impl.(ItemNode).getASuccessor(name) } + override Function getAMethod(string name) { result = impl.(ItemNode).getASuccessor(name) } override StructField getStructField(string name) { none() } @@ -247,7 +266,7 @@ class ImplType extends Type, TImpl { class ArrayType extends Type, TArrayType { ArrayType() { this = TArrayType() } - override Function getMethod(string name) { none() } + override Function getAMethod(string name) { none() } override StructField getStructField(string name) { none() } @@ -273,7 +292,7 @@ class ArrayType extends Type, TArrayType { class RefType extends Type, TRefType { RefType() { this = TRefType() } - override Function getMethod(string name) { none() } + override Function getAMethod(string name) { none() } override StructField getStructField(string name) { none() } @@ -318,7 +337,7 @@ class TypeParamTypeParameter extends TypeParameter, TTypeParamTypeParameter { TypeParam getTypeParam() { result = typeParam } - override Function getMethod(string name) { + override Function getAMethod(string name) { // NOTE: If the type parameter has trait bounds, then this finds methods // on the bounding traits. result = typeParam.(ItemNode).getASuccessor(name) @@ -377,7 +396,7 @@ class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypePara int getIndex() { traitAliasIndex(_, result, typeAlias) } - override Function getMethod(string name) { none() } + override Function getAMethod(string name) { none() } override string toString() { result = typeAlias.getName().getText() } @@ -388,7 +407,7 @@ class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypePara /** An implicit reference type parameter. */ class RefTypeParameter extends TypeParameter, TRefTypeParameter { - override Function getMethod(string name) { none() } + override Function getAMethod(string name) { none() } override string toString() { result = "&T" } @@ -411,7 +430,7 @@ class SelfTypeParameter extends TypeParameter, TSelfTypeParameter { override TypeMention getABaseTypeMention() { result = trait } - override Function getMethod(string name) { + override Function getAMethod(string name) { // The `Self` type parameter is an implementation of the trait, so it has // all the trait's methods. result = trait.(ItemNode).getASuccessor(name) From 52bd99b852280eae52e31d13e8861eb44bb0f230 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 30 Apr 2025 11:01:29 +0200 Subject: [PATCH 174/336] Address review comments --- .../lib/codeql/rust/internal/CachedStages.qll | 2 +- .../codeql/rust/internal/PathResolution.qll | 55 ++++++++++++------- rust/ql/lib/codeql/rust/internal/Type.qll | 39 ++++--------- 3 files changed, 47 insertions(+), 49 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/CachedStages.qll b/rust/ql/lib/codeql/rust/internal/CachedStages.qll index 4041b2731f97..2a7447ed7a3f 100644 --- a/rust/ql/lib/codeql/rust/internal/CachedStages.qll +++ b/rust/ql/lib/codeql/rust/internal/CachedStages.qll @@ -120,7 +120,7 @@ module Stages { or exists(resolvePath(_)) or - exists(any(ItemNode i).getASuccessor(_)) + exists(any(ItemNode i).getASuccessorFull(_)) or exists(any(ItemNode i).getASuccessorRec(_)) or diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index 37a895c0dcd4..5bc45afecf17 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -172,9 +172,14 @@ abstract class ItemNode extends Locatable { result = this.(TypeParamItemNode).resolveABound().getASuccessorRec(name).(AssocItemNode) } - /** Gets a successor named `name` of this item, if any. */ + /** + * Gets a successor named `name` of this item, if any. + * + * Whenever a function exists in both source code and in library code, + * both are included + */ cached - ItemNode getASuccessor(string name) { + ItemNode getASuccessorFull(string name) { Stages::PathResolutionStage::ref() and result = this.getASuccessorRec(name) or @@ -202,6 +207,22 @@ abstract class ItemNode extends Locatable { result.(CrateItemNode).isPotentialDollarCrateTarget() } + /** Gets a successor named `name` of this item, if any. */ + pragma[nomagic] + ItemNode getASuccessor(string name) { + result = this.getASuccessorFull(name) and + ( + // when a function exists in both source code and in library code, it is because + // we also extracted the source code as library code, and hence we only want + // the function from source code + result.fromSource() + or + not result instanceof Function + or + not this.getASuccessorFull(name).(Function).fromSource() + ) + } + /** Gets the location of this item. */ Location getLocation() { result = super.getLocation() } } @@ -234,7 +255,7 @@ abstract private class ModuleLikeNode extends ItemNode { private class SourceFileItemNode extends ModuleLikeNode, SourceFile { pragma[nomagic] ModuleLikeNode getSuper() { - result = any(ModuleItemNode mod | fileImport(mod, this)).getASuccessor("super") + result = any(ModuleItemNode mod | fileImport(mod, this)).getASuccessorFull("super") } override string getName() { result = "(source file)" } @@ -297,7 +318,7 @@ class CrateItemNode extends ItemNode instanceof Crate { predicate isPotentialDollarCrateTarget() { exists(string name, RelevantPath p | p.isDollarCrateQualifiedPath(name) and - exists(this.getASuccessor(name)) + exists(this.getASuccessorFull(name)) ) } @@ -328,10 +349,8 @@ private class ConstItemNode extends AssocItemNode instanceof Const { or // for trait items from library code, we do not currently know if they // have default implementations or not, so we assume they do - exists(TraitItemNode t | - this = t.getAnAssocItem() and - not this.fromSource() - ) + not this.fromSource() and + this = any(TraitItemNode t).getAnAssocItem() } override Namespace getNamespace() { result.isValue() } @@ -373,10 +392,8 @@ class FunctionItemNode extends AssocItemNode instanceof Function { or // for trait items from library code, we do not currently know if they // have default implementations or not, so we assume they do - exists(TraitItemNode t | - this = t.getAnAssocItem() and - not this.fromSource() - ) + not this.fromSource() and + this = any(TraitItemNode t).getAnAssocItem() } override Namespace getNamespace() { result.isValue() } @@ -940,8 +957,8 @@ private predicate unqualifiedPathLookup(ItemNode encl, string name, Namespace ns } pragma[nomagic] -private ItemNode getASuccessor(ItemNode pred, string name, Namespace ns) { - result = pred.getASuccessor(name) and +private ItemNode getASuccessorFull(ItemNode pred, string name, Namespace ns) { + result = pred.getASuccessorFull(name) and ns = result.getNamespace() } @@ -978,7 +995,7 @@ private predicate keywordLookup(ItemNode encl, string name, Namespace ns, Releva pragma[nomagic] private ItemNode unqualifiedPathLookup(RelevantPath p, Namespace ns) { - exists(ItemNode encl, string name | result = getASuccessor(encl, name, ns) | + exists(ItemNode encl, string name | result = getASuccessorFull(encl, name, ns) | unqualifiedPathLookup(encl, name, ns, p) or keywordLookup(encl, name, ns, p) @@ -1002,7 +1019,7 @@ private ItemNode resolvePath0(RelevantPath path, Namespace ns) { or exists(ItemNode q, string name | q = resolvePathQualifier(path, name) and - result = getASuccessor(q, name, ns) + result = getASuccessorFull(q, name, ns) ) or result = resolveUseTreeListItem(_, _, path) and @@ -1127,12 +1144,12 @@ private ItemNode resolveUseTreeListItem(Use use, UseTree tree, RelevantPath path mid = resolveUseTreeListItem(use, midTree) and tree = midTree.getUseTreeList().getAUseTree() and isUseTreeSubPathUnqualified(tree, path, pragma[only_bind_into](name)) and - result = mid.getASuccessor(pragma[only_bind_into](name)) + result = mid.getASuccessorFull(pragma[only_bind_into](name)) ) or exists(ItemNode q, string name | q = resolveUseTreeListItemQualifier(use, tree, path, name) and - result = q.getASuccessor(name) + result = q.getASuccessorFull(name) ) } @@ -1162,7 +1179,7 @@ private predicate useImportEdge(Use use, string name, ItemNode item) { then exists(ItemNode encl, Namespace ns | encl.getADescendant() = use and - item = getASuccessor(used, name, ns) and + item = getASuccessorFull(used, name, ns) and // glob imports can be shadowed not declares(encl, ns, name) and not name = ["super", "self", "Self", "$crate", "crate"] diff --git a/rust/ql/lib/codeql/rust/internal/Type.qll b/rust/ql/lib/codeql/rust/internal/Type.qll index 5abada5726d3..9e063d215161 100644 --- a/rust/ql/lib/codeql/rust/internal/Type.qll +++ b/rust/ql/lib/codeql/rust/internal/Type.qll @@ -29,26 +29,7 @@ newtype TType = abstract class Type extends TType { /** Gets the method `name` belonging to this type, if any. */ pragma[nomagic] - final Function getMethod(string name) { - result = this.getAMethod(name) and - ( - // when a method exists in both source code and in library code, it is because - // we also extracted the source code as library code, and hence we only want - // the method from source code - result.fromSource() - or - not this.getAMethod(name).fromSource() - ) - } - - /** - * Gets a method `name` belonging to this type, if any. - * - * Multiple methods may exist with the same name when it exists in both - * source code and in library code. - */ - pragma[nomagic] - abstract Function getAMethod(string name); + abstract Function getMethod(string name); /** Gets the struct field `name` belonging to this type, if any. */ pragma[nomagic] @@ -93,7 +74,7 @@ abstract class Type extends TType { abstract private class StructOrEnumType extends Type { abstract ItemNode asItemNode(); - final override Function getAMethod(string name) { + final override Function getMethod(string name) { result = this.asItemNode().getASuccessor(name) and exists(ImplOrTraitItemNode impl | result = impl.getAnAssocItem() | impl instanceof Trait @@ -157,7 +138,7 @@ class TraitType extends Type, TTrait { TraitType() { this = TTrait(trait) } - override Function getAMethod(string name) { result = trait.(ItemNode).getASuccessor(name) } + override Function getMethod(string name) { result = trait.(ItemNode).getASuccessor(name) } override StructField getStructField(string name) { none() } @@ -239,7 +220,7 @@ class ImplType extends Type, TImpl { ImplType() { this = TImpl(impl) } - override Function getAMethod(string name) { result = impl.(ItemNode).getASuccessor(name) } + override Function getMethod(string name) { result = impl.(ItemNode).getASuccessor(name) } override StructField getStructField(string name) { none() } @@ -266,7 +247,7 @@ class ImplType extends Type, TImpl { class ArrayType extends Type, TArrayType { ArrayType() { this = TArrayType() } - override Function getAMethod(string name) { none() } + override Function getMethod(string name) { none() } override StructField getStructField(string name) { none() } @@ -292,7 +273,7 @@ class ArrayType extends Type, TArrayType { class RefType extends Type, TRefType { RefType() { this = TRefType() } - override Function getAMethod(string name) { none() } + override Function getMethod(string name) { none() } override StructField getStructField(string name) { none() } @@ -337,7 +318,7 @@ class TypeParamTypeParameter extends TypeParameter, TTypeParamTypeParameter { TypeParam getTypeParam() { result = typeParam } - override Function getAMethod(string name) { + override Function getMethod(string name) { // NOTE: If the type parameter has trait bounds, then this finds methods // on the bounding traits. result = typeParam.(ItemNode).getASuccessor(name) @@ -396,7 +377,7 @@ class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypePara int getIndex() { traitAliasIndex(_, result, typeAlias) } - override Function getAMethod(string name) { none() } + override Function getMethod(string name) { none() } override string toString() { result = typeAlias.getName().getText() } @@ -407,7 +388,7 @@ class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypePara /** An implicit reference type parameter. */ class RefTypeParameter extends TypeParameter, TRefTypeParameter { - override Function getAMethod(string name) { none() } + override Function getMethod(string name) { none() } override string toString() { result = "&T" } @@ -430,7 +411,7 @@ class SelfTypeParameter extends TypeParameter, TSelfTypeParameter { override TypeMention getABaseTypeMention() { result = trait } - override Function getAMethod(string name) { + override Function getMethod(string name) { // The `Self` type parameter is an implementation of the trait, so it has // all the trait's methods. result = trait.(ItemNode).getASuccessor(name) From ba89a5de6f11b2a0fe354bc01b953d36c52acad1 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 30 Apr 2025 11:38:07 +0200 Subject: [PATCH 175/336] Codegen: make missing `codeql` error clearer --- misc/codegen/generators/qlgen.py | 10 ++++++++++ misc/codegen/test/test_qlgen.py | 24 +++++++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/misc/codegen/generators/qlgen.py b/misc/codegen/generators/qlgen.py index eefcad3e943b..05c945f34622 100755 --- a/misc/codegen/generators/qlgen.py +++ b/misc/codegen/generators/qlgen.py @@ -24,6 +24,7 @@ import logging import pathlib import re +import shutil import subprocess import typing import itertools @@ -257,6 +258,15 @@ def format(codeql, files): if not ql_files: return format_cmd = [codeql, "query", "format", "--in-place", "--"] + ql_files + if "/" in codeql: + if not pathlib.Path(codeql).exists(): + raise FormatError(f"Provided CodeQL binary `{codeql}` does not exist") + else: + codeql_path = shutil.which(codeql) + if not codeql_path: + raise FormatError( + f"`{codeql}` not found in PATH. Either install it, or pass `-- --codeql-binary` with a full path") + codeql = codeql_path res = subprocess.run(format_cmd, stderr=subprocess.PIPE, text=True) if res.returncode: for line in res.stderr.splitlines(): diff --git a/misc/codegen/test/test_qlgen.py b/misc/codegen/test/test_qlgen.py index 01dee2519998..75e587fbd5eb 100644 --- a/misc/codegen/test/test_qlgen.py +++ b/misc/codegen/test/test_qlgen.py @@ -52,6 +52,8 @@ def qlgen_opts(opts): opts.ql_format = True opts.root_dir = paths.root_dir opts.force = False + opts.codeql_binary = "./my_fake_codeql" + pathlib.Path(opts.codeql_binary).touch() return opts @@ -499,7 +501,6 @@ def test_class_dir_imports(generate_import_list): def test_format(opts, generate, render_manager, run_mock): - opts.codeql_binary = "my_fake_codeql" run_mock.return_value.stderr = "some\nlines\n" render_manager.written = [ pathlib.Path("x", "foo.ql"), @@ -508,13 +509,12 @@ def test_format(opts, generate, render_manager, run_mock): ] generate([schema.Class('A')]) assert run_mock.mock_calls == [ - mock.call(["my_fake_codeql", "query", "format", "--in-place", "--", "x/foo.ql", "bar.qll"], + mock.call([opts.codeql_binary, "query", "format", "--in-place", "--", "x/foo.ql", "bar.qll"], stderr=subprocess.PIPE, text=True), ] def test_format_error(opts, generate, render_manager, run_mock): - opts.codeql_binary = "my_fake_codeql" run_mock.return_value.stderr = "some\nlines\n" run_mock.return_value.returncode = 1 render_manager.written = [ @@ -526,6 +526,24 @@ def test_format_error(opts, generate, render_manager, run_mock): generate([schema.Class('A')]) +def test_format_no_codeql(opts, generate, render_manager, run_mock): + pathlib.Path(opts.codeql_binary).unlink() + render_manager.written = [ + pathlib.Path("bar.qll"), + ] + with pytest.raises(qlgen.FormatError): + generate([schema.Class('A')]) + + +def test_format_no_codeql_in_path(opts, generate, render_manager, run_mock): + opts.codeql_binary = "my_fake_codeql" + render_manager.written = [ + pathlib.Path("bar.qll"), + ] + with pytest.raises(qlgen.FormatError): + generate([schema.Class('A')]) + + @pytest.mark.parametrize("force", [False, True]) def test_manage_parameters(opts, generate, renderer, force): opts.force = force From 9958cc778470292da841a1f255d85919aefaf4aa Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 30 Apr 2025 11:43:03 +0200 Subject: [PATCH 176/336] Codegen: consider windows paths in local `codeql` binary heuristic --- misc/codegen/generators/qlgen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/codegen/generators/qlgen.py b/misc/codegen/generators/qlgen.py index 05c945f34622..7e898135d01f 100755 --- a/misc/codegen/generators/qlgen.py +++ b/misc/codegen/generators/qlgen.py @@ -258,7 +258,7 @@ def format(codeql, files): if not ql_files: return format_cmd = [codeql, "query", "format", "--in-place", "--"] + ql_files - if "/" in codeql: + if "/" in codeql or "\\" in codeql: if not pathlib.Path(codeql).exists(): raise FormatError(f"Provided CodeQL binary `{codeql}` does not exist") else: From da5d7991521a243ae8accedf99b7c60bba2093ee Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Apr 2025 11:59:47 +0200 Subject: [PATCH 177/336] JS: Change note --- javascript/ql/src/change-notes/2025-04-30-promise-all.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 javascript/ql/src/change-notes/2025-04-30-promise-all.md diff --git a/javascript/ql/src/change-notes/2025-04-30-promise-all.md b/javascript/ql/src/change-notes/2025-04-30-promise-all.md new file mode 100644 index 000000000000..a50e31ea01d0 --- /dev/null +++ b/javascript/ql/src/change-notes/2025-04-30-promise-all.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- +* Type information is now propagated more precisely through `Promise.all()` calls, + leading to more resolved calls and more sources and sinks being detected. From f6fae7ad60ad011e60ba072d9b7e68ac42fbcd42 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Wed, 30 Apr 2025 13:33:31 +0200 Subject: [PATCH 178/336] Added test cases for `cmd`, `which` and `asyncExec` --- .../test/library-tests/frameworks/Shelljs/ShellJS.expected | 1 + javascript/ql/test/library-tests/frameworks/Shelljs/tst.js | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/javascript/ql/test/library-tests/frameworks/Shelljs/ShellJS.expected b/javascript/ql/test/library-tests/frameworks/Shelljs/ShellJS.expected index 003ae3f442f8..de70e7a1d0af 100644 --- a/javascript/ql/test/library-tests/frameworks/Shelljs/ShellJS.expected +++ b/javascript/ql/test/library-tests/frameworks/Shelljs/ShellJS.expected @@ -56,6 +56,7 @@ test_FileSystemAccess | tst.js:60:1:60:41 | shelljs ... cement) | | tst.js:61:1:61:17 | shelljs.cat(file) | test_MissingFileSystemAccess +| tst.js:65:15:65:18 | file | test_SystemCommandExecution | tst.js:14:1:14:27 | shelljs ... ts, cb) | | tst.js:60:1:60:51 | shelljs ... ec(cmd) | diff --git a/javascript/ql/test/library-tests/frameworks/Shelljs/tst.js b/javascript/ql/test/library-tests/frameworks/Shelljs/tst.js index 9e7905c98477..2bbcd51f5821 100644 --- a/javascript/ql/test/library-tests/frameworks/Shelljs/tst.js +++ b/javascript/ql/test/library-tests/frameworks/Shelljs/tst.js @@ -59,3 +59,10 @@ shelljs.uniq(opts, file1, file2); shelljs.cat(file).sed(regex, replacement).exec(cmd); shelljs.cat(file).exec(cmd); + +shelljs.cmd(cmd, arg1, arg2, options); +shelljs.cmd(cmd); +shelljs.which(file); + +const shelljssync = require("async-shelljs"); +shelljssync.asyncExec(cmd, opts, cb); From 25d04f1cdd11e5bf6372924363035ac2cdb4895a Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Wed, 30 Apr 2025 13:35:17 +0200 Subject: [PATCH 179/336] Added support for `shelljs.which` --- .../ql/lib/semmle/javascript/frameworks/ShellJS.qll | 9 ++++++--- .../library-tests/frameworks/Shelljs/ShellJS.expected | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll index 9f3eeb6e0dc9..91b18a1779d1 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll @@ -14,7 +14,8 @@ module ShellJS { shellJSMember() .getMember([ "exec", "cd", "cp", "touch", "chmod", "pushd", "find", "ls", "ln", "mkdir", "mv", - "rm", "cat", "head", "sort", "tail", "uniq", "grep", "sed", "to", "toEnd", "echo" + "rm", "cat", "head", "sort", "tail", "uniq", "grep", "sed", "to", "toEnd", "echo", + "which", ]) .getReturn() } @@ -99,7 +100,8 @@ module ShellJS { */ private class ShellJSGenericFileAccess extends FileSystemAccess, ShellJSCall { ShellJSGenericFileAccess() { - name = ["cd", "cp", "touch", "chmod", "pushd", "find", "ls", "ln", "mkdir", "mv", "rm"] + name = + ["cd", "cp", "touch", "chmod", "pushd", "find", "ls", "ln", "mkdir", "mv", "rm", "which"] } override DataFlow::Node getAPathArgument() { result = this.getAnArgument() } @@ -111,7 +113,8 @@ module ShellJS { private class ShellJSFilenameSource extends FileNameSource, ShellJSCall { ShellJSFilenameSource() { name = "find" or - name = "ls" + name = "ls" or + name = "which" } } diff --git a/javascript/ql/test/library-tests/frameworks/Shelljs/ShellJS.expected b/javascript/ql/test/library-tests/frameworks/Shelljs/ShellJS.expected index de70e7a1d0af..4ca9f088bf49 100644 --- a/javascript/ql/test/library-tests/frameworks/Shelljs/ShellJS.expected +++ b/javascript/ql/test/library-tests/frameworks/Shelljs/ShellJS.expected @@ -55,8 +55,8 @@ test_FileSystemAccess | tst.js:60:1:60:17 | shelljs.cat(file) | | tst.js:60:1:60:41 | shelljs ... cement) | | tst.js:61:1:61:17 | shelljs.cat(file) | +| tst.js:65:1:65:19 | shelljs.which(file) | test_MissingFileSystemAccess -| tst.js:65:15:65:18 | file | test_SystemCommandExecution | tst.js:14:1:14:27 | shelljs ... ts, cb) | | tst.js:60:1:60:51 | shelljs ... ec(cmd) | @@ -67,3 +67,4 @@ test_FileNameSource | tst.js:25:1:25:22 | shelljs ... , file) | | tst.js:26:1:26:30 | shelljs ... file2) | | tst.js:27:1:27:24 | shelljs ... file2) | +| tst.js:65:1:65:19 | shelljs.which(file) | From 18cea2d6a5dec92818986f34d5730f769926ead8 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Wed, 30 Apr 2025 13:37:02 +0200 Subject: [PATCH 180/336] Added support for `shelljs.cmd` and `async-shelljs.asyncExec` --- .../semmle/javascript/frameworks/ShellJS.qll | 23 ++++++++++++++----- .../frameworks/Shelljs/ShellJS.expected | 3 +++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll index 91b18a1779d1..ae0ba17941c2 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll @@ -15,7 +15,7 @@ module ShellJS { .getMember([ "exec", "cd", "cp", "touch", "chmod", "pushd", "find", "ls", "ln", "mkdir", "mv", "rm", "cat", "head", "sort", "tail", "uniq", "grep", "sed", "to", "toEnd", "echo", - "which", + "which", "cmd", "asyncExec" ]) .getReturn() } @@ -154,16 +154,27 @@ module ShellJS { } /** - * A call to `shelljs.exec()` modeled as command execution. + * A call to `shelljs.exec()`, `shelljs.cmd()`, or `async-shelljs.asyncExec()` modeled as command execution. */ private class ShellJSExec extends SystemCommandExecution, ShellJSCall { - ShellJSExec() { name = "exec" } - - override DataFlow::Node getACommandArgument() { result = this.getArgument(0) } + ShellJSExec() { name = ["exec", "cmd", "asyncExec"] } + + override DataFlow::Node getACommandArgument() { + if name = "cmd" + then + result = this.getArgument(_) and + not ( + result = this.getLastArgument() and + exists(this.getOptionsArg()) + ) + else + // For exec/asyncExec: only first argument is command + result = this.getArgument(0) + } override predicate isShellInterpreted(DataFlow::Node arg) { arg = this.getACommandArgument() } - override predicate isSync() { none() } + override predicate isSync() { name = "cmd" } override DataFlow::Node getOptionsArg() { result = this.getLastArgument() and diff --git a/javascript/ql/test/library-tests/frameworks/Shelljs/ShellJS.expected b/javascript/ql/test/library-tests/frameworks/Shelljs/ShellJS.expected index 4ca9f088bf49..5c3c922a84fc 100644 --- a/javascript/ql/test/library-tests/frameworks/Shelljs/ShellJS.expected +++ b/javascript/ql/test/library-tests/frameworks/Shelljs/ShellJS.expected @@ -61,6 +61,9 @@ test_SystemCommandExecution | tst.js:14:1:14:27 | shelljs ... ts, cb) | | tst.js:60:1:60:51 | shelljs ... ec(cmd) | | tst.js:61:1:61:27 | shelljs ... ec(cmd) | +| tst.js:63:1:63:37 | shelljs ... ptions) | +| tst.js:64:1:64:16 | shelljs.cmd(cmd) | +| tst.js:68:1:68:36 | shelljs ... ts, cb) | test_FileNameSource | tst.js:15:1:15:26 | shelljs ... file2) | | tst.js:24:1:24:16 | shelljs.ls(file) | From f584d22b534801e54c6b4137042165bf60ed151c Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Wed, 30 Apr 2025 10:47:11 +0200 Subject: [PATCH 181/336] Rust: Use type inference to insert implicit borrows and derefs --- .../rust/dataflow/internal/DataFlowImpl.qll | 22 ++---------- .../codeql/rust/internal/TypeInference.qll | 26 ++++++++++++-- .../dataflow/local/DataFlowStep.expected | 35 ------------------- .../security/CWE-089/SqlInjection.expected | 12 ------- .../CaptureSummaryModels.expected | 8 ----- 5 files changed, 27 insertions(+), 76 deletions(-) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll index 4376df7caf8d..b29506224406 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll @@ -11,6 +11,7 @@ private import rust private import SsaImpl as SsaImpl private import codeql.rust.controlflow.internal.Scope as Scope private import codeql.rust.internal.PathResolution +private import codeql.rust.internal.TypeInference as TypeInference private import codeql.rust.controlflow.ControlFlowGraph private import codeql.rust.controlflow.CfgNodes private import codeql.rust.dataflow.Ssa @@ -321,23 +322,6 @@ predicate lambdaCallExpr(CallExprCfgNode call, LambdaCallKind kind, ExprCfgNode exists(kind) } -/** Holds if `mc` implicitly borrows its receiver. */ -private predicate implicitBorrow(MethodCallExpr mc) { - // Determining whether an implicit borrow happens depends on the type of the - // receiever as well as the target. As a heuristic we simply check if the - // target takes `self` as a borrow and limit the approximation to cases where - // the receiver is a simple variable. - mc.getReceiver() instanceof VariableAccess and - mc.getStaticTarget().getParamList().getSelfParam().isRef() -} - -/** Holds if `mc` implicitly dereferences its receiver. */ -private predicate implicitDeref(MethodCallExpr mc) { - // Similarly to `implicitBorrow` this is an approximation. - mc.getReceiver() instanceof VariableAccess and - not mc.getStaticTarget().getParamList().getSelfParam().isRef() -} - // Defines a set of aliases needed for the `RustDataFlow` module private module Aliases { class DataFlowCallableAlias = DataFlowCallable; @@ -520,15 +504,15 @@ module RustDataFlow implements InputSig { pragma[nomagic] private predicate implicitDerefToReceiver(Node node1, ReceiverNode node2, ReferenceContent c) { + TypeInference::receiverHasImplicitDeref(node1.asExpr().getExpr()) and node1.asExpr() = node2.getReceiver() and - implicitDeref(node2.getMethodCall().getMethodCallExpr()) and exists(c) } pragma[nomagic] private predicate implicitBorrowToReceiver(Node node1, ReceiverNode node2, ReferenceContent c) { + TypeInference::receiverHasImplicitBorrow(node1.asExpr().getExpr()) and node1.asExpr() = node2.getReceiver() and - implicitBorrow(node2.getMethodCall().getMethodCallExpr()) and exists(c) } diff --git a/rust/ql/lib/codeql/rust/internal/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/TypeInference.qll index 2fae9ef1f5b8..b999b72240bf 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeInference.qll @@ -690,7 +690,7 @@ private Type inferCallExprBaseType(AstNode n, TypePath path) { | if apos.isSelf() then - exists(Type receiverType | receiverType = CallExprBaseMatchingInput::inferReceiverType(n) | + exists(Type receiverType | receiverType = inferType(n) | if receiverType = TRefType() then path = path0 and @@ -840,7 +840,7 @@ private Type inferFieldExprType(AstNode n, TypePath path) { | if apos.isSelf() then - exists(Type receiverType | receiverType = FieldExprMatchingInput::inferReceiverType(n) | + exists(Type receiverType | receiverType = inferType(n) | if receiverType = TRefType() then // adjust for implicit deref @@ -895,6 +895,28 @@ cached private module Cached { private import codeql.rust.internal.CachedStages + /** Holds if `receiver` is the receiver of a method call with an implicit dereference. */ + cached + predicate receiverHasImplicitDeref(AstNode receiver) { + exists(CallExprBaseMatchingInput::Access a, CallExprBaseMatchingInput::AccessPosition apos | + apos.isSelf() and + receiver = a.getNodeAt(apos) and + inferType(receiver) = TRefType() and + CallExprBaseMatching::inferAccessType(a, apos, TypePath::nil()) != TRefType() + ) + } + + /** Holds if `receiver` is the receiver of a method call with an implicit borrow. */ + cached + predicate receiverHasImplicitBorrow(AstNode receiver) { + exists(CallExprBaseMatchingInput::Access a, CallExprBaseMatchingInput::AccessPosition apos | + apos.isSelf() and + receiver = a.getNodeAt(apos) and + CallExprBaseMatching::inferAccessType(a, apos, TypePath::nil()) = TRefType() and + inferType(receiver) != TRefType() + ) + } + pragma[inline] private Type getLookupType(AstNode n) { exists(Type t | diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index d9f17dbf4c4d..6c2a7c2ba85b 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -1931,33 +1931,16 @@ readStep | main.rs:221:9:221:23 | ...::Some(...) | Some | main.rs:221:22:221:22 | n | | main.rs:230:9:230:15 | Some(...) | Some | main.rs:230:14:230:14 | n | | main.rs:234:9:234:15 | Some(...) | Some | main.rs:234:14:234:14 | n | -| main.rs:241:10:241:11 | s1 | &ref | main.rs:241:10:241:11 | receiver for s1 | -| main.rs:246:10:246:11 | s1 | &ref | main.rs:246:10:246:11 | receiver for s1 | -| main.rs:249:10:249:11 | s2 | &ref | main.rs:249:10:249:11 | receiver for s2 | -| main.rs:254:10:254:11 | s1 | &ref | main.rs:254:10:254:11 | receiver for s1 | -| main.rs:257:10:257:11 | s2 | &ref | main.rs:257:10:257:11 | receiver for s2 | | main.rs:263:14:263:15 | s1 | Ok | main.rs:263:14:263:16 | TryExpr | | main.rs:263:14:263:15 | s1 | Some | main.rs:263:14:263:16 | TryExpr | | main.rs:265:10:265:11 | s2 | Ok | main.rs:265:10:265:12 | TryExpr | | main.rs:265:10:265:11 | s2 | Some | main.rs:265:10:265:12 | TryExpr | -| main.rs:271:29:271:30 | r1 | &ref | main.rs:271:29:271:30 | receiver for r1 | -| main.rs:272:29:272:30 | r1 | &ref | main.rs:272:29:272:30 | receiver for r1 | -| main.rs:273:10:273:12 | o1a | &ref | main.rs:273:10:273:12 | receiver for o1a | -| main.rs:274:10:274:12 | o1b | &ref | main.rs:274:10:274:12 | receiver for o1b | -| main.rs:277:29:277:30 | r2 | &ref | main.rs:277:29:277:30 | receiver for r2 | -| main.rs:278:29:278:30 | r2 | &ref | main.rs:278:29:278:30 | receiver for r2 | -| main.rs:279:10:279:12 | o2a | &ref | main.rs:279:10:279:12 | receiver for o2a | -| main.rs:280:10:280:12 | o2b | &ref | main.rs:280:10:280:12 | receiver for o2b | | main.rs:287:14:287:15 | s1 | Ok | main.rs:287:14:287:16 | TryExpr | | main.rs:287:14:287:15 | s1 | Some | main.rs:287:14:287:16 | TryExpr | | main.rs:288:14:288:15 | s2 | Ok | main.rs:288:14:288:16 | TryExpr | | main.rs:288:14:288:15 | s2 | Some | main.rs:288:14:288:16 | TryExpr | | main.rs:291:14:291:15 | s3 | Ok | main.rs:291:14:291:16 | TryExpr | | main.rs:291:14:291:15 | s3 | Some | main.rs:291:14:291:16 | TryExpr | -| main.rs:298:10:298:11 | s1 | &ref | main.rs:298:10:298:11 | receiver for s1 | -| main.rs:299:10:299:11 | s1 | &ref | main.rs:299:10:299:11 | receiver for s1 | -| main.rs:302:10:302:11 | s2 | &ref | main.rs:302:10:302:11 | receiver for s2 | -| main.rs:303:10:303:11 | s2 | &ref | main.rs:303:10:303:11 | receiver for s2 | | main.rs:315:9:315:25 | ...::A(...) | A | main.rs:315:24:315:24 | n | | main.rs:316:9:316:25 | ...::B(...) | B | main.rs:316:24:316:24 | n | | main.rs:319:9:319:25 | ...::A(...) | A | main.rs:319:24:319:24 | n | @@ -1997,40 +1980,22 @@ readStep | main.rs:442:9:442:20 | TuplePat | tuple.0 | main.rs:442:10:442:13 | cond | | main.rs:442:9:442:20 | TuplePat | tuple.1 | main.rs:442:16:442:19 | name | | main.rs:442:25:442:29 | names | element | main.rs:442:9:442:20 | TuplePat | -| main.rs:444:21:444:24 | name | &ref | main.rs:444:21:444:24 | receiver for name | | main.rs:444:41:444:67 | [post] \|...\| ... | captured default_name | main.rs:444:41:444:67 | [post] default_name | -| main.rs:444:44:444:55 | default_name | &ref | main.rs:444:44:444:55 | receiver for default_name | | main.rs:444:44:444:55 | this | captured default_name | main.rs:444:44:444:55 | default_name | -| main.rs:445:18:445:18 | n | &ref | main.rs:445:18:445:18 | receiver for n | -| main.rs:468:13:468:13 | a | &ref | main.rs:468:13:468:13 | receiver for a | -| main.rs:469:13:469:13 | b | &ref | main.rs:469:13:469:13 | receiver for b | -| main.rs:470:19:470:19 | b | &ref | main.rs:470:19:470:19 | receiver for b | | main.rs:481:10:481:11 | vs | element | main.rs:481:10:481:14 | vs[0] | -| main.rs:482:11:482:12 | vs | &ref | main.rs:482:11:482:12 | receiver for vs | | main.rs:482:11:482:35 | ... .unwrap() | &ref | main.rs:482:10:482:35 | * ... | -| main.rs:483:11:483:12 | vs | &ref | main.rs:483:11:483:12 | receiver for vs | | main.rs:483:11:483:35 | ... .unwrap() | &ref | main.rs:483:10:483:35 | * ... | | main.rs:485:14:485:15 | vs | element | main.rs:485:9:485:9 | v | | main.rs:488:9:488:10 | &... | &ref | main.rs:488:10:488:10 | v | -| main.rs:488:15:488:16 | vs | &ref | main.rs:488:15:488:16 | receiver for vs | | main.rs:488:15:488:23 | vs.iter() | element | main.rs:488:9:488:10 | &... | -| main.rs:492:27:492:28 | vs | &ref | main.rs:492:27:492:28 | receiver for vs | | main.rs:493:9:493:10 | &... | &ref | main.rs:493:10:493:10 | v | | main.rs:493:15:493:17 | vs2 | element | main.rs:493:9:493:10 | &... | -| main.rs:497:5:497:6 | vs | &ref | main.rs:497:5:497:6 | receiver for vs | | main.rs:497:29:497:29 | x | &ref | main.rs:497:28:497:29 | * ... | -| main.rs:498:5:498:6 | vs | &ref | main.rs:498:5:498:6 | receiver for vs | | main.rs:498:34:498:34 | x | &ref | main.rs:498:33:498:34 | * ... | -| main.rs:500:14:500:15 | vs | &ref | main.rs:500:14:500:15 | receiver for vs | | main.rs:500:14:500:27 | vs.into_iter() | element | main.rs:500:9:500:9 | v | | main.rs:506:10:506:15 | vs_mut | element | main.rs:506:10:506:18 | vs_mut[0] | -| main.rs:507:11:507:16 | vs_mut | &ref | main.rs:507:11:507:16 | receiver for vs_mut | | main.rs:507:11:507:39 | ... .unwrap() | &ref | main.rs:507:10:507:39 | * ... | -| main.rs:508:11:508:16 | vs_mut | &ref | main.rs:508:11:508:16 | receiver for vs_mut | | main.rs:508:11:508:39 | ... .unwrap() | &ref | main.rs:508:10:508:39 | * ... | | main.rs:510:9:510:14 | &mut ... | &ref | main.rs:510:14:510:14 | v | -| main.rs:510:19:510:24 | vs_mut | &ref | main.rs:510:19:510:24 | receiver for vs_mut | | main.rs:510:19:510:35 | vs_mut.iter_mut() | element | main.rs:510:9:510:14 | &mut ... | | main.rs:524:11:524:15 | c_ref | &ref | main.rs:524:10:524:15 | * ... | -| main.rs:531:10:531:10 | a | &ref | main.rs:531:10:531:10 | receiver for a | -| main.rs:537:10:537:10 | b | &ref | main.rs:537:10:537:10 | receiver for b | diff --git a/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected b/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected index b5aa4a386f29..7c3c14194747 100644 --- a/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected +++ b/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected @@ -31,15 +31,11 @@ edges | sqlx.rs:52:32:52:87 | ...::must_use(...) | sqlx.rs:52:9:52:20 | safe_query_3 | provenance | | | sqlx.rs:52:32:52:87 | MacroExpr | sqlx.rs:52:32:52:87 | ...::format(...) | provenance | MaD:4 | | sqlx.rs:52:32:52:87 | { ... } | sqlx.rs:52:32:52:87 | ...::must_use(...) | provenance | MaD:9 | -| sqlx.rs:53:9:53:22 | unsafe_query_1 [&ref] | sqlx.rs:63:26:63:39 | unsafe_query_1 [&ref] | provenance | | | sqlx.rs:53:9:53:22 | unsafe_query_1 [&ref] | sqlx.rs:63:26:63:48 | unsafe_query_1.as_str() | provenance | MaD:3 | -| sqlx.rs:53:9:53:22 | unsafe_query_1 [&ref] | sqlx.rs:74:25:74:38 | unsafe_query_1 [&ref] | provenance | | | sqlx.rs:53:9:53:22 | unsafe_query_1 [&ref] | sqlx.rs:74:25:74:47 | unsafe_query_1.as_str() | provenance | MaD:3 | | sqlx.rs:53:26:53:36 | &arg_string [&ref] | sqlx.rs:53:9:53:22 | unsafe_query_1 [&ref] | provenance | | | sqlx.rs:53:27:53:36 | arg_string | sqlx.rs:53:26:53:36 | &arg_string [&ref] | provenance | | -| sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | sqlx.rs:65:30:65:43 | unsafe_query_2 [&ref] | provenance | | | sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | provenance | MaD:3 | -| sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | sqlx.rs:76:29:76:42 | unsafe_query_2 [&ref] | provenance | | | sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | provenance | MaD:3 | | sqlx.rs:54:26:54:39 | &remote_string [&ref] | sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | provenance | | | sqlx.rs:54:27:54:39 | remote_string | sqlx.rs:54:26:54:39 | &remote_string [&ref] | provenance | | @@ -50,10 +46,6 @@ edges | sqlx.rs:56:34:56:89 | ...::must_use(...) | sqlx.rs:56:9:56:22 | unsafe_query_4 | provenance | | | sqlx.rs:56:34:56:89 | MacroExpr | sqlx.rs:56:34:56:89 | ...::format(...) | provenance | MaD:4 | | sqlx.rs:56:34:56:89 | { ... } | sqlx.rs:56:34:56:89 | ...::must_use(...) | provenance | MaD:9 | -| sqlx.rs:63:26:63:39 | unsafe_query_1 [&ref] | sqlx.rs:63:26:63:48 | unsafe_query_1.as_str() | provenance | MaD:3 | -| sqlx.rs:65:30:65:43 | unsafe_query_2 [&ref] | sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | provenance | MaD:3 | -| sqlx.rs:74:25:74:38 | unsafe_query_1 [&ref] | sqlx.rs:74:25:74:47 | unsafe_query_1.as_str() | provenance | MaD:3 | -| sqlx.rs:76:29:76:42 | unsafe_query_2 [&ref] | sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | provenance | MaD:3 | models | 1 | Source: lang:std; crate::env::args; commandargs; ReturnValue.Element | | 2 | Source: repo:https://github.com/seanmonstar/reqwest:reqwest; crate::blocking::get; remote; ReturnValue.Field[crate::result::Result::Ok(0)] | @@ -100,15 +92,11 @@ nodes | sqlx.rs:56:34:56:89 | MacroExpr | semmle.label | MacroExpr | | sqlx.rs:56:34:56:89 | { ... } | semmle.label | { ... } | | sqlx.rs:62:26:62:46 | safe_query_3.as_str() | semmle.label | safe_query_3.as_str() | -| sqlx.rs:63:26:63:39 | unsafe_query_1 [&ref] | semmle.label | unsafe_query_1 [&ref] | | sqlx.rs:63:26:63:48 | unsafe_query_1.as_str() | semmle.label | unsafe_query_1.as_str() | -| sqlx.rs:65:30:65:43 | unsafe_query_2 [&ref] | semmle.label | unsafe_query_2 [&ref] | | sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | semmle.label | unsafe_query_2.as_str() | | sqlx.rs:67:30:67:52 | unsafe_query_4.as_str() | semmle.label | unsafe_query_4.as_str() | | sqlx.rs:73:25:73:45 | safe_query_3.as_str() | semmle.label | safe_query_3.as_str() | -| sqlx.rs:74:25:74:38 | unsafe_query_1 [&ref] | semmle.label | unsafe_query_1 [&ref] | | sqlx.rs:74:25:74:47 | unsafe_query_1.as_str() | semmle.label | unsafe_query_1.as_str() | -| sqlx.rs:76:29:76:42 | unsafe_query_2 [&ref] | semmle.label | unsafe_query_2 [&ref] | | sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | semmle.label | unsafe_query_2.as_str() | | sqlx.rs:78:29:78:51 | unsafe_query_4.as_str() | semmle.label | unsafe_query_4.as_str() | subpaths diff --git a/rust/ql/test/utils-tests/modelgenerator/CaptureSummaryModels.expected b/rust/ql/test/utils-tests/modelgenerator/CaptureSummaryModels.expected index b05e99f352b0..e827c7320cc7 100644 --- a/rust/ql/test/utils-tests/modelgenerator/CaptureSummaryModels.expected +++ b/rust/ql/test/utils-tests/modelgenerator/CaptureSummaryModels.expected @@ -1,12 +1,4 @@ unexpectedModel | Unexpected summary found: repo::test;::clone;Argument[self].Field[crate::option::MyOption::MySome(0)].Reference;ReturnValue.Field[crate::option::MyOption::MySome(0)];value;dfc-generated | -| Unexpected summary found: repo::test;::from;Argument[0].Field[crate::option::MyOption::MySome(0)];ReturnValue.Field[crate::option::MyOption::MySome(0)].Reference;value;dfc-generated | | Unexpected summary found: repo::test;::cloned;Argument[self].Field[crate::option::MyOption::MySome(0)].Reference;ReturnValue.Field[crate::option::MyOption::MySome(0)];value;dfc-generated | -| Unexpected summary found: repo::test;::get_or_insert;Argument[0];Argument[self].Field[crate::option::MyOption::MySome(0)];value;dfc-generated | -| Unexpected summary found: repo::test;::get_or_insert;Argument[self].Field[crate::option::MyOption::MySome(0)];ReturnValue.Reference;value;dfc-generated | -| Unexpected summary found: repo::test;::get_or_insert_default;Argument[self].Field[crate::option::MyOption::MySome(0)];ReturnValue.Reference;value;dfc-generated | -| Unexpected summary found: repo::test;::get_or_insert_with;Argument[self].Field[crate::option::MyOption::MySome(0)];ReturnValue.Reference;value;dfc-generated | -| Unexpected summary found: repo::test;::insert;Argument[self].Field[crate::option::MyOption::MySome(0)];ReturnValue.Reference;value;dfc-generated | expectedModel -| Expected summary missing: repo::test;::take_if;Argument[self].Reference.Field[crate::option::MyOption::MySome(0)];Argument[0].Parameter[0].Reference;value;dfc-generated | -| Expected summary missing: repo::test;::take_if;Argument[self].Reference;ReturnValue;value;dfc-generated | From 6d617663662a2dd4a152dff9c2357865508b0248 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Wed, 30 Apr 2025 14:50:35 +0200 Subject: [PATCH 182/336] Added test case for `fastify.all` --- .../query-tests/Security/CWE-094/CodeInjection/fastify.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js index e1cba0d277ca..d538898f947a 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js @@ -101,3 +101,10 @@ fastify.get('/flow-through-reply', async (request, reply) => { } return { result: null }; }); + +fastify.all('/eval', async (request, reply) => { + const userInput = request.query.code; // $ MISSING: Source[js/code-injection] + const result = eval(userInput); // $ MISSING: Alert[js/code-injection] + const replyResult = eval(reply.locals.nestedCode); // $ MISSING: Alert[js/code-injection] + return { method: request.method, result }; +}); From 71f1b82a56245c63d447f5fc704add27ee02996f Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Wed, 30 Apr 2025 14:54:09 +0200 Subject: [PATCH 183/336] Added support for `fastify.all` --- .../ql/lib/semmle/javascript/frameworks/Fastify.qll | 7 +++++-- .../CWE-094/CodeInjection/CodeInjection.expected | 13 +++++++++++++ .../HeuristicSourceCodeInjection.expected | 9 +++++++++ .../Security/CWE-094/CodeInjection/fastify.js | 6 +++--- 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll index cf8dd76b75e3..4b53292e1482 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll @@ -138,7 +138,8 @@ module Fastify { RouteSetup() { this = server(server).getAMethodCall(methodName) and - methodName = ["route", "get", "head", "post", "put", "delete", "options", "patch", "addHook"] + methodName = + ["route", "get", "head", "post", "put", "delete", "options", "patch", "addHook", "all"] } override DataFlow::SourceNode getARouteHandler() { @@ -168,7 +169,9 @@ module Fastify { override string getRelativePath() { result = this.getArgument(0).getStringValue() } - override Http::RequestMethodName getHttpMethod() { result = this.getMethodName().toUpperCase() } + override Http::RequestMethodName getHttpMethod() { + if this.getMethodName() = "all" then any() else result = this.getMethodName().toUpperCase() + } } private class AddHookRouteSetup extends Routing::RouteSetup::MethodCall instanceof RouteSetup { diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected index 9ad04af3a2c5..4d54adb27249 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected @@ -57,6 +57,10 @@ | fastify.js:84:30:84:43 | reply.userCode | fastify.js:79:20:79:42 | request ... plyCode | fastify.js:84:30:84:43 | reply.userCode | This code execution depends on a $@. | fastify.js:79:20:79:42 | request ... plyCode | user-provided value | | fastify.js:99:30:99:52 | reply.l ... tedCode | fastify.js:94:29:94:41 | request.query | fastify.js:99:30:99:52 | reply.l ... tedCode | This code execution depends on a $@. | fastify.js:94:29:94:41 | request.query | user-provided value | | fastify.js:99:30:99:52 | reply.l ... tedCode | fastify.js:94:29:94:51 | request ... plyCode | fastify.js:99:30:99:52 | reply.l ... tedCode | This code execution depends on a $@. | fastify.js:94:29:94:51 | request ... plyCode | user-provided value | +| fastify.js:107:23:107:31 | userInput | fastify.js:106:21:106:33 | request.query | fastify.js:107:23:107:31 | userInput | This code execution depends on a $@. | fastify.js:106:21:106:33 | request.query | user-provided value | +| fastify.js:107:23:107:31 | userInput | fastify.js:106:21:106:38 | request.query.code | fastify.js:107:23:107:31 | userInput | This code execution depends on a $@. | fastify.js:106:21:106:38 | request.query.code | user-provided value | +| fastify.js:108:28:108:50 | reply.l ... tedCode | fastify.js:94:29:94:41 | request.query | fastify.js:108:28:108:50 | reply.l ... tedCode | This code execution depends on a $@. | fastify.js:94:29:94:41 | request.query | user-provided value | +| fastify.js:108:28:108:50 | reply.l ... tedCode | fastify.js:94:29:94:51 | request ... plyCode | fastify.js:108:28:108:50 | reply.l ... tedCode | This code execution depends on a $@. | fastify.js:94:29:94:51 | request ... plyCode | user-provided value | | module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code | This code execution depends on a $@. | module.js:9:16:9:29 | req.query.code | user-provided value | | module.js:11:17:11:30 | req.query.code | module.js:11:17:11:30 | req.query.code | module.js:11:17:11:30 | req.query.code | This code execution depends on a $@. | module.js:11:17:11:30 | req.query.code | user-provided value | | react-native.js:8:32:8:38 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:8:32:8:38 | tainted | This code execution depends on a $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value | @@ -145,6 +149,10 @@ edges | fastify.js:79:20:79:42 | request ... plyCode | fastify.js:84:30:84:43 | reply.userCode | provenance | | | fastify.js:94:29:94:41 | request.query | fastify.js:94:29:94:51 | request ... plyCode | provenance | | | fastify.js:94:29:94:51 | request ... plyCode | fastify.js:99:30:99:52 | reply.l ... tedCode | provenance | | +| fastify.js:94:29:94:51 | request ... plyCode | fastify.js:108:28:108:50 | reply.l ... tedCode | provenance | | +| fastify.js:106:9:106:38 | userInput | fastify.js:107:23:107:31 | userInput | provenance | | +| fastify.js:106:21:106:33 | request.query | fastify.js:106:9:106:38 | userInput | provenance | | +| fastify.js:106:21:106:38 | request.query.code | fastify.js:106:9:106:38 | userInput | provenance | | | react-native.js:7:7:7:33 | tainted | react-native.js:8:32:8:38 | tainted | provenance | | | react-native.js:7:7:7:33 | tainted | react-native.js:10:23:10:29 | tainted | provenance | | | react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted | provenance | | @@ -268,6 +276,11 @@ nodes | fastify.js:94:29:94:41 | request.query | semmle.label | request.query | | fastify.js:94:29:94:51 | request ... plyCode | semmle.label | request ... plyCode | | fastify.js:99:30:99:52 | reply.l ... tedCode | semmle.label | reply.l ... tedCode | +| fastify.js:106:9:106:38 | userInput | semmle.label | userInput | +| fastify.js:106:21:106:33 | request.query | semmle.label | request.query | +| fastify.js:106:21:106:38 | request.query.code | semmle.label | request.query.code | +| fastify.js:107:23:107:31 | userInput | semmle.label | userInput | +| fastify.js:108:28:108:50 | reply.l ... tedCode | semmle.label | reply.l ... tedCode | | module.js:9:16:9:29 | req.query.code | semmle.label | req.query.code | | module.js:11:17:11:30 | req.query.code | semmle.label | req.query.code | | react-native.js:7:7:7:33 | tainted | semmle.label | tainted | diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected index aa23d7a6d5a1..a1c8354ecf71 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected @@ -51,6 +51,10 @@ edges | fastify.js:79:20:79:42 | request ... plyCode | fastify.js:84:30:84:43 | reply.userCode | provenance | | | fastify.js:94:29:94:41 | request.query | fastify.js:94:29:94:51 | request ... plyCode | provenance | | | fastify.js:94:29:94:51 | request ... plyCode | fastify.js:99:30:99:52 | reply.l ... tedCode | provenance | | +| fastify.js:94:29:94:51 | request ... plyCode | fastify.js:108:28:108:50 | reply.l ... tedCode | provenance | | +| fastify.js:106:9:106:38 | userInput | fastify.js:107:23:107:31 | userInput | provenance | | +| fastify.js:106:21:106:33 | request.query | fastify.js:106:9:106:38 | userInput | provenance | | +| fastify.js:106:21:106:38 | request.query.code | fastify.js:106:9:106:38 | userInput | provenance | | | react-native.js:7:7:7:33 | tainted | react-native.js:8:32:8:38 | tainted | provenance | | | react-native.js:7:7:7:33 | tainted | react-native.js:10:23:10:29 | tainted | provenance | | | react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted | provenance | | @@ -176,6 +180,11 @@ nodes | fastify.js:94:29:94:41 | request.query | semmle.label | request.query | | fastify.js:94:29:94:51 | request ... plyCode | semmle.label | request ... plyCode | | fastify.js:99:30:99:52 | reply.l ... tedCode | semmle.label | reply.l ... tedCode | +| fastify.js:106:9:106:38 | userInput | semmle.label | userInput | +| fastify.js:106:21:106:33 | request.query | semmle.label | request.query | +| fastify.js:106:21:106:38 | request.query.code | semmle.label | request.query.code | +| fastify.js:107:23:107:31 | userInput | semmle.label | userInput | +| fastify.js:108:28:108:50 | reply.l ... tedCode | semmle.label | reply.l ... tedCode | | module.js:9:16:9:29 | req.query.code | semmle.label | req.query.code | | module.js:11:17:11:30 | req.query.code | semmle.label | req.query.code | | react-native.js:7:7:7:33 | tainted | semmle.label | tainted | diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js index d538898f947a..05dd3f6eb463 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/fastify.js @@ -103,8 +103,8 @@ fastify.get('/flow-through-reply', async (request, reply) => { }); fastify.all('/eval', async (request, reply) => { - const userInput = request.query.code; // $ MISSING: Source[js/code-injection] - const result = eval(userInput); // $ MISSING: Alert[js/code-injection] - const replyResult = eval(reply.locals.nestedCode); // $ MISSING: Alert[js/code-injection] + const userInput = request.query.code; // $ Source[js/code-injection] + const result = eval(userInput); // $ Alert[js/code-injection] + const replyResult = eval(reply.locals.nestedCode); // $ Alert[js/code-injection] return { method: request.method, result }; }); From 9624a413e4b3a464ec68a9073516572819fc535f Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Wed, 30 Apr 2025 14:57:00 +0200 Subject: [PATCH 184/336] Added change note --- javascript/ql/lib/change-notes/2025-04-30-fastify-all.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 javascript/ql/lib/change-notes/2025-04-30-fastify-all.md diff --git a/javascript/ql/lib/change-notes/2025-04-30-fastify-all.md b/javascript/ql/lib/change-notes/2025-04-30-fastify-all.md new file mode 100644 index 000000000000..a49092f6ba41 --- /dev/null +++ b/javascript/ql/lib/change-notes/2025-04-30-fastify-all.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Enhanced modeling of the [fastify](https://www.npmjs.com/package/fastify) framework to support the `all` route handler method. From 4f5b340278bf39aba61673cac360785068338a4a Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 30 Apr 2025 15:12:58 +0200 Subject: [PATCH 185/336] Rust: Add type inference debug predicates --- .../codeql/rust/internal/TypeInference.qll | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/rust/ql/lib/codeql/rust/internal/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/TypeInference.qll index 2fae9ef1f5b8..0f0c92306d12 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeInference.qll @@ -1017,3 +1017,24 @@ import Cached * Gets a type that `n` infers to, if any. */ Type inferType(AstNode n) { result = inferType(n, TypePath::nil()) } + +/** Provides predicates for debugging the type inference implementation. */ +private module Debug { + private Locatable getRelevantLocatable() { + exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | + result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and + filepath.matches("%/tauri/src/app/plugin.rs") and + startline = 54 + ) + } + + Type debugInferType(AstNode n, TypePath path) { + n = getRelevantLocatable() and + result = inferType(n, path) + } + + Function debugResolveMethodCallExpr(MethodCallExpr mce) { + mce = getRelevantLocatable() and + result = resolveMethodCallExpr(mce) + } +} From edd18dc0521aa972fcee2a66b1aebf7fc44348a7 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Wed, 30 Apr 2025 16:23:06 +0200 Subject: [PATCH 186/336] C++: Address review comment --- .../header-variant-tests/clang-pch/test.py | 19 ++++++++++--------- .../microsoft-pch/test.py | 7 ++++--- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/cpp/ql/integration-tests/header-variant-tests/clang-pch/test.py b/cpp/ql/integration-tests/header-variant-tests/clang-pch/test.py index 3cf2d42f7643..d7bc5fe6352f 100644 --- a/cpp/ql/integration-tests/header-variant-tests/clang-pch/test.py +++ b/cpp/ql/integration-tests/header-variant-tests/clang-pch/test.py @@ -3,14 +3,15 @@ def test(codeql, cpp): os.mkdir("pch") + extractor = f"{cpp.get_tool("extractor")}" codeql.database.create(command=[ - f'"{cpp.get_tool("extractor")}" --mimic-clang -emit-pch -o pch/a.pch a.c', - f'"{cpp.get_tool("extractor")}" --mimic-clang -include-pch pch/a.pch -Iextra_dummy_path b.c', - f'"{cpp.get_tool("extractor")}" --mimic-clang -include pch/a -Iextra_dummy_path c.c', - f'"{cpp.get_tool("extractor")}" --mimic-clang -emit-pch -o pch/d.pch d.c', - f'"{cpp.get_tool("extractor")}" --mimic-clang -include-pch pch/d.pch e.c', - f'"{cpp.get_tool("extractor")}" --mimic-clang -emit-pch -o pch/f.pch f.c', - f'"{cpp.get_tool("extractor")}" --mimic-clang -include-pch pch/f.pch g.c', - f'"{cpp.get_tool("extractor")}" --mimic-clang -emit-pch -o pch/h.pch h.c', - f'"{cpp.get_tool("extractor")}" --mimic-clang -include-pch pch/h.pch i.c', + f'"{extractor}" --mimic-clang -emit-pch -o pch/a.pch a.c', + f'"{extractor}" --mimic-clang -include-pch pch/a.pch -Iextra_dummy_path b.c', + f'"{extractor}" --mimic-clang -include pch/a -Iextra_dummy_path c.c', + f'"{extractor}" --mimic-clang -emit-pch -o pch/d.pch d.c', + f'"{extractor}" --mimic-clang -include-pch pch/d.pch e.c', + f'"{extractor}" --mimic-clang -emit-pch -o pch/f.pch f.c', + f'"{extractor}" --mimic-clang -include-pch pch/f.pch g.c', + f'"{extractor}" --mimic-clang -emit-pch -o pch/h.pch h.c', + f'"{extractor}" --mimic-clang -include-pch pch/h.pch i.c', ]) diff --git a/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/test.py b/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/test.py index eaa0fdb8786c..d734f0335f17 100644 --- a/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/test.py +++ b/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/test.py @@ -3,8 +3,9 @@ def test(codeql, cpp): os.mkdir("pch") + extractor = f"{cpp.get_tool("extractor")}" codeql.database.create(command=[ - f'"{cpp.get_tool("extractor")}" --mimic-cl /Yca.h /Fppch/a.pch a.c', - f'"{cpp.get_tool("extractor")}" --mimic-cl /Yub.h /Fppch/a.pch b.c', - f'"{cpp.get_tool("extractor")}" --mimic-cl /Yuc.h /Fppch/a.pch c.c', + f'"{extractor}" --mimic-cl /Yca.h /Fppch/a.pch a.c', + f'"{extractor}" --mimic-cl /Yub.h /Fppch/a.pch b.c', + f'"{extractor}" --mimic-cl /Yuc.h /Fppch/a.pch c.c', ]) From 7f24a2557dab63a2e1a241ef83c5e11a0622a28b Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Wed, 30 Apr 2025 16:28:31 +0200 Subject: [PATCH 187/336] Add modelling for JCA key gen cipher algorithm --- java/ql/lib/experimental/Quantum/JCA.qll | 83 +++++++---- java/ql/lib/experimental/Quantum/Language.qll | 35 +++-- .../Quantum/InsecureNonceSource.ql | 20 +++ .../experimental/Quantum/TestAESGCMNonce.ql | 16 +++ .../ql/src/experimental/Quantum/TestCipher.ql | 2 +- java/ql/src/experimental/Quantum/TestHash.ql | 4 +- misc/scripts/cryptography/generate_cbom.py | 10 +- .../codeql/cryptography/Model.qll | 135 ++++++++++++++---- 8 files changed, 234 insertions(+), 71 deletions(-) create mode 100644 java/ql/src/experimental/Quantum/InsecureNonceSource.ql create mode 100644 java/ql/src/experimental/Quantum/TestAESGCMNonce.ql diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 7507c9edbd50..6589cbbc9d5d 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -2,7 +2,6 @@ import java import semmle.code.java.dataflow.DataFlow import semmle.code.java.dataflow.TaintTracking import semmle.code.java.controlflow.Dominance -import codeql.util.Option module JCAModel { import Language @@ -354,9 +353,11 @@ module JCAModel { else result instanceof KeyOpAlg::TUnknownKeyOperationAlgorithmType } - override string getKeySize() { + override string getKeySizeFixed() { none() // TODO: implement to handle variants such as AES-128 } + + override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { none() } } bindingset[input] @@ -394,8 +395,6 @@ module JCAModel { override Crypto::HashAlgorithmInstance getOAEPEncodingHashAlgorithm() { result = this } override Crypto::HashAlgorithmInstance getMGF1HashAlgorithm() { none() } // TODO - - override string getKeySize() { none() } } /** @@ -446,8 +445,6 @@ module JCAModel { predicate isIntermediate(); } - module MethodCallOption = Option; - /** * An generic analysis module for analyzing the `getInstance` to `initialize` to `doOperation` pattern in the JCA. * @@ -568,6 +565,14 @@ module JCAModel { GetInstanceToInitToUseFlow::flowPath(src, sink) } + GetInstance getInstantiationFromInit( + Init init, GetInstanceToInitToUseFlow::PathNode src, GetInstanceToInitToUseFlow::PathNode sink + ) { + src.getNode().asExpr() = result and + sink.getNode().asExpr() = init.(MethodCall).getQualifier() and + GetInstanceToInitToUseFlow::flowPath(src, sink) + } + Init getInitFromUse( Use use, GetInstanceToInitToUseFlow::PathNode src, GetInstanceToInitToUseFlow::PathNode sink ) { @@ -829,6 +834,9 @@ module JCAModel { } } + module MessageDigestFlowAnalysisImpl = + GetInstanceInitUseFlowAnalysis; + class MessageDigestGetInstanceAlgorithmValueConsumer extends HashAlgorithmValueConsumer { MessageDigestGetInstanceCall call; @@ -849,17 +857,18 @@ module JCAModel { } Expr getAlgorithmArg() { result = this.getArgument(0) } - - DigestHashOperation getDigestCall() { - DigestGetInstanceToDigestFlow::flow(DataFlow::exprNode(this), - DataFlow::exprNode(result.(DigestCall).getQualifier())) - } } class DigestCall extends MethodCall { - DigestCall() { this.getCallee().hasQualifiedName("java.security", "MessageDigest", "digest") } + DigestCall() { + this.getCallee().hasQualifiedName("java.security", "MessageDigest", ["update", "digest"]) + } Expr getDigestArtifactOutput() { result = this } + + Expr getInputArg() { result = this.getArgument(0) } + + predicate isIntermediate() { this.getMethod().getName() = "update" } } // flow config from MessageDigest.getInstance to MessageDigest.digest @@ -873,23 +882,22 @@ module JCAModel { module DigestGetInstanceToDigestFlow = DataFlow::Global; - class DigestArtifact extends Crypto::DigestArtifactInstance { - DigestArtifact() { this = any(DigestCall call).getDigestArtifactOutput() } - - override DataFlow::Node getOutputNode() { result.asExpr() = this } - } - class DigestHashOperation extends Crypto::HashOperationInstance instanceof DigestCall { - override Crypto::DigestArtifactInstance getDigestArtifact() { - result = this.(DigestCall).getDigestArtifactOutput() + DigestHashOperation() { not super.isIntermediate() } + + override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { + result.asExpr() = super.getDigestArtifactOutput() } override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { - exists(MessageDigestGetInstanceCall getInstanceCall | - getInstanceCall.getDigestCall() = this and - getInstanceCall = - result.(MessageDigestGetInstanceAlgorithmValueConsumer).getInstantiationCall() - ) + MessageDigestFlowAnalysisImpl::getInstantiationFromUse(this, _, _) = + result.(MessageDigestGetInstanceAlgorithmValueConsumer).getInstantiationCall() + } + + override Crypto::ConsumerInputDataFlowNode getInputConsumer() { + result.asExpr() = super.getInputArg() or + result.asExpr() = + MessageDigestFlowAnalysisImpl::getAnIntermediateUseFromFinalUse(this, _, _).getInputArg() } } @@ -997,6 +1005,7 @@ module JCAModel { or // However, for general elliptic curves, getInstance("EC") is used // and java.security.spec.ECGenParameterSpec("") is what sets the specific curve. + // If init is not specified, the default (P-) // The result of ECGenParameterSpec is passed to KeyPairGenerator.initialize // If the curve is not specified, the default is used. // We would trace the use of this inside a KeyPairGenerator.initialize @@ -1096,6 +1105,30 @@ module JCAModel { override string getKeySizeFixed() { none() } } + class KeyGeneratorCipherAlgorithm extends CipherStringLiteralAlgorithmInstance { + KeyGeneratorCipherAlgorithm() { consumer instanceof KeyGenerationAlgorithmValueConsumer } + + override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { + exists(KeyGeneratorGetInstanceCall getInstance, KeyGeneratorInitCall init | + getInstance = + this.getConsumer().(KeyGenerationAlgorithmValueConsumer).getInstantiationCall() and + getInstance = KeyGeneratorFlowAnalysisImpl::getInstantiationFromInit(init, _, _) and + init.getKeySizeArg() = result.asExpr() + ) + } + + predicate isOnlyConsumedByKeyGen() { + forall(Crypto::AlgorithmValueConsumer c | + c = this.getConsumer() and + c instanceof KeyGenerationAlgorithmValueConsumer + ) + } + + override predicate shouldHaveModeOfOperation() { this.isOnlyConsumedByKeyGen() } + + override predicate shouldHavePaddingScheme() { this.isOnlyConsumedByKeyGen() } + } + /* * Key Derivation Functions (KDFs) */ diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 1e12f6f1ac8e..6f7dc88157b2 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -38,7 +38,7 @@ module CryptoInput implements InputSig { predicate artifactOutputFlowsToGenericInput( DataFlow::Node artifactOutput, DataFlow::Node otherInput ) { - ArtifactUniversalFlow::flow(artifactOutput, otherInput) + ArtifactFlow::flow(artifactOutput, otherInput) } } @@ -60,7 +60,7 @@ class GenericUnreferencedParameterSource extends Crypto::GenericUnreferencedPara } override predicate flowsTo(Crypto::FlowAwareElement other) { - GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) + GenericDataSourceFlow::flow(this.getOutputNode(), other.getInputNode()) } override DataFlow::Node getOutputNode() { result.asParameter() = this } @@ -76,7 +76,7 @@ class GenericLocalDataSource extends Crypto::GenericLocalDataSource { override DataFlow::Node getOutputNode() { result.asExpr() = this } override predicate flowsTo(Crypto::FlowAwareElement other) { - GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) + GenericDataSourceFlow::flow(this.getOutputNode(), other.getInputNode()) } override string getAdditionalDescription() { result = this.toString() } @@ -88,7 +88,7 @@ class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { override DataFlow::Node getOutputNode() { result.asExpr() = this } override predicate flowsTo(Crypto::FlowAwareElement other) { - GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) + GenericDataSourceFlow::flow(this.getOutputNode(), other.getInputNode()) } override string getAdditionalDescription() { result = this.toString() } @@ -107,7 +107,7 @@ class ConstantDataSource extends Crypto::GenericConstantSourceInstance instanceo override predicate flowsTo(Crypto::FlowAwareElement other) { // TODO: separate config to avoid blowing up data-flow analysis - GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) + GenericDataSourceFlow::flow(this.getOutputNode(), other.getInputNode()) } override string getAdditionalDescription() { result = this.toString() } @@ -122,15 +122,24 @@ abstract class RandomnessInstance extends Crypto::RandomNumberGenerationInstance } class SecureRandomnessInstance extends RandomnessInstance { + RandomDataSource source; + SecureRandomnessInstance() { - exists(RandomDataSource s | this = s.getOutput() | - s.getSourceOfRandomness() instanceof SecureRandomNumberGenerator - ) + this = source.getOutput() and + source.getSourceOfRandomness() instanceof SecureRandomNumberGenerator } + + override string getGeneratorName() { result = source.getSourceOfRandomness().getQualifiedName() } } class InsecureRandomnessInstance extends RandomnessInstance { - InsecureRandomnessInstance() { exists(InsecureRandomnessSource node | this = node.asExpr()) } + RandomDataSource source; + + InsecureRandomnessInstance() { + any(InsecureRandomnessSource src).asExpr() = this and source.getOutput() = this + } + + override string getGeneratorName() { result = source.getSourceOfRandomness().getQualifiedName() } } /** @@ -142,12 +151,12 @@ abstract class AdditionalFlowInputStep extends DataFlow::Node { final DataFlow::Node getInput() { result = this } } -module ArtifactUniversalFlow = DataFlow::Global; +module ArtifactFlow = DataFlow::Global; /** * Generic data source to node input configuration */ -module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { +module GenericDataSourceFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source = any(Crypto::GenericSourceInstance i).getOutputNode() } @@ -175,7 +184,7 @@ module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { } } -module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { +module ArtifactFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source = any(Crypto::ArtifactInstance artifact).getOutputNode() } @@ -203,7 +212,7 @@ module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { } } -module GenericDataSourceUniversalFlow = TaintTracking::Global; +module GenericDataSourceFlow = TaintTracking::Global; // Import library-specific modeling import JCA diff --git a/java/ql/src/experimental/Quantum/InsecureNonceSource.ql b/java/ql/src/experimental/Quantum/InsecureNonceSource.ql new file mode 100644 index 000000000000..9c06884328bb --- /dev/null +++ b/java/ql/src/experimental/Quantum/InsecureNonceSource.ql @@ -0,0 +1,20 @@ +/** + * @name Insecure nonce at a cipher operation + * @id java/insecure-nonce + * @kind problem + * @problem.severity error + * @precision high + * @description A nonce is generated from a source that is not secure. This can lead to + * vulnerabilities such as replay attacks or key recovery. + */ + +import experimental.Quantum.Language + +predicate isInsecureNonceSource(Crypto::NonceArtifactNode n, Crypto::NodeBase src) { + src = n.getSourceNode() and + not src.asElement() instanceof SecureRandomnessInstance +} + +from Crypto::KeyOperationNode op, Crypto::NodeBase src +where isInsecureNonceSource(op.getANonce(), src) +select op, "Operation uses insecure nonce source $@", src, src.toString() diff --git a/java/ql/src/experimental/Quantum/TestAESGCMNonce.ql b/java/ql/src/experimental/Quantum/TestAESGCMNonce.ql new file mode 100644 index 000000000000..985527318ffa --- /dev/null +++ b/java/ql/src/experimental/Quantum/TestAESGCMNonce.ql @@ -0,0 +1,16 @@ +/** + * @name "PQC Test" + */ + +import experimental.Quantum.Language + +class AESGCMAlgorithmNode extends Crypto::KeyOperationAlgorithmNode { + AESGCMAlgorithmNode() { + this.getAlgorithmType() = Crypto::KeyOpAlg::TSymmetricCipher(Crypto::KeyOpAlg::AES()) and + this.getModeOfOperation().getModeType() = Crypto::GCM() + } +} + +from Crypto::KeyOperationNode op, Crypto::NonceArtifactNode nonce +where op.getAKnownAlgorithm() instanceof AESGCMAlgorithmNode and nonce = op.getANonce() +select op, nonce.getSourceNode() diff --git a/java/ql/src/experimental/Quantum/TestCipher.ql b/java/ql/src/experimental/Quantum/TestCipher.ql index 6779a64f608e..503d60039229 100644 --- a/java/ql/src/experimental/Quantum/TestCipher.ql +++ b/java/ql/src/experimental/Quantum/TestCipher.ql @@ -1,5 +1,5 @@ /** - * @name "PQC Test" + * @name "Key operation slice table demo query" */ import experimental.Quantum.Language diff --git a/java/ql/src/experimental/Quantum/TestHash.ql b/java/ql/src/experimental/Quantum/TestHash.ql index 96f99193cba4..76ef6951a7e8 100644 --- a/java/ql/src/experimental/Quantum/TestHash.ql +++ b/java/ql/src/experimental/Quantum/TestHash.ql @@ -1,9 +1,9 @@ /** - * @name TestHashOperations + * @name "Hash operation slice table demo query" */ import experimental.Quantum.Language from Crypto::HashOperationNode op, Crypto::HashAlgorithmNode alg -where alg = op.getAKnownHashAlgorithm() +where alg = op.getAKnownAlgorithm() select op, op.getDigest(), alg, alg.getRawAlgorithmName() diff --git a/misc/scripts/cryptography/generate_cbom.py b/misc/scripts/cryptography/generate_cbom.py index fa4c2cb1d023..6bd0d19712c5 100644 --- a/misc/scripts/cryptography/generate_cbom.py +++ b/misc/scripts/cryptography/generate_cbom.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import os +import re import sys import argparse import subprocess @@ -86,6 +87,7 @@ def main(): parser.add_argument("-c", "--codeql", required=True, help="Path to CodeQL CLI executable.") parser.add_argument("-d", "--database", required=True, help="Path to the CodeQL database.") parser.add_argument("-q", "--query", required=True, help="Path to the .ql query file.") + parser.add_argument("--queryid", required=True, help="Query ID for the analysis.") parser.add_argument("-o", "--output", required=True, help="Output directory for analysis results.") args = parser.parse_args() @@ -94,7 +96,13 @@ def main(): run_codeql_analysis(args.codeql, args.database, args.query, args.output) # Locate DGML file - dgml_file = os.path.join(args.output, "java", "print-cbom-graph.dgml") + ALLOWED_QUERY_ID = re.compile(r'^[a-zA-Z0-9_\-]+$') + + if not ALLOWED_QUERY_ID.match(args.queryid): + print("Invalid query_id provided: '%s'. Allowed characters: letters, digits, '_', and '-'.", args.queryid) + sys.exit(1) + + dgml_file = os.path.join(args.output, "java", '{}.dgml'.format(args.queryid)) dot_file = dgml_file.replace(".dgml", ".dot") if os.path.exists(dgml_file): diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 510f334bc626..b3c104cbc5ed 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -3,7 +3,6 @@ */ import codeql.util.Location -import codeql.util.Option import codeql.util.Either signature module InputSig { @@ -379,6 +378,8 @@ module CryptographyBase Input> { exists(KeyDerivationOperationInstance op | inputNode = op.getInputConsumer()) or exists(MACOperationInstance op | inputNode = op.getMessageConsumer()) + or + exists(HashOperationInstance op | inputNode = op.getInputConsumer()) ) and this = Input::dfn_to_element(inputNode) } @@ -410,16 +411,11 @@ module CryptographyBase Input> { } } - /** - * An artifact representing a hash function's digest output. - */ - abstract class DigestArtifactInstance extends OutputArtifactInstance { } - /** * An artifact representing a random number generator's output. */ abstract class RandomNumberGenerationInstance extends OutputArtifactInstance { - // TODO: input seed? + abstract string getGeneratorName(); } /** @@ -438,6 +434,17 @@ module CryptographyBase Input> { override DataFlowNode getOutputNode() { result = creator.getOutputArtifact() } } + /** + * An artifact representing the message digest output of a hash operation. + */ + final class HashOutputArtifactInstance extends OutputArtifactInstance { + HashOperationInstance creator; + + HashOutputArtifactInstance() { Input::dfn_to_element(creator.getOutputArtifact()) = this } + + override DataFlowNode getOutputNode() { result = creator.getOutputArtifact() } + } + /** * An artifact representing the shared secret generated by key agreement operations. */ @@ -489,8 +496,14 @@ module CryptographyBase Input> { // TODO: key type hint? e.g. hint: private || public KeyArtifactConsumer() { ( - exists(KeyOperationInstance op | inputNode = op.getKeyConsumer()) or + exists(KeyOperationInstance op | inputNode = op.getKeyConsumer()) + or exists(MACOperationInstance op | inputNode = op.getKeyConsumer()) + or + exists(KeyAgreementSecretGenerationOperationInstance op | + inputNode = op.getServerKeyConsumer() or + inputNode = op.getPeerKeyConsumer() + ) ) and this = Input::dfn_to_element(inputNode) } @@ -770,7 +783,22 @@ module CryptographyBase Input> { * * If the algorithm accepts a range of key sizes without a particular one specified, this predicate should be implemented as `none()`. */ - abstract string getKeySize(); + abstract string getKeySizeFixed(); + + /** + * Gets a consumer for the key size in bits specified for this algorithm variant. + */ + abstract ConsumerInputDataFlowNode getKeySizeConsumer(); + + /** + * Holds if this algorithm is expected to have a mode specified. + */ + predicate shouldHaveModeOfOperation() { any() } + + /** + * Holds if this algorithm is expected to have a padding scheme specified. + */ + predicate shouldHavePaddingScheme() { any() } } newtype TBlockCipherModeOfOperationType = @@ -904,7 +932,9 @@ module CryptographyBase Input> { } abstract class HashOperationInstance extends OperationInstance { - abstract DigestArtifactInstance getDigestArtifact(); + abstract ArtifactOutputDataFlowNode getOutputArtifact(); + + abstract ConsumerInputDataFlowNode getInputConsumer(); } abstract class HashAlgorithmInstance extends AlgorithmInstance { @@ -1151,7 +1181,7 @@ module CryptographyBase Input> { private newtype TNode = // Output artifacts (data that is not an operation or algorithm, e.g., a key) - TDigest(DigestArtifactInstance e) or + TDigest(HashOutputArtifactInstance e) or TKey(KeyArtifactInstance e) or TSharedSecret(KeyAgreementSharedSecretOutputArtifactInstance e) or // Input artifacts (synthetic nodes, used to differentiate input as entities) @@ -1442,6 +1472,15 @@ module CryptographyBase Input> { override LocatableElement asElement() { result = instance } override string getSourceNodeRelationship() { none() } // TODO: seed? + + override predicate properties(string key, string value, Location location) { + super.properties(key, value, location) + or + // [ONLY_KNOWN] + key = "Description" and + value = instance.getGeneratorName() and + location = this.getLocation() + } } /** @@ -1518,7 +1557,7 @@ module CryptographyBase Input> { * A digest artifact produced by a hash operation. */ final class DigestArtifactNode extends ArtifactNode, TDigest { - DigestArtifactInstance instance; + HashOutputArtifactInstance instance; DigestArtifactNode() { this = TDigest(instance) } @@ -1664,12 +1703,28 @@ module CryptographyBase Input> { result.asElement() = instance.getOutputArtifact().getArtifact() } + KeyArtifactNode getServerKey() { + result.asElement() = instance.getServerKeyConsumer().getConsumer() + } + + KeyArtifactNode getPeerKey() { + result.asElement() = instance.getPeerKeyConsumer().getConsumer() + } + override NodeBase getChild(string key) { result = super.getChild(key) or // [ALWAYS_KNOWN] key = "Output" and result = this.getOutput() + or + // [KNOWN_OR_UNKOWN] + key = "ServerKey" and + if exists(this.getServerKey()) then result = this.getServerKey() else result = this + or + // [KNOWN_OR_UNKOWN] + key = "PeerKey" and + if exists(this.getPeerKey()) then result = this.getPeerKey() else result = this } } @@ -2115,7 +2170,14 @@ module CryptographyBase Input> { /** * Gets the key size variant of this algorithm in bits, e.g., 128 for "AES-128". */ - string getKeySize() { result = instance.asAlg().getKeySize() } // TODO: key sizes for known algorithms + string getKeySizeFixed() { result = instance.asAlg().getKeySizeFixed() } // TODO: key sizes for known algorithms + + /** + * Gets the key size generic source node. + */ + GenericSourceNode getKeySize() { + result = instance.asAlg().getKeySizeConsumer().getConsumer().getAGenericSourceNode() + } /** * Gets the type of this key operation algorithm, e.g., "SymmetricEncryption(_)" or "" @@ -2139,17 +2201,23 @@ module CryptographyBase Input> { override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) or - // [KNOWN_OR_UNKNOWN] + // [KNOWN_OR_UNKNOWN] - but only if not suppressed edgeName = "Mode" and - if exists(this.getModeOfOperation()) - then result = this.getModeOfOperation() - else result = this + ( + if exists(this.getModeOfOperation()) + then result = this.getModeOfOperation() + else result = this + ) and + instance.asAlg().shouldHaveModeOfOperation() or - // [KNOWN_OR_UNKNOWN] + // [KNOWN_OR_UNKNOWN] - but only if not suppressed edgeName = "Padding" and - if exists(this.getPaddingAlgorithm()) - then result = this.getPaddingAlgorithm() - else result = this + ( + if exists(this.getPaddingAlgorithm()) + then result = this.getPaddingAlgorithm() + else result = this + ) and + instance.asAlg().shouldHavePaddingScheme() } override predicate properties(string key, string value, Location location) { @@ -2160,14 +2228,13 @@ module CryptographyBase Input> { this.getSymmetricCipherStructure().toString() = value and location = this.getLocation() or + // [ONLY_KNOWN] + key = "KeySize" and ( - // [KNOWN_OR_UNKNOWN] - key = "KeySize" and - if exists(this.getKeySize()) - then value = this.getKeySize() - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) + value = this.getKeySizeFixed() and + location = this.getLocation() + or + node_as_property(this.getKeySize(), value, location) ) } } @@ -2191,10 +2258,16 @@ module CryptographyBase Input> { node instanceof HashAlgorithmNode } + MessageArtifactNode getInputArtifact() { + result.asElement() = instance.getInputConsumer().getConsumer() + } + /** * Gets the output digest node */ - DigestArtifactNode getDigest() { result.asElement() = instance.getDigestArtifact() } + DigestArtifactNode getDigest() { + result.asElement() = instance.getOutputArtifact().getArtifact() + } override NodeBase getChild(string key) { result = super.getChild(key) @@ -2202,6 +2275,10 @@ module CryptographyBase Input> { // [KNOWN_OR_UNKNOWN] key = "Digest" and if exists(this.getDigest()) then result = this.getDigest() else result = this + or + // [KNOWN_OR_UNKNOWN] + key = "Message" and + if exists(this.getInputArtifact()) then result = this.getInputArtifact() else result = this } } From c263d3faf93f29d691612f947482365d2e08fa14 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Wed, 30 Apr 2025 17:39:22 +0200 Subject: [PATCH 188/336] Rust: Remove predicates unused after refactor --- .../lib/codeql/rust/internal/TypeInference.qll | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/TypeInference.qll index b999b72240bf..f553351868b3 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeInference.qll @@ -662,15 +662,6 @@ private module CallExprBaseMatchingInput implements MatchingInputSig { tAdj = t ) } - - pragma[nomagic] - additional Type inferReceiverType(AstNode n) { - exists(Access a, AccessPosition apos | - result = inferType(n) and - n = a.getNodeAt(apos) and - apos.isSelf() - ) - } } private module CallExprBaseMatching = Matching; @@ -813,15 +804,6 @@ private module FieldExprMatchingInput implements MatchingInputSig { tAdj = t ) } - - pragma[nomagic] - additional Type inferReceiverType(AstNode n) { - exists(Access a, AccessPosition apos | - result = inferType(n) and - n = a.getNodeAt(apos) and - apos.isSelf() - ) - } } private module FieldExprMatching = Matching; From c80588cda15b873c2f5c4196726104feb7c72065 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Wed, 30 Apr 2025 11:41:28 -0400 Subject: [PATCH 189/336] Adding content to KnownSymmetricCipherAlgorithmql. --- .../InventorySlices/KnownSymmetricCipherAlgorithm.ql | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql index e69de29bb2d1..21949f1c8c6d 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql @@ -0,0 +1,12 @@ +/** + * @name Detects known symmetric cipher algorithms + * @id java/crypto_inventory_slices/known_symmetric_cipher_algorithm + * @kind problem + */ + +import java +import experimental.Quantum.Language + +from Crypto::KeyOperationAlgorithmNode a +where a.getAlgorithmType() instanceof Crypto::KeyOpAlg::SymmetricCipherAlgorithm +select a, "Instance of symmetric cipher algorithm " + a.getAlgorithmName() From cf614a596d965f2584bfc568a9ec3dbd370ddbf6 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 30 Apr 2025 16:43:03 +0100 Subject: [PATCH 190/336] Fix cwe tags to include leading zero --- cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.ql | 2 +- .../src/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.ql | 2 +- .../Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.ql | 2 +- cpp/ql/src/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql | 2 +- cpp/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql | 2 +- .../Security/CWE/CWE-020/LateCheckOfFunctionArgument.ql | 2 +- csharp/ql/src/Configuration/PasswordInConfigurationFile.ql | 2 +- csharp/ql/src/Security Features/CWE-011/ASPNetDebug.ql | 2 +- .../ql/src/Security Features/CWE-016/ASPNetMaxRequestLength.ql | 2 +- .../src/Security Features/CWE-016/ASPNetPagesValidateRequest.ql | 2 +- .../CWE-020/ExternalAPIsUsedWithUntrustedData.ql | 2 +- csharp/ql/src/Security Features/CWE-020/RuntimeChecksBypass.ql | 2 +- .../src/Security Features/CWE-020/UntrustedDataToExternalAPI.ql | 2 +- .../CWE-248/MissingASPNETGlobalErrorHandler.ql | 2 +- go/ql/src/Security/CWE-020/ExternalAPIsUsedWithUntrustedData.ql | 2 +- go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql | 2 +- go/ql/src/Security/CWE-020/MissingRegexpAnchor.ql | 2 +- go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql | 2 +- go/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql | 2 +- go/ql/src/Security/CWE-020/UntrustedDataToUnknownExternalAPI.ql | 2 +- go/ql/src/experimental/CWE-090/LDAPInjection.ql | 2 +- go/ql/src/experimental/CWE-74/DsnInjection.ql | 2 +- go/ql/src/experimental/CWE-74/DsnInjectionLocal.ql | 2 +- .../src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql | 2 +- .../Security/CWE/CWE-020/ExternalAPIsUsedWithUntrustedData.ql | 2 +- java/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql | 2 +- java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql | 2 +- javascript/ql/src/Electron/DisablingWebSecurity.ql | 2 +- .../src/Security/CWE-020/ExternalAPIsUsedWithUntrustedData.ql | 2 +- .../ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql | 2 +- .../ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql | 2 +- .../CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql | 2 +- .../Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql | 2 +- python/ql/src/Security/CWE-020/CookieInjection.ql | 2 +- .../src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql | 2 +- python/ql/src/experimental/Security/CWE-094/Js2Py.ql | 2 +- .../ql/src/experimental/template-injection/TemplateInjection.ql | 2 +- 37 files changed, 37 insertions(+), 37 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.ql b/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.ql index 33c319722958..3aff4e1dcc2e 100644 --- a/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.ql +++ b/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.ql @@ -8,7 +8,7 @@ * @security-severity 7.8 * @precision high * @tags security - * external/cwe/cwe-14 + * external/cwe/cwe-014 */ import cpp diff --git a/cpp/ql/src/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.ql b/cpp/ql/src/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.ql index bebff32a5c1d..80bf2b8a8b39 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.ql +++ b/cpp/ql/src/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.ql @@ -5,7 +5,7 @@ * to it. * @id cpp/count-untrusted-data-external-api * @kind table - * @tags security external/cwe/cwe-20 + * @tags security external/cwe/cwe-020 */ import cpp diff --git a/cpp/ql/src/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.ql b/cpp/ql/src/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.ql index 69911c22c6af..3bc364c41164 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.ql +++ b/cpp/ql/src/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.ql @@ -5,7 +5,7 @@ * to it. * @id cpp/count-untrusted-data-external-api-ir * @kind table - * @tags security external/cwe/cwe-20 + * @tags security external/cwe/cwe-020 */ import cpp diff --git a/cpp/ql/src/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql b/cpp/ql/src/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql index 432f47f67355..07c97ed77fd2 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql +++ b/cpp/ql/src/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql @@ -6,7 +6,7 @@ * @precision low * @problem.severity error * @security-severity 7.8 - * @tags security external/cwe/cwe-20 + * @tags security external/cwe/cwe-020 */ import cpp diff --git a/cpp/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql b/cpp/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql index 1cfd0a7132f8..34ea739e6753 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql +++ b/cpp/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql @@ -6,7 +6,7 @@ * @precision low * @problem.severity error * @security-severity 7.8 - * @tags security external/cwe/cwe-20 + * @tags security external/cwe/cwe-020 */ import cpp diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-020/LateCheckOfFunctionArgument.ql b/cpp/ql/src/experimental/Security/CWE/CWE-020/LateCheckOfFunctionArgument.ql index 07d18992db66..be53ba1fc683 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-020/LateCheckOfFunctionArgument.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-020/LateCheckOfFunctionArgument.ql @@ -10,7 +10,7 @@ * @tags correctness * security * experimental - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import cpp diff --git a/csharp/ql/src/Configuration/PasswordInConfigurationFile.ql b/csharp/ql/src/Configuration/PasswordInConfigurationFile.ql index c6f004789a7d..a2fe7cf2290e 100644 --- a/csharp/ql/src/Configuration/PasswordInConfigurationFile.ql +++ b/csharp/ql/src/Configuration/PasswordInConfigurationFile.ql @@ -7,7 +7,7 @@ * @precision medium * @id cs/password-in-configuration * @tags security - * external/cwe/cwe-13 + * external/cwe/cwe-013 * external/cwe/cwe-256 * external/cwe/cwe-313 */ diff --git a/csharp/ql/src/Security Features/CWE-011/ASPNetDebug.ql b/csharp/ql/src/Security Features/CWE-011/ASPNetDebug.ql index 308f3eeeac2c..4e0e52352b47 100644 --- a/csharp/ql/src/Security Features/CWE-011/ASPNetDebug.ql +++ b/csharp/ql/src/Security Features/CWE-011/ASPNetDebug.ql @@ -10,7 +10,7 @@ * @tags security * maintainability * frameworks/asp.net - * external/cwe/cwe-11 + * external/cwe/cwe-011 * external/cwe/cwe-532 */ diff --git a/csharp/ql/src/Security Features/CWE-016/ASPNetMaxRequestLength.ql b/csharp/ql/src/Security Features/CWE-016/ASPNetMaxRequestLength.ql index 89bd133d59ae..b9ac41e0e39e 100644 --- a/csharp/ql/src/Security Features/CWE-016/ASPNetMaxRequestLength.ql +++ b/csharp/ql/src/Security Features/CWE-016/ASPNetMaxRequestLength.ql @@ -8,7 +8,7 @@ * @id cs/web/large-max-request-length * @tags security * frameworks/asp.net - * external/cwe/cwe-16 + * external/cwe/cwe-016 */ import csharp diff --git a/csharp/ql/src/Security Features/CWE-016/ASPNetPagesValidateRequest.ql b/csharp/ql/src/Security Features/CWE-016/ASPNetPagesValidateRequest.ql index 68902a0622d8..3c51b7a8e2e0 100644 --- a/csharp/ql/src/Security Features/CWE-016/ASPNetPagesValidateRequest.ql +++ b/csharp/ql/src/Security Features/CWE-016/ASPNetPagesValidateRequest.ql @@ -8,7 +8,7 @@ * @id cs/web/request-validation-disabled * @tags security * frameworks/asp.net - * external/cwe/cwe-16 + * external/cwe/cwe-016 */ import csharp diff --git a/csharp/ql/src/Security Features/CWE-020/ExternalAPIsUsedWithUntrustedData.ql b/csharp/ql/src/Security Features/CWE-020/ExternalAPIsUsedWithUntrustedData.ql index b07b1093ec88..8427ceb87eb0 100644 --- a/csharp/ql/src/Security Features/CWE-020/ExternalAPIsUsedWithUntrustedData.ql +++ b/csharp/ql/src/Security Features/CWE-020/ExternalAPIsUsedWithUntrustedData.ql @@ -5,7 +5,7 @@ * to it. * @id cs/count-untrusted-data-external-api * @kind table - * @tags security external/cwe/cwe-20 + * @tags security external/cwe/cwe-020 */ import csharp diff --git a/csharp/ql/src/Security Features/CWE-020/RuntimeChecksBypass.ql b/csharp/ql/src/Security Features/CWE-020/RuntimeChecksBypass.ql index 6148f0f6ae91..af0294590331 100644 --- a/csharp/ql/src/Security Features/CWE-020/RuntimeChecksBypass.ql +++ b/csharp/ql/src/Security Features/CWE-020/RuntimeChecksBypass.ql @@ -7,7 +7,7 @@ * @security-severity 7.8 * @precision medium * @tags security - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import semmle.code.csharp.serialization.Serialization diff --git a/csharp/ql/src/Security Features/CWE-020/UntrustedDataToExternalAPI.ql b/csharp/ql/src/Security Features/CWE-020/UntrustedDataToExternalAPI.ql index a71a2705bdda..0543f198d229 100644 --- a/csharp/ql/src/Security Features/CWE-020/UntrustedDataToExternalAPI.ql +++ b/csharp/ql/src/Security Features/CWE-020/UntrustedDataToExternalAPI.ql @@ -6,7 +6,7 @@ * @precision low * @problem.severity error * @security-severity 7.8 - * @tags security external/cwe/cwe-20 + * @tags security external/cwe/cwe-020 */ import csharp diff --git a/csharp/ql/src/Security Features/CWE-248/MissingASPNETGlobalErrorHandler.ql b/csharp/ql/src/Security Features/CWE-248/MissingASPNETGlobalErrorHandler.ql index f37d4c497de9..14d73c02e1ef 100644 --- a/csharp/ql/src/Security Features/CWE-248/MissingASPNETGlobalErrorHandler.ql +++ b/csharp/ql/src/Security Features/CWE-248/MissingASPNETGlobalErrorHandler.ql @@ -8,7 +8,7 @@ * @precision high * @id cs/web/missing-global-error-handler * @tags security - * external/cwe/cwe-12 + * external/cwe/cwe-012 * external/cwe/cwe-248 */ diff --git a/go/ql/src/Security/CWE-020/ExternalAPIsUsedWithUntrustedData.ql b/go/ql/src/Security/CWE-020/ExternalAPIsUsedWithUntrustedData.ql index b23cd0030232..2b32d8ffecc2 100644 --- a/go/ql/src/Security/CWE-020/ExternalAPIsUsedWithUntrustedData.ql +++ b/go/ql/src/Security/CWE-020/ExternalAPIsUsedWithUntrustedData.ql @@ -5,7 +5,7 @@ * to it. * @id go/count-untrusted-data-external-api * @kind table - * @tags security external/cwe/cwe-20 + * @tags security external/cwe/cwe-020 */ import go diff --git a/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql b/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql index 03018ee1c32d..89954b08f991 100644 --- a/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql +++ b/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql @@ -9,7 +9,7 @@ * @id go/incomplete-hostname-regexp * @tags correctness * security - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import go diff --git a/go/ql/src/Security/CWE-020/MissingRegexpAnchor.ql b/go/ql/src/Security/CWE-020/MissingRegexpAnchor.ql index df93440ac526..a478968e58b9 100644 --- a/go/ql/src/Security/CWE-020/MissingRegexpAnchor.ql +++ b/go/ql/src/Security/CWE-020/MissingRegexpAnchor.ql @@ -8,7 +8,7 @@ * @id go/regex/missing-regexp-anchor * @tags correctness * security - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import go diff --git a/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql b/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql index 81cc634346a3..e58cf8644904 100644 --- a/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql +++ b/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql @@ -8,7 +8,7 @@ * @id go/suspicious-character-in-regex * @tags correctness * security - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import go diff --git a/go/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql b/go/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql index 4ab22af3a459..6e8d99471ee4 100644 --- a/go/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql +++ b/go/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql @@ -6,7 +6,7 @@ * @precision low * @problem.severity error * @security-severity 7.8 - * @tags security external/cwe/cwe-20 + * @tags security external/cwe/cwe-020 */ import go diff --git a/go/ql/src/Security/CWE-020/UntrustedDataToUnknownExternalAPI.ql b/go/ql/src/Security/CWE-020/UntrustedDataToUnknownExternalAPI.ql index 23945e38d465..451980479040 100644 --- a/go/ql/src/Security/CWE-020/UntrustedDataToUnknownExternalAPI.ql +++ b/go/ql/src/Security/CWE-020/UntrustedDataToUnknownExternalAPI.ql @@ -6,7 +6,7 @@ * @precision low * @problem.severity error * @security-severity 7.8 - * @tags security external/cwe/cwe-20 + * @tags security external/cwe/cwe-020 */ import go diff --git a/go/ql/src/experimental/CWE-090/LDAPInjection.ql b/go/ql/src/experimental/CWE-090/LDAPInjection.ql index 7da669aa6120..6b269df20baf 100644 --- a/go/ql/src/experimental/CWE-090/LDAPInjection.ql +++ b/go/ql/src/experimental/CWE-090/LDAPInjection.ql @@ -7,7 +7,7 @@ * @id go/ldap-injection * @tags security * experimental - * external/cwe/cwe-90 + * external/cwe/cwe-090 */ import go diff --git a/go/ql/src/experimental/CWE-74/DsnInjection.ql b/go/ql/src/experimental/CWE-74/DsnInjection.ql index 2b2ee0a62e4c..c8df87e296ea 100644 --- a/go/ql/src/experimental/CWE-74/DsnInjection.ql +++ b/go/ql/src/experimental/CWE-74/DsnInjection.ql @@ -6,7 +6,7 @@ * @id go/dsn-injection * @tags security * experimental - * external/cwe/cwe-74 + * external/cwe/cwe-074 */ import go diff --git a/go/ql/src/experimental/CWE-74/DsnInjectionLocal.ql b/go/ql/src/experimental/CWE-74/DsnInjectionLocal.ql index 1744a25848b5..d741199ac229 100644 --- a/go/ql/src/experimental/CWE-74/DsnInjectionLocal.ql +++ b/go/ql/src/experimental/CWE-74/DsnInjectionLocal.ql @@ -6,7 +6,7 @@ * @id go/dsn-injection-local * @tags security * experimental - * external/cwe/cwe-74 + * external/cwe/cwe-074 */ import go diff --git a/go/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/go/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql index 0aff713f26bc..ff63f6bfbec7 100644 --- a/go/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql +++ b/go/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql @@ -7,7 +7,7 @@ * @id go/html-template-escaping-passthrough * @tags security * experimental - * external/cwe/cwe-79 + * external/cwe/cwe-079 */ import go diff --git a/java/ql/src/Security/CWE/CWE-020/ExternalAPIsUsedWithUntrustedData.ql b/java/ql/src/Security/CWE/CWE-020/ExternalAPIsUsedWithUntrustedData.ql index 23c82397de08..ffdfcaf9f80b 100644 --- a/java/ql/src/Security/CWE/CWE-020/ExternalAPIsUsedWithUntrustedData.ql +++ b/java/ql/src/Security/CWE/CWE-020/ExternalAPIsUsedWithUntrustedData.ql @@ -5,7 +5,7 @@ * to it. * @id java/count-untrusted-data-external-api * @kind table - * @tags security external/cwe/cwe-20 + * @tags security external/cwe/cwe-020 */ import java diff --git a/java/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql b/java/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql index fdbb34b2247f..a75672445fb1 100644 --- a/java/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql +++ b/java/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql @@ -6,7 +6,7 @@ * @precision low * @problem.severity error * @security-severity 7.8 - * @tags security external/cwe/cwe-20 + * @tags security external/cwe/cwe-020 */ import java diff --git a/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql b/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql index 7376aa51e584..fb7a40052f0b 100644 --- a/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql +++ b/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql @@ -9,7 +9,7 @@ * @precision high * @id java/netty-http-request-or-response-splitting * @tags security - * external/cwe/cwe-93 + * external/cwe/cwe-093 * external/cwe/cwe-113 */ diff --git a/javascript/ql/src/Electron/DisablingWebSecurity.ql b/javascript/ql/src/Electron/DisablingWebSecurity.ql index a2b0c0a8a01f..392d8fb73223 100644 --- a/javascript/ql/src/Electron/DisablingWebSecurity.ql +++ b/javascript/ql/src/Electron/DisablingWebSecurity.ql @@ -7,7 +7,7 @@ * @precision very-high * @tags security * frameworks/electron - * external/cwe/cwe-79 + * external/cwe/cwe-079 * @id js/disabling-electron-websecurity */ diff --git a/javascript/ql/src/Security/CWE-020/ExternalAPIsUsedWithUntrustedData.ql b/javascript/ql/src/Security/CWE-020/ExternalAPIsUsedWithUntrustedData.ql index 045edc172f3f..9f811c85c971 100644 --- a/javascript/ql/src/Security/CWE-020/ExternalAPIsUsedWithUntrustedData.ql +++ b/javascript/ql/src/Security/CWE-020/ExternalAPIsUsedWithUntrustedData.ql @@ -5,7 +5,7 @@ * to it. * @id js/count-untrusted-data-external-api * @kind table - * @tags security external/cwe/cwe-20 + * @tags security external/cwe/cwe-020 */ import javascript diff --git a/javascript/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql b/javascript/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql index 30931a6a5823..1fd1df14887b 100644 --- a/javascript/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql +++ b/javascript/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql @@ -6,7 +6,7 @@ * @precision low * @problem.severity error * @security-severity 7.8 - * @tags security external/cwe/cwe-20 + * @tags security external/cwe/cwe-020 */ import javascript diff --git a/javascript/ql/src/experimental/heuristics/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql b/javascript/ql/src/experimental/heuristics/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql index 4bf06b544474..fa7f313e9e51 100644 --- a/javascript/ql/src/experimental/heuristics/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql +++ b/javascript/ql/src/experimental/heuristics/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql @@ -7,7 +7,7 @@ * @problem.severity error * @security-severity 7.8 * @tags experimental - * security external/cwe/cwe-20 + * security external/cwe/cwe-020 */ import javascript diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql index ac374311ee8a..a0905e6626d3 100644 --- a/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql +++ b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql @@ -5,7 +5,7 @@ * to it. * @id py/count-untrusted-data-external-api * @kind table - * @tags security external/cwe/cwe-20 + * @tags security external/cwe/cwe-020 */ import python diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql b/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql index f5706ccc3a6d..feb5b77c02a8 100644 --- a/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql +++ b/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql @@ -6,7 +6,7 @@ * @precision low * @problem.severity error * @security-severity 7.8 - * @tags security external/cwe/cwe-20 + * @tags security external/cwe/cwe-020 */ import python diff --git a/python/ql/src/Security/CWE-020/CookieInjection.ql b/python/ql/src/Security/CWE-020/CookieInjection.ql index 0cb9c2dadbb6..e0600648eac2 100644 --- a/python/ql/src/Security/CWE-020/CookieInjection.ql +++ b/python/ql/src/Security/CWE-020/CookieInjection.ql @@ -7,7 +7,7 @@ * @security-severity 5.0 * @id py/cookie-injection * @tags security - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import python diff --git a/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql b/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql index 5ab77438d637..1dbd95d5533e 100644 --- a/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql +++ b/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql @@ -8,7 +8,7 @@ * @id py/incomplete-url-substring-sanitization * @tags correctness * security - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import python diff --git a/python/ql/src/experimental/Security/CWE-094/Js2Py.ql b/python/ql/src/experimental/Security/CWE-094/Js2Py.ql index 2bb3fea1b329..53c919d97327 100644 --- a/python/ql/src/experimental/Security/CWE-094/Js2Py.ql +++ b/python/ql/src/experimental/Security/CWE-094/Js2Py.ql @@ -8,7 +8,7 @@ * @id py/js2py-rce * @tags security * experimental - * external/cwe/cwe-94 + * external/cwe/cwe-094 */ import python diff --git a/ruby/ql/src/experimental/template-injection/TemplateInjection.ql b/ruby/ql/src/experimental/template-injection/TemplateInjection.ql index 7ad81c34123a..7ad670d6ec12 100644 --- a/ruby/ql/src/experimental/template-injection/TemplateInjection.ql +++ b/ruby/ql/src/experimental/template-injection/TemplateInjection.ql @@ -8,7 +8,7 @@ * @precision high * @id rb/server-side-template-injection * @tags security - * external/cwe/cwe-94 + * external/cwe/cwe-094 */ import codeql.ruby.DataFlow From a9132c43d0072ec2fb270aef24183349cfc5121c Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 30 Apr 2025 16:47:35 +0100 Subject: [PATCH 191/336] Fix incorrect CWE tags --- python/ql/src/Expressions/UseofInput.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/Expressions/UseofInput.ql b/python/ql/src/Expressions/UseofInput.ql index b7e9b6f7d9d8..b5e49a65f989 100644 --- a/python/ql/src/Expressions/UseofInput.ql +++ b/python/ql/src/Expressions/UseofInput.ql @@ -4,8 +4,8 @@ * @kind problem * @tags security * correctness - * security/cwe/cwe-94 - * security/cwe/cwe-95 + * external/cwe/cwe-094 + * external/cwe/cwe-095 * @problem.severity error * @security-severity 9.8 * @sub-severity high From 3423a1072ac2c39e91581f9d3d3241d185410321 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Wed, 30 Apr 2025 19:10:35 +0200 Subject: [PATCH 192/336] C++: Address review comments --- cpp/ql/integration-tests/header-variant-tests/clang-pch/test.py | 2 +- .../header-variant-tests/microsoft-pch/test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/integration-tests/header-variant-tests/clang-pch/test.py b/cpp/ql/integration-tests/header-variant-tests/clang-pch/test.py index d7bc5fe6352f..0a48fc3a79ce 100644 --- a/cpp/ql/integration-tests/header-variant-tests/clang-pch/test.py +++ b/cpp/ql/integration-tests/header-variant-tests/clang-pch/test.py @@ -3,7 +3,7 @@ def test(codeql, cpp): os.mkdir("pch") - extractor = f"{cpp.get_tool("extractor")}" + extractor = cpp.get_tool("extractor") codeql.database.create(command=[ f'"{extractor}" --mimic-clang -emit-pch -o pch/a.pch a.c', f'"{extractor}" --mimic-clang -include-pch pch/a.pch -Iextra_dummy_path b.c', diff --git a/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/test.py b/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/test.py index d734f0335f17..89bceec397e8 100644 --- a/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/test.py +++ b/cpp/ql/integration-tests/header-variant-tests/microsoft-pch/test.py @@ -3,7 +3,7 @@ def test(codeql, cpp): os.mkdir("pch") - extractor = f"{cpp.get_tool("extractor")}" + extractor = cpp.get_tool("extractor") codeql.database.create(command=[ f'"{extractor}" --mimic-cl /Yca.h /Fppch/a.pch a.c', f'"{extractor}" --mimic-cl /Yub.h /Fppch/a.pch b.c', From 531f2a15a4414441ab19cdb7bc524175430529ff Mon Sep 17 00:00:00 2001 From: yoff Date: Wed, 30 Apr 2025 19:58:14 +0200 Subject: [PATCH 193/336] python: model `send_header` from `http.server` --- .../ql/lib/semmle/python/frameworks/Stdlib.qll | 16 ++++++++++++++++ .../frameworks/stdlib/http_server.py | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 4ad671bb19aa..2d4bd83a55a1 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -1963,6 +1963,22 @@ module StdlibPrivate { /** Gets a reference to an instance of the `BaseHttpRequestHandler` class or any subclass. */ DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) } + /** A call to a method that writes to a response header. */ + private class HeaderWriteCall extends Http::Server::ResponseHeaderWrite::Range, + DataFlow::MethodCallNode + { + HeaderWriteCall() { this.calls(instance(), "send_header") } + + override DataFlow::Node getNameArg() { result = this.getArg(0) } + + override DataFlow::Node getValueArg() { result = this.getArg(1) } + + // TODO: These checks perhaps could be made more precise. + override predicate nameAllowsNewline() { any() } + + override predicate valueAllowsNewline() { any() } + } + private class AdditionalTaintStep extends TaintTracking::AdditionalTaintStep { override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { nodeFrom = instance() and diff --git a/python/ql/test/library-tests/frameworks/stdlib/http_server.py b/python/ql/test/library-tests/frameworks/stdlib/http_server.py index 9110aa6a26a9..8e9fd925c249 100644 --- a/python/ql/test/library-tests/frameworks/stdlib/http_server.py +++ b/python/ql/test/library-tests/frameworks/stdlib/http_server.py @@ -83,7 +83,7 @@ def taint_sources(self): def do_GET(self): # $ requestHandler # send_response will log a line to stderr self.send_response(200) - self.send_header("Content-type", "text/plain; charset=utf-8") + self.send_header("Content-type", "text/plain; charset=utf-8") # $ headerWriteNameUnsanitized="Content-type" headerWriteValueUnsanitized="text/plain; charset=utf-8" self.end_headers() self.wfile.write(b"Hello BaseHTTPRequestHandler\n") self.wfile.writelines([b"1\n", b"2\n", b"3\n"]) From cf45e771f3a1bd2b4e91f4dcfef0bda6bcb0b022 Mon Sep 17 00:00:00 2001 From: yoff Date: Wed, 30 Apr 2025 20:01:43 +0200 Subject: [PATCH 194/336] python: remove copied comment --- python/ql/lib/semmle/python/frameworks/Stdlib.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 2d4bd83a55a1..4a3c346fb016 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -1973,7 +1973,6 @@ module StdlibPrivate { override DataFlow::Node getValueArg() { result = this.getArg(1) } - // TODO: These checks perhaps could be made more precise. override predicate nameAllowsNewline() { any() } override predicate valueAllowsNewline() { any() } From e63b38c515db9730258956573ad2784934ef8b54 Mon Sep 17 00:00:00 2001 From: yoff Date: Wed, 30 Apr 2025 20:05:55 +0200 Subject: [PATCH 195/336] python: add change note --- python/ql/lib/change-notes/2025-04-30-model-send-header.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 python/ql/lib/change-notes/2025-04-30-model-send-header.md diff --git a/python/ql/lib/change-notes/2025-04-30-model-send-header.md b/python/ql/lib/change-notes/2025-04-30-model-send-header.md new file mode 100644 index 000000000000..032e984bdf3a --- /dev/null +++ b/python/ql/lib/change-notes/2025-04-30-model-send-header.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added header write model for `send_header` in `http.server`. \ No newline at end of file From 723778fa82823b2355cabf90698da6392668e0cb Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Wed, 30 Apr 2025 20:31:12 +0200 Subject: [PATCH 196/336] C++: Limit flow through sinks and sources in `cpp/upcast-array-pointer-arithmetic` --- .../src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql b/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql index 7dda356353ed..d1645007a321 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql @@ -44,6 +44,10 @@ module CastToPointerArithFlowConfig implements DataFlow::StateConfigSig { ) and getFullyConvertedType(node) = state } + + predicate isBarrierIn(DataFlow::Node node) { isSource(node, _) } + + predicate isBarrierOut(DataFlow::Node node) { isSink(node, _) } } /** From 51e70d0c3bff9ba69b40f50c6fc4267056f32f89 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 24 Apr 2025 13:04:21 +0200 Subject: [PATCH 197/336] Rust: Add Copilot generated test for `?` operator expressions --- .../test/library-tests/type-inference/main.rs | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/rust/ql/test/library-tests/type-inference/main.rs b/rust/ql/test/library-tests/type-inference/main.rs index 1972b181c83c..7e8ab73d00d2 100644 --- a/rust/ql/test/library-tests/type-inference/main.rs +++ b/rust/ql/test/library-tests/type-inference/main.rs @@ -919,6 +919,99 @@ mod borrowed_typed { } } +mod try_expressions { + use std::fmt::Debug; + + #[derive(Debug)] + struct S1; + + #[derive(Debug)] + struct S2; + + #[derive(Debug)] + enum MyResult { + MyOk(T), + MyErr(E), + } + + impl MyResult { + fn map(self, op: F) -> MyResult + where + F: FnOnce(T) -> U, + { + match self { + MyResult::MyOk(t) => MyResult::MyOk(op(t)), + MyResult::MyErr(e) => MyResult::MyErr(e), + } + } + + fn and_then(self, op: F) -> MyResult + where + F: FnOnce(T) -> MyResult, + { + match self { + MyResult::MyOk(t) => op(t), + MyResult::MyErr(e) => MyResult::MyErr(e), + } + } + } + + // For the try operator to work, we need to implement From for OtherE + impl From for S2 { + fn from(s: S1) -> S2 { + S2 + } + } + + // Simple function using ? operator with same error types + fn try_same_error() -> MyResult { + let x = MyResult::MyOk(S1)?; // $ type=x:S1 + MyResult::MyOk(x) + } + + // Function using ? operator with different error types that need conversion + fn try_convert_error() -> MyResult { + let x: MyResult = MyResult::MyOk(S1); + let y = x?; // $ type=y:S1 + MyResult::MyOk(y) + } + + // Chained ? operations + fn try_chained() -> MyResult { + let x: MyResult, S1> = MyResult::MyOk(MyResult::MyOk(S1)); + let y = x?.map(|s| s)?; // First ? returns MyResult, second ? returns S1 + MyResult::MyOk(y) + } + + // Function that uses ? with closures and complex error cases + fn try_complex(input: MyResult) -> MyResult { + let value = input?; // $ method=From::from + let mapped = MyResult::MyOk(value).and_then(|v| { + println!("{:?}", v); + MyResult::MyOk::<_, S1>(v) + })?; // $ method=From::from + MyResult::MyOk(mapped) + } + + pub fn f() { + if let MyResult::MyOk(result) = try_same_error() { + println!("{:?}", result); + } + + if let MyResult::MyOk(result) = try_convert_error() { + println!("{:?}", result); + } + + if let MyResult::MyOk(result) = try_chained() { + println!("{:?}", result); + } + + if let MyResult::MyOk(result) = try_complex(MyResult::MyOk(S1)) { + println!("{:?}", result); + } + } +} + fn main() { field_access::f(); method_impl::f(); @@ -935,4 +1028,5 @@ fn main() { trait_implicit_self_borrow::f(); implicit_self_borrow::f(); borrowed_typed::f(); + try_expressions::f(); } From 88075c4c8cdd60ad9a7db5f93f3e9741ab64a5f5 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 24 Apr 2025 13:05:14 +0200 Subject: [PATCH 198/336] Rust: Make manual tweaks to Copilot generated code --- .../test/library-tests/type-inference/main.rs | 78 +++++------------ .../type-inference/type-inference.expected | 86 ++++++++++++++++++- 2 files changed, 104 insertions(+), 60 deletions(-) diff --git a/rust/ql/test/library-tests/type-inference/main.rs b/rust/ql/test/library-tests/type-inference/main.rs index 7e8ab73d00d2..0b93a8511a06 100644 --- a/rust/ql/test/library-tests/type-inference/main.rs +++ b/rust/ql/test/library-tests/type-inference/main.rs @@ -928,85 +928,51 @@ mod try_expressions { #[derive(Debug)] struct S2; - #[derive(Debug)] - enum MyResult { - MyOk(T), - MyErr(E), - } - - impl MyResult { - fn map(self, op: F) -> MyResult - where - F: FnOnce(T) -> U, - { - match self { - MyResult::MyOk(t) => MyResult::MyOk(op(t)), - MyResult::MyErr(e) => MyResult::MyErr(e), - } - } - - fn and_then(self, op: F) -> MyResult - where - F: FnOnce(T) -> MyResult, - { - match self { - MyResult::MyOk(t) => op(t), - MyResult::MyErr(e) => MyResult::MyErr(e), - } - } - } - - // For the try operator to work, we need to implement From for OtherE - impl From for S2 { - fn from(s: S1) -> S2 { - S2 - } - } - // Simple function using ? operator with same error types - fn try_same_error() -> MyResult { - let x = MyResult::MyOk(S1)?; // $ type=x:S1 - MyResult::MyOk(x) + fn try_same_error() -> Result { + let x = Result::Ok(S1)?; // $ MISSING: type=x:S1 + Result::Ok(S1) } // Function using ? operator with different error types that need conversion - fn try_convert_error() -> MyResult { - let x: MyResult = MyResult::MyOk(S1); - let y = x?; // $ type=y:S1 - MyResult::MyOk(y) + fn try_convert_error() -> Result { + let x = Result::Ok(S1); + let y = x?; // $ MISSING: type=y:S1 + Result::Ok(S1) } // Chained ? operations - fn try_chained() -> MyResult { - let x: MyResult, S1> = MyResult::MyOk(MyResult::MyOk(S1)); - let y = x?.map(|s| s)?; // First ? returns MyResult, second ? returns S1 - MyResult::MyOk(y) + fn try_chained() -> Result { + let x = Result::Ok(Result::Ok(S1)); + // First ? returns Result, second ? returns S1 + let y = x?.map(|s| s)?; // $ MISSING: method=map + Result::Ok(S1) } // Function that uses ? with closures and complex error cases - fn try_complex(input: MyResult) -> MyResult { - let value = input?; // $ method=From::from - let mapped = MyResult::MyOk(value).and_then(|v| { + fn try_complex(input: Result) -> Result { + let value = input?; + let mapped = Result::Ok(value).and_then(|v| { println!("{:?}", v); - MyResult::MyOk::<_, S1>(v) - })?; // $ method=From::from - MyResult::MyOk(mapped) + Result::Ok::<_, S1>(v) + })?; // $ method=and_then + Result::Err(S1) } pub fn f() { - if let MyResult::MyOk(result) = try_same_error() { + if let Result::Ok(result) = try_same_error() { println!("{:?}", result); } - if let MyResult::MyOk(result) = try_convert_error() { + if let Result::Ok(result) = try_convert_error() { println!("{:?}", result); } - if let MyResult::MyOk(result) = try_chained() { + if let Result::Ok(result) = try_chained() { println!("{:?}", result); } - if let MyResult::MyOk(result) = try_complex(MyResult::MyOk(S1)) { + if let Result::Ok(result) = try_complex(Result::Ok(S1)) { println!("{:?}", result); } } diff --git a/rust/ql/test/library-tests/type-inference/type-inference.expected b/rust/ql/test/library-tests/type-inference/type-inference.expected index c91b3cef3dc3..c9b7b349a70c 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -1005,7 +1005,85 @@ inferType | main.rs:918:15:918:16 | &x | | file://:0:0:0:0 | & | | main.rs:918:15:918:16 | &x | &T | main.rs:894:5:894:13 | S | | main.rs:918:16:918:16 | x | | main.rs:894:5:894:13 | S | -| main.rs:924:5:924:20 | ...::f(...) | | main.rs:67:5:67:21 | Foo | -| main.rs:925:5:925:60 | ...::g(...) | | main.rs:67:5:67:21 | Foo | -| main.rs:925:20:925:38 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo | -| main.rs:925:41:925:59 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo | +| main.rs:932:43:935:5 | { ... } | | file://:0:0:0:0 | Result | +| main.rs:932:43:935:5 | { ... } | E | main.rs:925:5:926:14 | S1 | +| main.rs:932:43:935:5 | { ... } | T | main.rs:925:5:926:14 | S1 | +| main.rs:933:17:933:30 | ...::Ok(...) | | file://:0:0:0:0 | Result | +| main.rs:933:17:933:30 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 | +| main.rs:933:28:933:29 | S1 | | main.rs:925:5:926:14 | S1 | +| main.rs:934:9:934:22 | ...::Ok(...) | | file://:0:0:0:0 | Result | +| main.rs:934:9:934:22 | ...::Ok(...) | E | main.rs:925:5:926:14 | S1 | +| main.rs:934:9:934:22 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 | +| main.rs:934:20:934:21 | S1 | | main.rs:925:5:926:14 | S1 | +| main.rs:938:46:942:5 | { ... } | | file://:0:0:0:0 | Result | +| main.rs:938:46:942:5 | { ... } | E | main.rs:928:5:929:14 | S2 | +| main.rs:938:46:942:5 | { ... } | T | main.rs:925:5:926:14 | S1 | +| main.rs:939:13:939:13 | x | | file://:0:0:0:0 | Result | +| main.rs:939:13:939:13 | x | T | main.rs:925:5:926:14 | S1 | +| main.rs:939:17:939:30 | ...::Ok(...) | | file://:0:0:0:0 | Result | +| main.rs:939:17:939:30 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 | +| main.rs:939:28:939:29 | S1 | | main.rs:925:5:926:14 | S1 | +| main.rs:940:17:940:17 | x | | file://:0:0:0:0 | Result | +| main.rs:940:17:940:17 | x | T | main.rs:925:5:926:14 | S1 | +| main.rs:941:9:941:22 | ...::Ok(...) | | file://:0:0:0:0 | Result | +| main.rs:941:9:941:22 | ...::Ok(...) | E | main.rs:928:5:929:14 | S2 | +| main.rs:941:9:941:22 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 | +| main.rs:941:20:941:21 | S1 | | main.rs:925:5:926:14 | S1 | +| main.rs:945:40:950:5 | { ... } | | file://:0:0:0:0 | Result | +| main.rs:945:40:950:5 | { ... } | E | main.rs:928:5:929:14 | S2 | +| main.rs:945:40:950:5 | { ... } | T | main.rs:925:5:926:14 | S1 | +| main.rs:946:13:946:13 | x | | file://:0:0:0:0 | Result | +| main.rs:946:13:946:13 | x | T | file://:0:0:0:0 | Result | +| main.rs:946:13:946:13 | x | T.T | main.rs:925:5:926:14 | S1 | +| main.rs:946:17:946:42 | ...::Ok(...) | | file://:0:0:0:0 | Result | +| main.rs:946:17:946:42 | ...::Ok(...) | T | file://:0:0:0:0 | Result | +| main.rs:946:17:946:42 | ...::Ok(...) | T.T | main.rs:925:5:926:14 | S1 | +| main.rs:946:28:946:41 | ...::Ok(...) | | file://:0:0:0:0 | Result | +| main.rs:946:28:946:41 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 | +| main.rs:946:39:946:40 | S1 | | main.rs:925:5:926:14 | S1 | +| main.rs:948:17:948:17 | x | | file://:0:0:0:0 | Result | +| main.rs:948:17:948:17 | x | T | file://:0:0:0:0 | Result | +| main.rs:948:17:948:17 | x | T.T | main.rs:925:5:926:14 | S1 | +| main.rs:949:9:949:22 | ...::Ok(...) | | file://:0:0:0:0 | Result | +| main.rs:949:9:949:22 | ...::Ok(...) | E | main.rs:928:5:929:14 | S2 | +| main.rs:949:9:949:22 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 | +| main.rs:949:20:949:21 | S1 | | main.rs:925:5:926:14 | S1 | +| main.rs:953:30:953:34 | input | | file://:0:0:0:0 | Result | +| main.rs:953:30:953:34 | input | E | main.rs:925:5:926:14 | S1 | +| main.rs:953:30:953:34 | input | T | main.rs:953:20:953:27 | T | +| main.rs:953:69:960:5 | { ... } | | file://:0:0:0:0 | Result | +| main.rs:953:69:960:5 | { ... } | E | main.rs:925:5:926:14 | S1 | +| main.rs:953:69:960:5 | { ... } | T | main.rs:953:20:953:27 | T | +| main.rs:954:21:954:25 | input | | file://:0:0:0:0 | Result | +| main.rs:954:21:954:25 | input | E | main.rs:925:5:926:14 | S1 | +| main.rs:954:21:954:25 | input | T | main.rs:953:20:953:27 | T | +| main.rs:955:22:955:38 | ...::Ok(...) | | file://:0:0:0:0 | Result | +| main.rs:955:22:958:10 | ... .and_then(...) | | file://:0:0:0:0 | Result | +| main.rs:955:53:958:9 | { ... } | | file://:0:0:0:0 | Result | +| main.rs:955:53:958:9 | { ... } | E | main.rs:925:5:926:14 | S1 | +| main.rs:957:13:957:34 | ...::Ok::<...>(...) | | file://:0:0:0:0 | Result | +| main.rs:957:13:957:34 | ...::Ok::<...>(...) | E | main.rs:925:5:926:14 | S1 | +| main.rs:959:9:959:23 | ...::Err(...) | | file://:0:0:0:0 | Result | +| main.rs:959:9:959:23 | ...::Err(...) | E | main.rs:925:5:926:14 | S1 | +| main.rs:959:9:959:23 | ...::Err(...) | T | main.rs:953:20:953:27 | T | +| main.rs:959:21:959:22 | S1 | | main.rs:925:5:926:14 | S1 | +| main.rs:963:37:963:52 | try_same_error(...) | | file://:0:0:0:0 | Result | +| main.rs:963:37:963:52 | try_same_error(...) | E | main.rs:925:5:926:14 | S1 | +| main.rs:963:37:963:52 | try_same_error(...) | T | main.rs:925:5:926:14 | S1 | +| main.rs:967:37:967:55 | try_convert_error(...) | | file://:0:0:0:0 | Result | +| main.rs:967:37:967:55 | try_convert_error(...) | E | main.rs:928:5:929:14 | S2 | +| main.rs:967:37:967:55 | try_convert_error(...) | T | main.rs:925:5:926:14 | S1 | +| main.rs:971:37:971:49 | try_chained(...) | | file://:0:0:0:0 | Result | +| main.rs:971:37:971:49 | try_chained(...) | E | main.rs:928:5:929:14 | S2 | +| main.rs:971:37:971:49 | try_chained(...) | T | main.rs:925:5:926:14 | S1 | +| main.rs:975:37:975:63 | try_complex(...) | | file://:0:0:0:0 | Result | +| main.rs:975:37:975:63 | try_complex(...) | E | main.rs:925:5:926:14 | S1 | +| main.rs:975:37:975:63 | try_complex(...) | T | main.rs:925:5:926:14 | S1 | +| main.rs:975:49:975:62 | ...::Ok(...) | | file://:0:0:0:0 | Result | +| main.rs:975:49:975:62 | ...::Ok(...) | E | main.rs:925:5:926:14 | S1 | +| main.rs:975:49:975:62 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 | +| main.rs:975:60:975:61 | S1 | | main.rs:925:5:926:14 | S1 | +| main.rs:983:5:983:20 | ...::f(...) | | main.rs:67:5:67:21 | Foo | +| main.rs:984:5:984:60 | ...::g(...) | | main.rs:67:5:67:21 | Foo | +| main.rs:984:20:984:38 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo | +| main.rs:984:41:984:59 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo | From a3c26b4bfe57958419b2d2432c9c5dbf98408637 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 24 Apr 2025 13:05:42 +0200 Subject: [PATCH 199/336] Rust: Type inference for `?` expressions --- .../lib/codeql/rust/internal/TypeInference.qll | 14 ++++++++++++++ .../PathResolutionConsistency.expected | 17 +++++++++++++++++ .../test/library-tests/type-inference/main.rs | 6 +++--- .../type-inference/type-inference.expected | 11 +++++++++++ 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 rust/ql/test/library-tests/frameworks/postgres/CONSISTENCY/PathResolutionConsistency.expected diff --git a/rust/ql/lib/codeql/rust/internal/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/TypeInference.qll index 0f0c92306d12..5c5f678950a2 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeInference.qll @@ -6,6 +6,7 @@ private import Type private import Type as T private import TypeMention private import codeql.typeinference.internal.TypeInference +private import codeql.rust.frameworks.stdlib.Stdlib class Type = T::Type; @@ -891,6 +892,17 @@ private Type inferRefExprType(Expr e, TypePath path) { ) } +pragma[nomagic] +private Type inferTryExprType(TryExpr te, TypePath path) { + exists(TypeParam tp | + result = inferType(te.getExpr(), TypePath::cons(TTypeParamTypeParameter(tp), path)) + | + tp = any(ResultEnum r).getGenericParamList().getGenericParam(0) + or + tp = any(OptionEnum o).getGenericParamList().getGenericParam(0) + ) +} + cached private module Cached { private import codeql.rust.internal.CachedStages @@ -1008,6 +1020,8 @@ private module Cached { result = inferFieldExprType(n, path) or result = inferRefExprType(n, path) + or + result = inferTryExprType(n, path) } } diff --git a/rust/ql/test/library-tests/frameworks/postgres/CONSISTENCY/PathResolutionConsistency.expected b/rust/ql/test/library-tests/frameworks/postgres/CONSISTENCY/PathResolutionConsistency.expected new file mode 100644 index 000000000000..c47d16d68751 --- /dev/null +++ b/rust/ql/test/library-tests/frameworks/postgres/CONSISTENCY/PathResolutionConsistency.expected @@ -0,0 +1,17 @@ +multipleMethodCallTargets +| main.rs:11:5:18:5 | conn.execute(...) | file://:0:0:0:0 | fn execute | +| main.rs:11:5:18:5 | conn.execute(...) | file://:0:0:0:0 | fn execute | +| main.rs:22:5:22:37 | conn.execute(...) | file://:0:0:0:0 | fn execute | +| main.rs:22:5:22:37 | conn.execute(...) | file://:0:0:0:0 | fn execute | +| main.rs:23:5:23:38 | conn.batch_execute(...) | file://:0:0:0:0 | fn batch_execute | +| main.rs:23:5:23:38 | conn.batch_execute(...) | file://:0:0:0:0 | fn batch_execute | +| main.rs:25:5:25:32 | conn.prepare(...) | file://:0:0:0:0 | fn prepare | +| main.rs:25:5:25:32 | conn.prepare(...) | file://:0:0:0:0 | fn prepare | +| main.rs:28:5:28:35 | conn.query(...) | file://:0:0:0:0 | fn query | +| main.rs:28:5:28:35 | conn.query(...) | file://:0:0:0:0 | fn query | +| main.rs:29:5:29:39 | conn.query_one(...) | file://:0:0:0:0 | fn query_one | +| main.rs:29:5:29:39 | conn.query_one(...) | file://:0:0:0:0 | fn query_one | +| main.rs:30:5:30:39 | conn.query_opt(...) | file://:0:0:0:0 | fn query_opt | +| main.rs:30:5:30:39 | conn.query_opt(...) | file://:0:0:0:0 | fn query_opt | +| main.rs:35:17:35:67 | conn.query(...) | file://:0:0:0:0 | fn query | +| main.rs:35:17:35:67 | conn.query(...) | file://:0:0:0:0 | fn query | diff --git a/rust/ql/test/library-tests/type-inference/main.rs b/rust/ql/test/library-tests/type-inference/main.rs index 0b93a8511a06..fa16b6264740 100644 --- a/rust/ql/test/library-tests/type-inference/main.rs +++ b/rust/ql/test/library-tests/type-inference/main.rs @@ -930,14 +930,14 @@ mod try_expressions { // Simple function using ? operator with same error types fn try_same_error() -> Result { - let x = Result::Ok(S1)?; // $ MISSING: type=x:S1 + let x = Result::Ok(S1)?; // $ type=x:S1 Result::Ok(S1) } // Function using ? operator with different error types that need conversion fn try_convert_error() -> Result { let x = Result::Ok(S1); - let y = x?; // $ MISSING: type=y:S1 + let y = x?; // $ type=y:S1 Result::Ok(S1) } @@ -945,7 +945,7 @@ mod try_expressions { fn try_chained() -> Result { let x = Result::Ok(Result::Ok(S1)); // First ? returns Result, second ? returns S1 - let y = x?.map(|s| s)?; // $ MISSING: method=map + let y = x?.map(|s| s)?; // $ method=map Result::Ok(S1) } diff --git a/rust/ql/test/library-tests/type-inference/type-inference.expected b/rust/ql/test/library-tests/type-inference/type-inference.expected index c9b7b349a70c..42e5d90701b9 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -1008,8 +1008,10 @@ inferType | main.rs:932:43:935:5 | { ... } | | file://:0:0:0:0 | Result | | main.rs:932:43:935:5 | { ... } | E | main.rs:925:5:926:14 | S1 | | main.rs:932:43:935:5 | { ... } | T | main.rs:925:5:926:14 | S1 | +| main.rs:933:13:933:13 | x | | main.rs:925:5:926:14 | S1 | | main.rs:933:17:933:30 | ...::Ok(...) | | file://:0:0:0:0 | Result | | main.rs:933:17:933:30 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 | +| main.rs:933:17:933:31 | TryExpr | | main.rs:925:5:926:14 | S1 | | main.rs:933:28:933:29 | S1 | | main.rs:925:5:926:14 | S1 | | main.rs:934:9:934:22 | ...::Ok(...) | | file://:0:0:0:0 | Result | | main.rs:934:9:934:22 | ...::Ok(...) | E | main.rs:925:5:926:14 | S1 | @@ -1023,8 +1025,10 @@ inferType | main.rs:939:17:939:30 | ...::Ok(...) | | file://:0:0:0:0 | Result | | main.rs:939:17:939:30 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 | | main.rs:939:28:939:29 | S1 | | main.rs:925:5:926:14 | S1 | +| main.rs:940:13:940:13 | y | | main.rs:925:5:926:14 | S1 | | main.rs:940:17:940:17 | x | | file://:0:0:0:0 | Result | | main.rs:940:17:940:17 | x | T | main.rs:925:5:926:14 | S1 | +| main.rs:940:17:940:18 | TryExpr | | main.rs:925:5:926:14 | S1 | | main.rs:941:9:941:22 | ...::Ok(...) | | file://:0:0:0:0 | Result | | main.rs:941:9:941:22 | ...::Ok(...) | E | main.rs:928:5:929:14 | S2 | | main.rs:941:9:941:22 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 | @@ -1044,6 +1048,9 @@ inferType | main.rs:948:17:948:17 | x | | file://:0:0:0:0 | Result | | main.rs:948:17:948:17 | x | T | file://:0:0:0:0 | Result | | main.rs:948:17:948:17 | x | T.T | main.rs:925:5:926:14 | S1 | +| main.rs:948:17:948:18 | TryExpr | | file://:0:0:0:0 | Result | +| main.rs:948:17:948:18 | TryExpr | T | main.rs:925:5:926:14 | S1 | +| main.rs:948:17:948:29 | ... .map(...) | | file://:0:0:0:0 | Result | | main.rs:949:9:949:22 | ...::Ok(...) | | file://:0:0:0:0 | Result | | main.rs:949:9:949:22 | ...::Ok(...) | E | main.rs:928:5:929:14 | S2 | | main.rs:949:9:949:22 | ...::Ok(...) | T | main.rs:925:5:926:14 | S1 | @@ -1054,11 +1061,15 @@ inferType | main.rs:953:69:960:5 | { ... } | | file://:0:0:0:0 | Result | | main.rs:953:69:960:5 | { ... } | E | main.rs:925:5:926:14 | S1 | | main.rs:953:69:960:5 | { ... } | T | main.rs:953:20:953:27 | T | +| main.rs:954:13:954:17 | value | | main.rs:953:20:953:27 | T | | main.rs:954:21:954:25 | input | | file://:0:0:0:0 | Result | | main.rs:954:21:954:25 | input | E | main.rs:925:5:926:14 | S1 | | main.rs:954:21:954:25 | input | T | main.rs:953:20:953:27 | T | +| main.rs:954:21:954:26 | TryExpr | | main.rs:953:20:953:27 | T | | main.rs:955:22:955:38 | ...::Ok(...) | | file://:0:0:0:0 | Result | +| main.rs:955:22:955:38 | ...::Ok(...) | T | main.rs:953:20:953:27 | T | | main.rs:955:22:958:10 | ... .and_then(...) | | file://:0:0:0:0 | Result | +| main.rs:955:33:955:37 | value | | main.rs:953:20:953:27 | T | | main.rs:955:53:958:9 | { ... } | | file://:0:0:0:0 | Result | | main.rs:955:53:958:9 | { ... } | E | main.rs:925:5:926:14 | S1 | | main.rs:957:13:957:34 | ...::Ok::<...>(...) | | file://:0:0:0:0 | Result | From 2ed48ae571c5303074bce306f0e6d9e9d78e922d Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Wed, 30 Apr 2025 20:51:27 +0200 Subject: [PATCH 200/336] C++: Update expected test results after barrier introduction --- .../CastArrayPointerArithmetic.expected | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Conversion/CastArrayPointerArithmetic/CastArrayPointerArithmetic.expected b/cpp/ql/test/query-tests/Likely Bugs/Conversion/CastArrayPointerArithmetic/CastArrayPointerArithmetic.expected index 3f66b2c20b30..75e2e581664e 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Conversion/CastArrayPointerArithmetic/CastArrayPointerArithmetic.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Conversion/CastArrayPointerArithmetic/CastArrayPointerArithmetic.expected @@ -3,22 +3,13 @@ edges | test.cpp:30:34:30:34 | b | test.cpp:31:2:31:2 | b | provenance | | | test.cpp:34:31:34:31 | b | test.cpp:35:2:35:2 | b | provenance | | | test.cpp:57:19:57:19 | d | test.cpp:26:29:26:29 | b | provenance | | -| test.cpp:57:19:57:19 | d | test.cpp:58:25:58:25 | d | provenance | | -| test.cpp:57:19:57:19 | d | test.cpp:59:21:59:21 | d | provenance | | | test.cpp:58:25:58:25 | d | test.cpp:30:34:30:34 | b | provenance | | -| test.cpp:58:25:58:25 | d | test.cpp:59:21:59:21 | d | provenance | | | test.cpp:59:21:59:21 | d | test.cpp:34:31:34:31 | b | provenance | | | test.cpp:74:19:74:21 | dss | test.cpp:26:29:26:29 | b | provenance | | -| test.cpp:74:19:74:21 | dss | test.cpp:75:25:75:27 | dss | provenance | | -| test.cpp:74:19:74:21 | dss | test.cpp:76:21:76:23 | dss | provenance | | | test.cpp:75:25:75:27 | dss | test.cpp:30:34:30:34 | b | provenance | | -| test.cpp:75:25:75:27 | dss | test.cpp:76:21:76:23 | dss | provenance | | | test.cpp:76:21:76:23 | dss | test.cpp:34:31:34:31 | b | provenance | | | test.cpp:86:19:86:20 | d2 | test.cpp:26:29:26:29 | b | provenance | | -| test.cpp:86:19:86:20 | d2 | test.cpp:87:25:87:26 | d2 | provenance | | -| test.cpp:86:19:86:20 | d2 | test.cpp:88:21:88:22 | d2 | provenance | | | test.cpp:87:25:87:26 | d2 | test.cpp:30:34:30:34 | b | provenance | | -| test.cpp:87:25:87:26 | d2 | test.cpp:88:21:88:22 | d2 | provenance | | | test.cpp:88:21:88:22 | d2 | test.cpp:34:31:34:31 | b | provenance | | nodes | test.cpp:26:29:26:29 | b | semmle.label | b | @@ -41,18 +32,9 @@ subpaths | test.cpp:27:2:27:2 | b | test.cpp:57:19:57:19 | d | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast | | test.cpp:27:2:27:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast | | test.cpp:27:2:27:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast | -| test.cpp:31:2:31:2 | b | test.cpp:57:19:57:19 | d | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast | | test.cpp:31:2:31:2 | b | test.cpp:58:25:58:25 | d | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:58:25:58:25 | d | this cast | -| test.cpp:31:2:31:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast | | test.cpp:31:2:31:2 | b | test.cpp:75:25:75:27 | dss | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:75:25:75:27 | dss | this cast | -| test.cpp:31:2:31:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast | | test.cpp:31:2:31:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast | -| test.cpp:35:2:35:2 | b | test.cpp:57:19:57:19 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast | -| test.cpp:35:2:35:2 | b | test.cpp:58:25:58:25 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:58:25:58:25 | d | this cast | | test.cpp:35:2:35:2 | b | test.cpp:59:21:59:21 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:59:21:59:21 | d | this cast | -| test.cpp:35:2:35:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast | -| test.cpp:35:2:35:2 | b | test.cpp:75:25:75:27 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:75:25:75:27 | dss | this cast | | test.cpp:35:2:35:2 | b | test.cpp:76:21:76:23 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:76:21:76:23 | dss | this cast | -| test.cpp:35:2:35:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast | -| test.cpp:35:2:35:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast | | test.cpp:35:2:35:2 | b | test.cpp:88:21:88:22 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:88:21:88:22 | d2 | this cast | From 36199b3f06253ba0a8a79af3a679c8d78a35d2dd Mon Sep 17 00:00:00 2001 From: Aditya Sharad Date: Wed, 30 Apr 2025 16:40:36 -0700 Subject: [PATCH 201/336] Docs: Fix escaping in 2.21.0 changelog These break when the RST is processed. Escape the backslashes and consistently add inline code blocks. --- .../codeql-overview/codeql-changelog/codeql-cli-2.21.0.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.0.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.0.rst index 7d62123a49a7..aa604d702e75 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.0.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.0.rst @@ -165,7 +165,7 @@ Java/Kotlin """"""""""" * Java extraction is now able to download Maven 3.9.x if a Maven Enforcer Plugin configuration indicates it is necessary. Maven 3.8.x is still preferred if the enforcer-plugin configuration (if any) permits it. -* Added a path injection sanitizer for calls to :code:`java.lang.String.matches`, :code:`java.lang.String.replace`, and :code:`java.lang.String.replaceAll` that make sure '/', '\', '..' are not in the path. +* Added a path injection sanitizer for calls to :code:`java.lang.String.matches`, :code:`java.lang.String.replace`, and :code:`java.lang.String.replaceAll` that make sure :code:`/`, :code:`\\`, :code:`..` are not in the path. JavaScript/TypeScript """"""""""""""""""""" @@ -207,5 +207,5 @@ JavaScript/TypeScript * Intersection :code:`&&` * Subtraction :code:`--` - * :code:`\q` quoted string + * :code:`\\q` quoted string From 499d224c2b1c85d0fcf083625c23c2495d44c244 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Thu, 1 May 2025 10:11:10 +0200 Subject: [PATCH 202/336] Rust: Update generated models for core and std --- .../frameworks/stdlib/lang-alloc.model.yml | 1 + .../ext/generated/rust/lang-alloc.model.yml | 320 +++- .../ext/generated/rust/lang-core.model.yml | 1346 ++++++++--------- .../generated/rust/lang-proc_macro.model.yml | 46 +- .../lib/ext/generated/rust/lang-std.model.yml | 399 ++++- .../dataflow/local/DataFlowStep.expected | 235 +-- .../dataflow/modeled/inline-flow.expected | 16 +- 7 files changed, 1368 insertions(+), 995 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml index effb389aeccf..8d177c4e8565 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml @@ -37,3 +37,4 @@ extensions: - ["lang:alloc", "<_ as crate::string::ToString>::to_string", "Argument[self]", "ReturnValue", "taint", "manual"] - ["lang:alloc", "::parse", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"] - ["lang:alloc", "::trim", "Argument[self]", "ReturnValue.Reference", "taint", "manual"] + - ["lang:alloc", "::from", "Argument[0]", "ReturnValue", "value", "manual"] diff --git a/rust/ql/lib/ext/generated/rust/lang-alloc.model.yml b/rust/ql/lib/ext/generated/rust/lang-alloc.model.yml index 7cd8a602f246..2b91ef421070 100644 --- a/rust/ql/lib/ext/generated/rust/lang-alloc.model.yml +++ b/rust/ql/lib/ext/generated/rust/lang-alloc.model.yml @@ -5,15 +5,22 @@ extensions: extensible: summaryModel data: - ["lang:alloc", "<&&str as crate::string::SpecToString>::spec_to_string", "Argument[self].Reference.Reference", "ReturnValue", "value", "dfc-generated"] - - ["lang:alloc", "<&crate::string::String as crate::str::pattern::Pattern>::into_searcher", "Argument[0]", "ReturnValue.Field[crate::str::pattern::StrSearcher::haystack]", "value", "dfc-generated"] - - ["lang:alloc", "<&crate::string::String as crate::str::pattern::Pattern>::into_searcher", "Argument[self].Element", "ReturnValue.Field[crate::str::pattern::StrSearcher::needle]", "value", "dfc-generated"] - - ["lang:alloc", "<&str as crate::string::SpecToString>::spec_to_string", "Argument[self].Reference.Field[crate::borrow::Cow::Owned(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "<&crate::string::String as crate::str::pattern::Pattern>::as_utf8_pattern", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::str::pattern::Utf8Pattern::StringPattern(0)]", "value", "dfc-generated"] + - ["lang:alloc", "<&str as crate::string::SpecToString>::spec_to_string", "Argument[self].Reference.Field[crate::string::String::vec]", "ReturnValue.Field[crate::string::String::vec]", "value", "dfc-generated"] + - ["lang:alloc", "<&str as crate::string::SpecToString>::spec_to_string", "Argument[self].Reference.Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "<&str as crate::string::SpecToString>::spec_to_string", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "<_ as crate::borrow::ToOwned>::clone_into", "Argument[self].Reference", "Argument[0].Reference", "value", "dfc-generated"] - ["lang:alloc", "<_ as crate::borrow::ToOwned>::clone_into", "Argument[self]", "Argument[0].Reference", "value", "dfc-generated"] + - ["lang:alloc", "<_ as crate::borrow::ToOwned>::to_owned", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "<_ as crate::borrow::ToOwned>::to_owned", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "<_ as crate::vec::spec_from_elem::SpecFromElem>::from_elem", "Argument[1]", "ReturnValue.Field[crate::vec::Vec::len]", "value", "dfc-generated"] - ["lang:alloc", "::borrow", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::clone", "Argument[self].Reference.Field[crate::borrow::Cow::Borrowed(0)]", "ReturnValue.Field[crate::borrow::Cow::Borrowed(0)]", "value", "dfc-generated"] - ["lang:alloc", "::as_ref", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::from", "Argument[0].Reference", "ReturnValue.Field[crate::borrow::Cow::Borrowed(0)].Reference", "value", "dfc-generated"] + - ["lang:alloc", "::from", "Argument[0]", "ReturnValue.Field[crate::borrow::Cow::Borrowed(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::from", "Argument[0]", "ReturnValue.Field[crate::borrow::Cow::Owned(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::from", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:alloc", "::add_assign", "Argument[0]", "Argument[self].Reference.Field[crate::borrow::Cow::Borrowed(0)]", "value", "dfc-generated"] - ["lang:alloc", "::add_assign", "Argument[0]", "Argument[self].Reference", "value", "dfc-generated"] - ["lang:alloc", "::deref", "Argument[self].Reference.Field[crate::borrow::Cow::Borrowed(0)]", "ReturnValue", "value", "dfc-generated"] @@ -21,8 +28,8 @@ extensions: - ["lang:alloc", "::to_mut", "Argument[self].Reference.Field[crate::borrow::Cow::Owned(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::borrow", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::borrow_mut", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::clone_from", "Argument[0].Reference", "Argument[self].Reference", "value", "dfc-generated"] - ["lang:alloc", "::clone_from", "Argument[0]", "Argument[self].Reference", "value", "dfc-generated"] - - ["lang:alloc", "::clone_from", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:alloc", "::as_mut", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::as_ref", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::try_from", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] @@ -31,6 +38,7 @@ extensions: - ["lang:alloc", "::deref", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::deref_mut", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::allocator", "Argument[0].Field[1]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::allocator", "Argument[0].Field[crate::boxed::Box(1)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::as_mut_ptr", "Argument[0].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::as_ptr", "Argument[0].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::downcast", "Argument[self]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] @@ -40,95 +48,293 @@ extensions: - ["lang:alloc", "::into_pin", "Argument[0]", "ReturnValue.Field[crate::pin::Pin::__pointer]", "value", "dfc-generated"] - ["lang:alloc", "::new_uninit_in", "Argument[0]", "ReturnValue.Field[crate::boxed::Box(1)]", "value", "dfc-generated"] - ["lang:alloc", "::new_zeroed_in", "Argument[0]", "ReturnValue.Field[crate::boxed::Box(1)]", "value", "dfc-generated"] - - ["lang:alloc", "::try_new_in", "Argument[1]", "ReturnValue.Field[crate::boxed::Box(1)]", "value", "dfc-generated"] - ["lang:alloc", "::try_new_uninit_in", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::boxed::Box(1)]", "value", "dfc-generated"] - ["lang:alloc", "::try_new_zeroed_in", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::boxed::Box(1)]", "value", "dfc-generated"] - ["lang:alloc", "::borrow", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::borrow", "Argument[self].Field[crate::bstr::ByteString(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::borrow_mut", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::borrow_mut", "Argument[self].Field[crate::bstr::ByteString(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::as_mut", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::as_mut", "Argument[self].Field[crate::bstr::ByteString(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::as_ref", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::as_ref", "Argument[self].Field[crate::bstr::ByteString(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::deref", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::deref", "Argument[self].Field[crate::bstr::ByteString(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::deref_mut", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::deref_mut", "Argument[self].Field[crate::bstr::ByteString(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::index", "Argument[self].Field[0].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::index", "Argument[self].Field[crate::bstr::ByteString(0)].Element", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::index_mut", "Argument[self].Field[0].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::index_mut", "Argument[self].Field[crate::bstr::ByteString(0)].Element", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::as_bytes", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::as_bytes", "Argument[self].Field[crate::bstr::ByteString(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::from", "Argument[0]", "ReturnValue.Field[crate::collections::TryReserveError::kind]", "value", "dfc-generated"] + - ["lang:alloc", "::kind", "Argument[self].Field[crate::collections::TryReserveError::kind].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::kind", "Argument[self].Field[crate::collections::TryReserveError::kind]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::kind", "Argument[self].Field[crate::collections::TryReserveError::kind]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self].Field[crate::collections::binary_heap::BinaryHeap::data].Reference", "ReturnValue.Field[crate::collections::binary_heap::BinaryHeap::data]", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self].Field[crate::collections::binary_heap::BinaryHeap::data]", "ReturnValue.Field[crate::collections::binary_heap::BinaryHeap::data]", "value", "dfc-generated"] + - ["lang:alloc", "::from", "Argument[0]", "ReturnValue.Field[crate::collections::binary_heap::BinaryHeap::data]", "value", "dfc-generated"] - ["lang:alloc", "::drain_sorted", "Argument[self]", "ReturnValue.Field[crate::collections::binary_heap::DrainSorted::inner]", "value", "dfc-generated"] - ["lang:alloc", "::into_iter_sorted", "Argument[self]", "ReturnValue.Field[crate::collections::binary_heap::IntoIterSorted::inner]", "value", "dfc-generated"] - ["lang:alloc", "::peek_mut", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::collections::binary_heap::PeekMut::heap]", "value", "dfc-generated"] - ["lang:alloc", "::as_inner", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::as_into_iter", "Argument[self].Field[crate::collections::binary_heap::IntoIter::iter]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::next", "Argument[self].Field[crate::collections::binary_heap::Iter::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:alloc", "::new", "Argument[0]", "ReturnValue.Field[crate::collections::btree::dedup_sorted_iter::DedupSortedIter::iter].Field[crate::iter::adapters::peekable::Peekable::iter]", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self].Field[crate::collections::btree::map::BTreeMap::alloc].Reference", "ReturnValue.Field[crate::collections::btree::map::BTreeMap::alloc].Field[crate::mem::manually_drop::ManuallyDrop::value]", "value", "dfc-generated"] - ["lang:alloc", "::bulk_build_from_sorted_iter", "Argument[1]", "ReturnValue.Field[crate::collections::btree::map::BTreeMap::alloc].Field[crate::mem::manually_drop::ManuallyDrop::value]", "value", "dfc-generated"] - ["lang:alloc", "::entry", "Argument[0]", "ReturnValue.Field[crate::collections::btree::map::entry::Entry::Vacant(0)].Field[crate::collections::btree::map::entry::VacantEntry::key]", "value", "dfc-generated"] - ["lang:alloc", "::extract_if", "Argument[0]", "ReturnValue.Field[crate::collections::btree::map::ExtractIf::pred]", "value", "dfc-generated"] + - ["lang:alloc", "::extract_if_inner", "Argument[self].Field[crate::collections::btree::map::BTreeMap::alloc].Reference", "ReturnValue.Field[1]", "value", "dfc-generated"] - ["lang:alloc", "::get_or_insert_with", "Argument[0]", "Argument[1].Parameter[0]", "value", "dfc-generated"] + - ["lang:alloc", "::iter", "Argument[self].Field[crate::collections::btree::map::BTreeMap::length]", "ReturnValue.Field[crate::collections::btree::map::Iter::length]", "value", "dfc-generated"] + - ["lang:alloc", "::iter_mut", "Argument[self].Field[crate::collections::btree::map::BTreeMap::length]", "ReturnValue.Field[crate::collections::btree::map::IterMut::length]", "value", "dfc-generated"] + - ["lang:alloc", "::len", "Argument[self].Field[crate::collections::btree::map::BTreeMap::length]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::lower_bound", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::lower_bound_mut", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:alloc", "::new_in", "Argument[0]", "ReturnValue.Field[crate::collections::btree::map::BTreeMap::alloc].Field[crate::mem::manually_drop::ManuallyDrop::value]", "value", "dfc-generated"] + - ["lang:alloc", "::split_off", "Argument[self].Field[crate::collections::btree::map::BTreeMap::alloc].Reference", "ReturnValue.Field[crate::collections::btree::map::BTreeMap::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::split_off", "Argument[self].Field[crate::collections::btree::map::BTreeMap::alloc]", "ReturnValue.Field[crate::collections::btree::map::BTreeMap::alloc].Reference", "value", "dfc-generated"] + - ["lang:alloc", "::split_off", "Argument[self].Field[crate::collections::btree::map::BTreeMap::alloc]", "ReturnValue.Field[crate::collections::btree::map::BTreeMap::alloc]", "value", "dfc-generated"] - ["lang:alloc", "::try_insert", "Argument[1]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::collections::btree::map::entry::OccupiedError::value]", "value", "dfc-generated"] + - ["lang:alloc", "::upper_bound", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::upper_bound_mut", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:alloc", "::clone", "Argument[self].Reference.Field[crate::collections::btree::map::Cursor::current]", "ReturnValue.Field[crate::collections::btree::map::Cursor::current]", "value", "dfc-generated"] - ["lang:alloc", "::clone", "Argument[self].Reference.Field[crate::collections::btree::map::Cursor::root]", "ReturnValue.Field[crate::collections::btree::map::Cursor::root]", "value", "dfc-generated"] + - ["lang:alloc", "::next", "Argument[self].Field[crate::collections::btree::map::Cursor::current].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::next", "Argument[self].Field[crate::collections::btree::map::Cursor::current].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::peek_next", "Argument[self].Field[crate::collections::btree::map::Cursor::current].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::peek_next", "Argument[self].Field[crate::collections::btree::map::Cursor::current].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::peek_prev", "Argument[self].Field[crate::collections::btree::map::Cursor::current].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::peek_prev", "Argument[self].Field[crate::collections::btree::map::Cursor::current].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::prev", "Argument[self].Field[crate::collections::btree::map::Cursor::current].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::prev", "Argument[self].Field[crate::collections::btree::map::Cursor::current].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::with_mutable_key", "Argument[self].Field[crate::collections::btree::map::CursorMut::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::next", "Argument[self].Field[crate::collections::btree::map::CursorMutKey::current].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::next", "Argument[self].Field[crate::collections::btree::map::CursorMutKey::current].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::prev", "Argument[self].Field[crate::collections::btree::map::CursorMutKey::current].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::prev", "Argument[self].Field[crate::collections::btree::map::CursorMutKey::current].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::remove_next", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::remove_prev", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::next", "Argument[self].Field[crate::collections::btree::map::ExtractIfInner::cur_leaf_edge].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::next", "Argument[self].Field[crate::collections::btree::map::ExtractIfInner::cur_leaf_edge].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::btree::map::ExtractIfInner::length].Reference", "ReturnValue.Field[1].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::len", "Argument[self].Field[crate::collections::btree::map::IntoIter::length]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::btree::map::IntoIter::length]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::btree::map::IntoIter::length]", "ReturnValue.Field[1].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::iter", "Argument[self].Field[crate::collections::btree::map::IntoIter::length]", "ReturnValue.Field[crate::collections::btree::map::Iter::length]", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self].Field[crate::collections::btree::map::Iter::length]", "ReturnValue.Field[crate::collections::btree::map::Iter::length]", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self].Field[crate::collections::btree::map::Iter::range].Reference", "ReturnValue.Field[crate::collections::btree::map::Iter::range]", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self].Field[crate::collections::btree::map::Iter::range]", "ReturnValue.Field[crate::collections::btree::map::Iter::range]", "value", "dfc-generated"] + - ["lang:alloc", "::len", "Argument[self].Field[crate::collections::btree::map::Iter::length]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::btree::map::Iter::length]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::btree::map::Iter::length]", "ReturnValue.Field[1].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::len", "Argument[self].Field[crate::collections::btree::map::IterMut::length]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::btree::map::IterMut::length]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::btree::map::IterMut::length]", "ReturnValue.Field[1].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::iter", "Argument[self].Field[crate::collections::btree::map::IterMut::length]", "ReturnValue.Field[crate::collections::btree::map::Iter::length]", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::len", "Argument[self].Field[crate::collections::btree::map::Keys::inner].Field[crate::collections::btree::map::Iter::length]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::btree::map::Keys::inner].Field[crate::collections::btree::map::Iter::length]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::btree::map::Keys::inner].Field[crate::collections::btree::map::Iter::length]", "ReturnValue.Field[1].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self].Field[crate::collections::btree::map::Range::inner].Reference", "ReturnValue.Field[crate::collections::btree::map::Range::inner]", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self].Field[crate::collections::btree::map::Range::inner]", "ReturnValue.Field[crate::collections::btree::map::Range::inner]", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::len", "Argument[self].Field[crate::collections::btree::map::Values::inner].Field[crate::collections::btree::map::Iter::length]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::btree::map::Values::inner].Field[crate::collections::btree::map::Iter::length]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::btree::map::Values::inner].Field[crate::collections::btree::map::Iter::length]", "ReturnValue.Field[1].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::len", "Argument[self].Field[crate::collections::btree::map::ValuesMut::inner].Field[crate::collections::btree::map::IterMut::length]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::btree::map::ValuesMut::inner].Field[crate::collections::btree::map::IterMut::length]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::btree::map::ValuesMut::inner].Field[crate::collections::btree::map::IterMut::length]", "ReturnValue.Field[1].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::and_modify", "Argument[self].Field[crate::collections::btree::map::entry::Entry::Occupied(0)]", "ReturnValue.Field[crate::collections::btree::map::entry::Entry::Occupied(0)]", "value", "dfc-generated"] - ["lang:alloc", "::and_modify", "Argument[self].Field[crate::collections::btree::map::entry::Entry::Vacant(0)]", "ReturnValue.Field[crate::collections::btree::map::entry::Entry::Vacant(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::insert_entry", "Argument[self].Field[crate::collections::btree::map::entry::Entry::Occupied(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::insert_entry", "Argument[self].Field[crate::collections::btree::map::entry::VacantEntry::alloc]", "ReturnValue.Field[crate::collections::btree::map::entry::OccupiedEntry::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::insert_entry", "Argument[self].Field[crate::collections::btree::map::entry::VacantEntry::dormant_map]", "ReturnValue.Field[crate::collections::btree::map::entry::OccupiedEntry::dormant_map]", "value", "dfc-generated"] + - ["lang:alloc", "::into_key", "Argument[self].Field[crate::collections::btree::map::entry::VacantEntry::key]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::key", "Argument[self].Field[crate::collections::btree::map::entry::VacantEntry::key]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:alloc", "::new", "Argument[0]", "ReturnValue.Field[crate::collections::btree::merge_iter::MergeIterInner::a]", "value", "dfc-generated"] - ["lang:alloc", "::new", "Argument[1]", "ReturnValue.Field[crate::collections::btree::merge_iter::MergeIterInner::b]", "value", "dfc-generated"] + - ["lang:alloc", "::nexts", "Argument[self].Field[crate::collections::btree::merge_iter::MergeIterInner::a].Element", "ReturnValue.Field[0].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::nexts", "Argument[self].Field[crate::collections::btree::merge_iter::MergeIterInner::b].Element", "ReturnValue.Field[1].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:alloc", "::clone", "Argument[self].Field[crate::collections::btree::navigate::LazyLeafHandle::Edge(0)].Reference", "ReturnValue.Field[crate::collections::btree::navigate::LazyLeafHandle::Edge(0)]", "value", "dfc-generated"] - ["lang:alloc", "::clone", "Argument[self].Field[crate::collections::btree::navigate::LazyLeafHandle::Root(0)].Reference", "ReturnValue.Field[crate::collections::btree::navigate::LazyLeafHandle::Root(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::into_left_child", "Argument[self].Field[crate::collections::btree::node::BalancingContext::left_child]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::into_right_child", "Argument[self].Field[crate::collections::btree::node::BalancingContext::right_child]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::merge_tracking_child", "Argument[self].Field[crate::collections::btree::node::BalancingContext::left_child]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::merge_tracking_child_edge", "Argument[0].Field[crate::collections::btree::node::LeftOrRight::Left(0)]", "ReturnValue.Field[crate::collections::btree::node::Handle::idx]", "value", "dfc-generated"] - - ["lang:alloc", "::steal_left", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::merge_tracking_child_edge", "Argument[self].Field[crate::collections::btree::node::BalancingContext::left_child]", "ReturnValue.Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] + - ["lang:alloc", "::merge_tracking_parent", "Argument[self].Field[crate::collections::btree::node::BalancingContext::parent].Field[crate::collections::btree::node::Handle::node]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::steal_left", "Argument[self].Field[crate::collections::btree::node::BalancingContext::right_child]", "ReturnValue.Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] - ["lang:alloc", "::steal_right", "Argument[0]", "ReturnValue.Field[crate::collections::btree::node::Handle::idx]", "value", "dfc-generated"] + - ["lang:alloc", "::steal_right", "Argument[self].Field[crate::collections::btree::node::BalancingContext::left_child]", "ReturnValue.Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] - ["lang:alloc", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::awaken", "Argument[self].Field[crate::collections::btree::node::Handle::idx]", "ReturnValue.Field[crate::collections::btree::node::Handle::idx]", "value", "dfc-generated"] + - ["lang:alloc", "::cast_to_leaf_unchecked", "Argument[self].Field[crate::collections::btree::node::Handle::idx]", "ReturnValue.Field[crate::collections::btree::node::Handle::idx]", "value", "dfc-generated"] - ["lang:alloc", "::consider_for_balancing", "Argument[self]", "ReturnValue.Field[crate::collections::btree::node::BalancingContext::parent]", "value", "dfc-generated"] + - ["lang:alloc", "::descend", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::dormant", "Argument[self].Field[crate::collections::btree::node::Handle::idx]", "ReturnValue.Field[crate::collections::btree::node::Handle::idx]", "value", "dfc-generated"] + - ["lang:alloc", "::force", "Argument[self].Field[crate::collections::btree::node::Handle::idx]", "ReturnValue.Field[crate::collections::btree::node::ForceResult::Internal(0)].Field[crate::collections::btree::node::Handle::idx]", "value", "dfc-generated"] + - ["lang:alloc", "::force", "Argument[self].Field[crate::collections::btree::node::Handle::idx]", "ReturnValue.Field[crate::collections::btree::node::ForceResult::Leaf(0)].Field[crate::collections::btree::node::Handle::idx]", "value", "dfc-generated"] + - ["lang:alloc", "::forget_node_type", "Argument[self].Field[crate::collections::btree::node::Handle::idx]", "ReturnValue.Field[crate::collections::btree::node::Handle::idx]", "value", "dfc-generated"] + - ["lang:alloc", "::idx", "Argument[self].Field[crate::collections::btree::node::Handle::idx]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::into_node", "Argument[self].Field[crate::collections::btree::node::Handle::node]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::left_edge", "Argument[self].Field[crate::collections::btree::node::Handle::idx]", "ReturnValue.Field[crate::collections::btree::node::Handle::idx]", "value", "dfc-generated"] + - ["lang:alloc", "::left_edge", "Argument[self].Field[crate::collections::btree::node::Handle::node]", "ReturnValue.Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] + - ["lang:alloc", "::left_kv", "Argument[self].Field[crate::collections::btree::node::Handle::node]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] - ["lang:alloc", "::left_kv", "Argument[self]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:alloc", "::new_edge", "Argument[0]", "ReturnValue.Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] - ["lang:alloc", "::new_edge", "Argument[1]", "ReturnValue.Field[crate::collections::btree::node::Handle::idx]", "value", "dfc-generated"] - ["lang:alloc", "::new_kv", "Argument[0]", "ReturnValue.Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] - ["lang:alloc", "::new_kv", "Argument[1]", "ReturnValue.Field[crate::collections::btree::node::Handle::idx]", "value", "dfc-generated"] + - ["lang:alloc", "::reborrow", "Argument[self].Field[crate::collections::btree::node::Handle::idx]", "ReturnValue.Field[crate::collections::btree::node::Handle::idx]", "value", "dfc-generated"] + - ["lang:alloc", "::reborrow", "Argument[self].Field[crate::collections::btree::node::Handle::node].Field[crate::collections::btree::node::NodeRef::height]", "ReturnValue.Field[crate::collections::btree::node::Handle::node].Field[crate::collections::btree::node::NodeRef::height]", "value", "dfc-generated"] + - ["lang:alloc", "::reborrow", "Argument[self].Field[crate::collections::btree::node::Handle::node].Field[crate::collections::btree::node::NodeRef::node]", "ReturnValue.Field[crate::collections::btree::node::Handle::node].Field[crate::collections::btree::node::NodeRef::node]", "value", "dfc-generated"] + - ["lang:alloc", "::reborrow_mut", "Argument[self].Field[crate::collections::btree::node::Handle::idx]", "ReturnValue.Field[crate::collections::btree::node::Handle::idx]", "value", "dfc-generated"] + - ["lang:alloc", "::right_edge", "Argument[self].Field[crate::collections::btree::node::Handle::node]", "ReturnValue.Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] + - ["lang:alloc", "::right_kv", "Argument[self].Field[crate::collections::btree::node::Handle::idx]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::collections::btree::node::Handle::idx]", "value", "dfc-generated"] + - ["lang:alloc", "::right_kv", "Argument[self].Field[crate::collections::btree::node::Handle::node]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] - ["lang:alloc", "::right_kv", "Argument[self]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::split", "Argument[self].Field[crate::collections::btree::node::Handle::node].Field[crate::collections::btree::node::NodeRef::height]", "ReturnValue.Field[crate::collections::btree::node::SplitResult::right].Field[crate::collections::btree::node::NodeRef::height]", "value", "dfc-generated"] + - ["lang:alloc", "::split", "Argument[self].Field[crate::collections::btree::node::Handle::node]", "ReturnValue.Field[crate::collections::btree::node::SplitResult::left]", "value", "dfc-generated"] - ["lang:alloc", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - - ["lang:alloc", "::ascend", "Argument[self]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::awaken", "Argument[self].Field[crate::collections::btree::node::NodeRef::height]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::height]", "value", "dfc-generated"] + - ["lang:alloc", "::awaken", "Argument[self].Field[crate::collections::btree::node::NodeRef::node]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::node]", "value", "dfc-generated"] + - ["lang:alloc", "::borrow_mut", "Argument[self].Field[crate::collections::btree::node::NodeRef::height]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::height]", "value", "dfc-generated"] + - ["lang:alloc", "::borrow_mut", "Argument[self].Field[crate::collections::btree::node::NodeRef::node]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::node]", "value", "dfc-generated"] + - ["lang:alloc", "::borrow_valmut", "Argument[self].Field[crate::collections::btree::node::NodeRef::height]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::height]", "value", "dfc-generated"] + - ["lang:alloc", "::borrow_valmut", "Argument[self].Field[crate::collections::btree::node::NodeRef::node]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::node]", "value", "dfc-generated"] - ["lang:alloc", "::calc_split_length", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:alloc", "::choose_parent_kv", "Argument[self]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::cast_to_leaf_unchecked", "Argument[self].Field[crate::collections::btree::node::NodeRef::height]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::height]", "value", "dfc-generated"] + - ["lang:alloc", "::cast_to_leaf_unchecked", "Argument[self].Field[crate::collections::btree::node::NodeRef::node]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::node]", "value", "dfc-generated"] + - ["lang:alloc", "::dormant", "Argument[self].Field[crate::collections::btree::node::NodeRef::height]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::height]", "value", "dfc-generated"] + - ["lang:alloc", "::dormant", "Argument[self].Field[crate::collections::btree::node::NodeRef::node]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::node]", "value", "dfc-generated"] - ["lang:alloc", "::find_lower_bound_edge", "Argument[0]", "ReturnValue.Field[1]", "value", "dfc-generated"] - ["lang:alloc", "::find_lower_bound_edge", "Argument[self]", "ReturnValue.Field[0].Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] - ["lang:alloc", "::find_upper_bound_edge", "Argument[0]", "ReturnValue.Field[1]", "value", "dfc-generated"] - ["lang:alloc", "::find_upper_bound_edge", "Argument[self]", "ReturnValue.Field[0].Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] - ["lang:alloc", "::first_edge", "Argument[self]", "ReturnValue.Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] - ["lang:alloc", "::first_kv", "Argument[self]", "ReturnValue.Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] + - ["lang:alloc", "::force", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::forget_type", "Argument[self].Field[crate::collections::btree::node::NodeRef::height]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::height]", "value", "dfc-generated"] + - ["lang:alloc", "::forget_type", "Argument[self].Field[crate::collections::btree::node::NodeRef::node]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::node]", "value", "dfc-generated"] + - ["lang:alloc", "::height", "Argument[self].Field[crate::collections::btree::node::NodeRef::height]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::into_dying", "Argument[self].Field[crate::collections::btree::node::NodeRef::height]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::height]", "value", "dfc-generated"] + - ["lang:alloc", "::into_dying", "Argument[self].Field[crate::collections::btree::node::NodeRef::node]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::node]", "value", "dfc-generated"] - ["lang:alloc", "::last_edge", "Argument[self]", "ReturnValue.Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] - ["lang:alloc", "::last_kv", "Argument[self]", "ReturnValue.Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] + - ["lang:alloc", "::push_internal_level", "Argument[self].Field[crate::collections::btree::node::NodeRef::height]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::height]", "value", "dfc-generated"] + - ["lang:alloc", "::push_internal_level", "Argument[self].Field[crate::collections::btree::node::NodeRef::node]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::node]", "value", "dfc-generated"] + - ["lang:alloc", "::push_with_handle", "Argument[self].Field[crate::collections::btree::node::NodeRef::height]", "ReturnValue.Field[crate::collections::btree::node::Handle::node].Field[crate::collections::btree::node::NodeRef::height]", "value", "dfc-generated"] + - ["lang:alloc", "::push_with_handle", "Argument[self].Field[crate::collections::btree::node::NodeRef::node]", "ReturnValue.Field[crate::collections::btree::node::Handle::node].Field[crate::collections::btree::node::NodeRef::node]", "value", "dfc-generated"] + - ["lang:alloc", "::reborrow", "Argument[self].Field[crate::collections::btree::node::NodeRef::height]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::height]", "value", "dfc-generated"] + - ["lang:alloc", "::reborrow", "Argument[self].Field[crate::collections::btree::node::NodeRef::node]", "ReturnValue.Field[crate::collections::btree::node::NodeRef::node]", "value", "dfc-generated"] - ["lang:alloc", "::search_node", "Argument[self]", "ReturnValue.Field[crate::collections::btree::search::SearchResult::Found(0)].Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] - ["lang:alloc", "::search_node", "Argument[self]", "ReturnValue.Field[crate::collections::btree::search::SearchResult::GoDown(0)].Field[crate::collections::btree::node::Handle::node]", "value", "dfc-generated"] - ["lang:alloc", "::search_tree_for_bifurcation", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]", "value", "dfc-generated"] - ["lang:alloc", "::visit_nodes_in_order", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::forget_node_type", "Argument[self].Field[crate::collections::btree::node::SplitResult::kv]", "ReturnValue.Field[crate::collections::btree::node::SplitResult::kv]", "value", "dfc-generated"] + - ["lang:alloc", "::from_range", "Argument[0].Field[crate::ops::range::Bound::Excluded(0)]", "ReturnValue.Field[crate::collections::btree::search::SearchBound::Excluded(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::from_range", "Argument[0].Field[crate::ops::range::Bound::Included(0)]", "ReturnValue.Field[crate::collections::btree::search::SearchBound::Included(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self].Field[crate::collections::btree::set::BTreeSet::map].Reference", "ReturnValue.Field[crate::collections::btree::set::BTreeSet::map]", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self].Field[crate::collections::btree::set::BTreeSet::map]", "ReturnValue.Field[crate::collections::btree::set::BTreeSet::map]", "value", "dfc-generated"] + - ["lang:alloc", "::clone_from", "Argument[0].Field[crate::collections::btree::set::BTreeSet::map]", "Argument[self].Field[crate::collections::btree::set::BTreeSet::map].Reference", "value", "dfc-generated"] + - ["lang:alloc", "::clone_from", "Argument[0].Field[crate::collections::btree::set::BTreeSet::map]", "Argument[self].Field[crate::collections::btree::set::BTreeSet::map]", "value", "dfc-generated"] - ["lang:alloc", "::difference", "Argument[0]", "ReturnValue.Field[crate::collections::btree::set::Difference::inner].Field[crate::collections::btree::set::DifferenceInner::Search::other_set]", "value", "dfc-generated"] - ["lang:alloc", "::extract_if", "Argument[0]", "ReturnValue.Field[crate::collections::btree::set::ExtractIf::pred]", "value", "dfc-generated"] - - ["lang:alloc", "::get_or_insert_with", "Argument[0]", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:alloc", "::intersection", "Argument[0]", "ReturnValue.Field[crate::collections::btree::set::Intersection::inner].Field[crate::collections::btree::set::IntersectionInner::Search::large_set]", "value", "dfc-generated"] - ["lang:alloc", "::intersection", "Argument[self]", "ReturnValue.Field[crate::collections::btree::set::Intersection::inner].Field[crate::collections::btree::set::IntersectionInner::Search::large_set]", "value", "dfc-generated"] - - ["lang:alloc", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::collections::btree::set::SymmetricDifference(0)]", "value", "dfc-generated"] - - ["lang:alloc", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::collections::btree::set::Union(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::with_mutable_key", "Argument[self].Field[crate::collections::btree::set::CursorMut::inner].Field[crate::collections::btree::map::CursorMut::inner]", "ReturnValue.Field[crate::collections::btree::set::CursorMutKey::inner]", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:alloc", "::insert", "Argument[self].Field[crate::collections::btree::set::entry::Entry::Occupied(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::clone", "Argument[self].Reference.Field[crate::collections::linked_list::Cursor::current]", "ReturnValue.Field[crate::collections::linked_list::Cursor::current]", "value", "dfc-generated"] - ["lang:alloc", "::clone", "Argument[self].Reference.Field[crate::collections::linked_list::Cursor::index]", "ReturnValue.Field[crate::collections::linked_list::Cursor::index]", "value", "dfc-generated"] - ["lang:alloc", "::clone", "Argument[self].Reference.Field[crate::collections::linked_list::Cursor::list]", "ReturnValue.Field[crate::collections::linked_list::Cursor::list]", "value", "dfc-generated"] + - ["lang:alloc", "::as_list", "Argument[self].Field[crate::collections::linked_list::Cursor::list]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::index", "Argument[self].Field[crate::collections::linked_list::Cursor::current].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::index", "Argument[self].Field[crate::collections::linked_list::Cursor::current].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::index", "Argument[self].Field[crate::collections::linked_list::Cursor::index]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::move_next", "Argument[self].Field[crate::collections::linked_list::Cursor::list].Field[crate::collections::linked_list::LinkedList::head]", "Argument[self].Field[crate::collections::linked_list::Cursor::current]", "value", "dfc-generated"] + - ["lang:alloc", "::move_prev", "Argument[self].Field[crate::collections::linked_list::Cursor::list].Field[crate::collections::linked_list::LinkedList::tail]", "Argument[self].Field[crate::collections::linked_list::Cursor::current]", "value", "dfc-generated"] + - ["lang:alloc", "::as_cursor", "Argument[self].Field[crate::collections::linked_list::CursorMut::current]", "ReturnValue.Field[crate::collections::linked_list::Cursor::current]", "value", "dfc-generated"] + - ["lang:alloc", "::as_cursor", "Argument[self].Field[crate::collections::linked_list::CursorMut::index]", "ReturnValue.Field[crate::collections::linked_list::Cursor::index]", "value", "dfc-generated"] + - ["lang:alloc", "::as_cursor", "Argument[self].Field[crate::collections::linked_list::CursorMut::list]", "ReturnValue.Field[crate::collections::linked_list::Cursor::list]", "value", "dfc-generated"] + - ["lang:alloc", "::as_list", "Argument[self].Field[crate::collections::linked_list::CursorMut::list]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::index", "Argument[self].Field[crate::collections::linked_list::CursorMut::current].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::index", "Argument[self].Field[crate::collections::linked_list::CursorMut::current].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::index", "Argument[self].Field[crate::collections::linked_list::CursorMut::index]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::insert_after", "Argument[self].Field[crate::collections::linked_list::CursorMut::list].Field[crate::collections::linked_list::LinkedList::len]", "Argument[self].Field[crate::collections::linked_list::CursorMut::index]", "value", "dfc-generated"] + - ["lang:alloc", "::move_next", "Argument[self].Field[crate::collections::linked_list::CursorMut::list].Field[crate::collections::linked_list::LinkedList::head]", "Argument[self].Field[crate::collections::linked_list::CursorMut::current]", "value", "dfc-generated"] + - ["lang:alloc", "::move_prev", "Argument[self].Field[crate::collections::linked_list::CursorMut::list].Field[crate::collections::linked_list::LinkedList::tail]", "Argument[self].Field[crate::collections::linked_list::CursorMut::current]", "value", "dfc-generated"] + - ["lang:alloc", "::remove_current", "Argument[self].Field[crate::collections::linked_list::CursorMut::current].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::remove_current", "Argument[self].Field[crate::collections::linked_list::CursorMut::current].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::remove_current_as_list", "Argument[self].Field[crate::collections::linked_list::CursorMut::current].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::remove_current_as_list", "Argument[self].Field[crate::collections::linked_list::CursorMut::current].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::remove_current_as_list", "Argument[self].Field[crate::collections::linked_list::CursorMut::list].Field[crate::collections::linked_list::LinkedList::alloc]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::collections::linked_list::LinkedList::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::splice_after", "Argument[self].Field[crate::collections::linked_list::CursorMut::list].Field[crate::collections::linked_list::LinkedList::len]", "Argument[self].Field[crate::collections::linked_list::CursorMut::index]", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::linked_list::IntoIter::list].Field[crate::collections::linked_list::LinkedList::len]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::linked_list::IntoIter::list].Field[crate::collections::linked_list::LinkedList::len]", "ReturnValue.Field[1].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::linked_list::Iter::len]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::linked_list::Iter::len]", "ReturnValue.Field[1].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::linked_list::IterMut::len]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::linked_list::IterMut::len]", "ReturnValue.Field[1].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::spec_extend", "Argument[0]", "Argument[self]", "taint", "df-generated"] + - ["lang:alloc", "::append", "Argument[0].Field[crate::collections::linked_list::LinkedList::tail].Reference", "Argument[self].Field[crate::collections::linked_list::LinkedList::tail]", "value", "dfc-generated"] + - ["lang:alloc", "::append", "Argument[0].Field[crate::collections::linked_list::LinkedList::tail]", "Argument[self].Field[crate::collections::linked_list::LinkedList::tail]", "value", "dfc-generated"] + - ["lang:alloc", "::cursor_back", "Argument[self].Field[crate::collections::linked_list::LinkedList::tail]", "ReturnValue.Field[crate::collections::linked_list::Cursor::current]", "value", "dfc-generated"] - ["lang:alloc", "::cursor_back", "Argument[self]", "ReturnValue.Field[crate::collections::linked_list::Cursor::list]", "value", "dfc-generated"] + - ["lang:alloc", "::cursor_back_mut", "Argument[self].Field[crate::collections::linked_list::LinkedList::tail]", "ReturnValue.Field[crate::collections::linked_list::CursorMut::current]", "value", "dfc-generated"] - ["lang:alloc", "::cursor_back_mut", "Argument[self]", "ReturnValue.Field[crate::collections::linked_list::CursorMut::list]", "value", "dfc-generated"] + - ["lang:alloc", "::cursor_front", "Argument[self].Field[crate::collections::linked_list::LinkedList::head]", "ReturnValue.Field[crate::collections::linked_list::Cursor::current]", "value", "dfc-generated"] - ["lang:alloc", "::cursor_front", "Argument[self]", "ReturnValue.Field[crate::collections::linked_list::Cursor::list]", "value", "dfc-generated"] + - ["lang:alloc", "::cursor_front_mut", "Argument[self].Field[crate::collections::linked_list::LinkedList::head]", "ReturnValue.Field[crate::collections::linked_list::CursorMut::current]", "value", "dfc-generated"] - ["lang:alloc", "::cursor_front_mut", "Argument[self]", "ReturnValue.Field[crate::collections::linked_list::CursorMut::list]", "value", "dfc-generated"] - ["lang:alloc", "::extract_if", "Argument[0]", "ReturnValue.Field[crate::collections::linked_list::ExtractIf::pred]", "value", "dfc-generated"] + - ["lang:alloc", "::extract_if", "Argument[self].Field[crate::collections::linked_list::LinkedList::head]", "ReturnValue.Field[crate::collections::linked_list::ExtractIf::it]", "value", "dfc-generated"] + - ["lang:alloc", "::extract_if", "Argument[self].Field[crate::collections::linked_list::LinkedList::len]", "ReturnValue.Field[crate::collections::linked_list::ExtractIf::old_len]", "value", "dfc-generated"] - ["lang:alloc", "::extract_if", "Argument[self]", "ReturnValue.Field[crate::collections::linked_list::ExtractIf::list]", "value", "dfc-generated"] + - ["lang:alloc", "::iter", "Argument[self].Field[crate::collections::linked_list::LinkedList::head]", "ReturnValue.Field[crate::collections::linked_list::Iter::head]", "value", "dfc-generated"] + - ["lang:alloc", "::iter", "Argument[self].Field[crate::collections::linked_list::LinkedList::len]", "ReturnValue.Field[crate::collections::linked_list::Iter::len]", "value", "dfc-generated"] + - ["lang:alloc", "::iter", "Argument[self].Field[crate::collections::linked_list::LinkedList::tail]", "ReturnValue.Field[crate::collections::linked_list::Iter::tail]", "value", "dfc-generated"] + - ["lang:alloc", "::iter_mut", "Argument[self].Field[crate::collections::linked_list::LinkedList::head]", "ReturnValue.Field[crate::collections::linked_list::IterMut::head]", "value", "dfc-generated"] + - ["lang:alloc", "::iter_mut", "Argument[self].Field[crate::collections::linked_list::LinkedList::len]", "ReturnValue.Field[crate::collections::linked_list::IterMut::len]", "value", "dfc-generated"] + - ["lang:alloc", "::iter_mut", "Argument[self].Field[crate::collections::linked_list::LinkedList::tail]", "ReturnValue.Field[crate::collections::linked_list::IterMut::tail]", "value", "dfc-generated"] + - ["lang:alloc", "::len", "Argument[self].Field[crate::collections::linked_list::LinkedList::len]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::new_in", "Argument[0]", "ReturnValue.Field[crate::collections::linked_list::LinkedList::alloc]", "value", "dfc-generated"] - - ["lang:alloc", "::split_off", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - - ["lang:alloc", "::into_iter", "Argument[self]", "ReturnValue.Field[crate::collections::vec_deque::into_iter::IntoIter::inner]", "value", "dfc-generated"] + - ["lang:alloc", "::split_off", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:alloc", "::drain", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:alloc", "::retain", "Argument[self].Element", "Argument[0].Parameter[0].Reference", "value", "dfc-generated"] + - ["lang:alloc", "::from_contiguous_raw_parts_in", "Argument[1].Field[crate::ops::range::Range::start]", "ReturnValue.Field[crate::collections::vec_deque::VecDeque::head]", "value", "dfc-generated"] + - ["lang:alloc", "::len", "Argument[self].Field[crate::collections::vec_deque::VecDeque::len]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::retain_mut", "Argument[self].Element", "Argument[0].Parameter[0].Reference", "value", "dfc-generated"] + - ["lang:alloc", "::split_off", "Argument[0]", "Argument[self].Field[crate::collections::vec_deque::VecDeque::len]", "value", "dfc-generated"] + - ["lang:alloc", "::truncate", "Argument[0]", "Argument[self].Field[crate::collections::vec_deque::VecDeque::len]", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::vec_deque::drain::Drain::remaining]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:alloc", "::size_hint", "Argument[self].Field[crate::collections::vec_deque::drain::Drain::remaining]", "ReturnValue.Field[1].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::new", "Argument[1]", "Argument[0].Field[crate::collections::vec_deque::VecDeque::len]", "value", "dfc-generated"] - ["lang:alloc", "::new", "Argument[1]", "ReturnValue.Field[crate::collections::vec_deque::drain::Drain::idx]", "value", "dfc-generated"] - ["lang:alloc", "::new", "Argument[2]", "ReturnValue.Field[crate::collections::vec_deque::drain::Drain::drain_len]", "value", "dfc-generated"] - ["lang:alloc", "::new", "Argument[2]", "ReturnValue.Field[crate::collections::vec_deque::drain::Drain::remaining]", "value", "dfc-generated"] + - ["lang:alloc", "::count", "Argument[self].Field[crate::collections::vec_deque::into_iter::IntoIter::inner].Field[crate::collections::vec_deque::VecDeque::len]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::fold", "Argument[0].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::into_vecdeque", "Argument[self].Field[crate::collections::vec_deque::into_iter::IntoIter::inner]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::new", "Argument[0]", "ReturnValue.Field[crate::collections::vec_deque::into_iter::IntoIter::inner]", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:alloc", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::try_rfold", "Argument[0].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::try_rfold", "Argument[0].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::next", "Argument[self].Field[crate::collections::vec_deque::iter::Iter::i1].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:alloc", "::try_fold", "Argument[0].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::try_fold", "Argument[0].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::new", "Argument[0]", "ReturnValue.Field[crate::collections::vec_deque::iter::Iter::i1]", "value", "dfc-generated"] @@ -141,15 +347,21 @@ extensions: - ["lang:alloc", "::try_fold", "Argument[0].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::new", "Argument[0]", "ReturnValue.Field[crate::collections::vec_deque::iter_mut::IterMut::i1]", "value", "dfc-generated"] - ["lang:alloc", "::new", "Argument[1]", "ReturnValue.Field[crate::collections::vec_deque::iter_mut::IterMut::i2]", "value", "dfc-generated"] - - ["lang:alloc", "::into_c_string", "Argument[self].Field[crate::borrow::Cow::Owned(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::borrow", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::as_ref", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:alloc", "::from", "Argument[0].Field[crate::borrow::Cow::Owned(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::index", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::as_bytes_with_nul", "Argument[self].Field[crate::ffi::c_str::CString::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::as_c_str", "Argument[self].Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::from_vec_with_nul", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::ffi::c_str::FromVecWithNulError::bytes]", "value", "dfc-generated"] + - ["lang:alloc", "::as_bytes", "Argument[self].Field[crate::ffi::c_str::FromVecWithNulError::bytes].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::into_bytes", "Argument[self].Field[crate::ffi::c_str::FromVecWithNulError::bytes]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::source", "Argument[self].Field[crate::ffi::c_str::IntoStringError::error]", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:alloc", "::into_cstring", "Argument[self].Field[crate::ffi::c_str::IntoStringError::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::utf8_error", "Argument[self].Field[crate::ffi::c_str::IntoStringError::error]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::into_vec", "Argument[self].Field[1]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::into_vec", "Argument[self].Field[crate::ffi::c_str::NulError(1)]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::nul_position", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::nul_position", "Argument[self].Field[crate::ffi::c_str::NulError(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::spec_to_string", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:alloc", "::from", "Argument[0]", "ReturnValue.Field[crate::pin::Pin::__pointer]", "value", "dfc-generated"] - ["lang:alloc", "::from_nonnull_in", "Argument[2]", "ReturnValue.Field[crate::raw_vec::RawVec::inner].Field[crate::raw_vec::RawVecInner::alloc]", "value", "dfc-generated"] @@ -160,8 +372,11 @@ extensions: - ["lang:alloc", "::borrow", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::as_ref", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::try_from", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::allocator", "Argument[0].Field[crate::rc::Rc::alloc]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::downcast", "Argument[self]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - - ["lang:alloc", "::from_raw_in", "Argument[1]", "ReturnValue.Field[crate::rc::Rc::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::downgrade", "Argument[0].Field[crate::rc::Rc::alloc].Reference", "ReturnValue.Field[crate::rc::Weak::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::downgrade", "Argument[0].Field[crate::rc::Rc::alloc]", "ReturnValue.Field[crate::rc::Weak::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::downgrade", "Argument[0].Field[crate::rc::Rc::ptr]", "ReturnValue.Field[crate::rc::Weak::ptr]", "value", "dfc-generated"] - ["lang:alloc", "::new_uninit_in", "Argument[0]", "ReturnValue.Field[crate::rc::Rc::alloc]", "value", "dfc-generated"] - ["lang:alloc", "::new_uninit_slice_in", "Argument[1]", "ReturnValue.Field[crate::rc::Rc::alloc]", "value", "dfc-generated"] - ["lang:alloc", "::new_zeroed_in", "Argument[0]", "ReturnValue.Field[crate::rc::Rc::alloc]", "value", "dfc-generated"] @@ -169,42 +384,54 @@ extensions: - ["lang:alloc", "::try_new_uninit_in", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::rc::Rc::alloc]", "value", "dfc-generated"] - ["lang:alloc", "::try_new_zeroed_in", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::rc::Rc::alloc]", "value", "dfc-generated"] - ["lang:alloc", "::try_unwrap", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::unwrap_or_clone", "Argument[0].Reference.Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::unwrap_or_clone", "Argument[0].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::strong_ref", "Argument[self].Field[crate::rc::RcInner::strong]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::weak_ref", "Argument[self].Field[crate::rc::RcInner::weak]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::borrow", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::borrow_mut", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::as_mut", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::as_ref", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - - ["lang:alloc", "::from_raw", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::downgrade", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::allocator", "Argument[self].Field[crate::rc::Weak::alloc]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::from_raw_in", "Argument[1]", "ReturnValue.Field[crate::rc::Weak::alloc]", "value", "dfc-generated"] - ["lang:alloc", "::new_in", "Argument[0]", "ReturnValue.Field[crate::rc::Weak::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::upgrade", "Argument[self].Field[crate::rc::Weak::alloc].Reference", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::rc::Rc::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::upgrade", "Argument[self].Field[crate::rc::Weak::alloc]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::rc::Rc::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::upgrade", "Argument[self].Field[crate::rc::Weak::ptr]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::rc::Rc::ptr]", "value", "dfc-generated"] + - ["lang:alloc", "::strong_ref", "Argument[self].Field[crate::rc::WeakInner::strong]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::weak_ref", "Argument[self].Field[crate::rc::WeakInner::weak]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::as_bytes", "Argument[self].Field[crate::string::FromUtf8Error::bytes].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::into_bytes", "Argument[self].Field[crate::string::FromUtf8Error::bytes]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::utf8_error", "Argument[self].Field[crate::string::FromUtf8Error::error]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::into_string", "Argument[self].Field[crate::string::IntoChars::bytes].Element", "ReturnValue.Field[crate::string::String::vec].Element", "value", "dfc-generated"] - ["lang:alloc", "::borrow", "Argument[self].Element", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::borrow_mut", "Argument[self].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self].Field[crate::string::String::vec].Reference", "ReturnValue.Field[crate::string::String::vec]", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self].Field[crate::string::String::vec]", "ReturnValue.Field[crate::string::String::vec]", "value", "dfc-generated"] - ["lang:alloc", "::as_mut", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:alloc", "::as_ref", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:alloc", "::as_ref", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:alloc", "::from", "Argument[0].Field[crate::borrow::Cow::Owned(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::from", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:alloc", "::from", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:alloc", "::try_from", "Argument[0].Field[0]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::string::FromUtf8Error::bytes]", "value", "dfc-generated"] - - ["lang:alloc", "::try_from", "Argument[0].Field[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::string::String::vec]", "value", "dfc-generated"] - - ["lang:alloc", "::try_from", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::string::FromUtf8Error::bytes]", "value", "dfc-generated"] - - ["lang:alloc", "::try_from", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::string::String::vec]", "value", "dfc-generated"] + - ["lang:alloc", "::try_from", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:alloc", "::add", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:alloc", "::deref", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:alloc", "::from_str", "Argument[0].Field[crate::borrow::Cow::Owned(0)]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] - - ["lang:alloc", "::from_str", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] - - ["lang:alloc", "::spec_to_string", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::deref", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::from_str", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::as_mut_vec", "Argument[self].Field[crate::string::String::vec]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::drain", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:alloc", "::from_raw_parts", "Argument[1]", "ReturnValue.Field[crate::string::String::vec].Field[crate::vec::Vec::len]", "value", "dfc-generated"] - ["lang:alloc", "::from_utf8", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::string::FromUtf8Error::bytes]", "value", "dfc-generated"] - ["lang:alloc", "::from_utf8", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::string::String::vec]", "value", "dfc-generated"] - ["lang:alloc", "::from_utf8_lossy_owned", "Argument[0]", "ReturnValue.Field[crate::string::String::vec]", "value", "dfc-generated"] - ["lang:alloc", "::from_utf8_unchecked", "Argument[0]", "ReturnValue.Field[crate::string::String::vec]", "value", "dfc-generated"] + - ["lang:alloc", "::into_bytes", "Argument[self].Field[crate::string::String::vec]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::borrow", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::as_ref", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::try_from", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::allocator", "Argument[0].Field[crate::sync::Arc::alloc]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::downcast", "Argument[self]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - - ["lang:alloc", "::from_raw_in", "Argument[1]", "ReturnValue.Field[crate::sync::Arc::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::downgrade", "Argument[0].Field[crate::sync::Arc::alloc].Reference", "ReturnValue.Field[crate::sync::Weak::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::downgrade", "Argument[0].Field[crate::sync::Arc::alloc]", "ReturnValue.Field[crate::sync::Weak::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::downgrade", "Argument[0].Field[crate::sync::Arc::ptr]", "ReturnValue.Field[crate::sync::Weak::ptr]", "value", "dfc-generated"] - ["lang:alloc", "::new_uninit_in", "Argument[0]", "ReturnValue.Field[crate::sync::Arc::alloc]", "value", "dfc-generated"] - ["lang:alloc", "::new_uninit_slice_in", "Argument[1]", "ReturnValue.Field[crate::sync::Arc::alloc]", "value", "dfc-generated"] - ["lang:alloc", "::new_zeroed_in", "Argument[0]", "ReturnValue.Field[crate::sync::Arc::alloc]", "value", "dfc-generated"] @@ -212,40 +439,55 @@ extensions: - ["lang:alloc", "::try_new_uninit_in", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::sync::Arc::alloc]", "value", "dfc-generated"] - ["lang:alloc", "::try_new_zeroed_in", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::sync::Arc::alloc]", "value", "dfc-generated"] - ["lang:alloc", "::try_unwrap", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:alloc", "::unwrap_or_clone", "Argument[0].Reference.Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::unwrap_or_clone", "Argument[0].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::allocator", "Argument[self].Field[crate::sync::Weak::alloc]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::from_raw", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:alloc", "::from_raw_in", "Argument[1]", "ReturnValue.Field[crate::sync::Weak::alloc]", "value", "dfc-generated"] - ["lang:alloc", "::new_in", "Argument[0]", "ReturnValue.Field[crate::sync::Weak::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::upgrade", "Argument[self].Field[crate::sync::Weak::alloc].Reference", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::sync::Arc::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::upgrade", "Argument[self].Field[crate::sync::Weak::alloc]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::sync::Arc::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::upgrade", "Argument[self].Field[crate::sync::Weak::ptr]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::sync::Arc::ptr]", "value", "dfc-generated"] - ["lang:alloc", "::borrow", "Argument[self].Element", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::borrow_mut", "Argument[self].Element", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:alloc", "::as_mut", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::as_ref", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::from", "Argument[0].Field[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:alloc", "::from", "Argument[0].Field[crate::borrow::Cow::Owned(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:alloc", "::drain", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::from", "Argument[0].Field[crate::bstr::ByteString(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::from", "Argument[0].Field[crate::collections::binary_heap::BinaryHeap::data]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::from", "Argument[0].Field[crate::string::String::vec]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::extract_if", "Argument[1]", "ReturnValue.Field[crate::vec::extract_if::ExtractIf::pred]", "value", "dfc-generated"] - ["lang:alloc", "::extract_if", "Argument[self]", "ReturnValue.Field[crate::vec::extract_if::ExtractIf::vec]", "value", "dfc-generated"] - - ["lang:alloc", "::from_parts", "Argument[1]", "ReturnValue.Field[crate::vec::Vec::len]", "value", "dfc-generated"] - ["lang:alloc", "::from_parts_in", "Argument[1]", "ReturnValue.Field[crate::vec::Vec::len]", "value", "dfc-generated"] - - ["lang:alloc", "::from_raw_parts", "Argument[1]", "ReturnValue.Field[crate::vec::Vec::len]", "value", "dfc-generated"] - ["lang:alloc", "::from_raw_parts_in", "Argument[1]", "ReturnValue.Field[crate::vec::Vec::len]", "value", "dfc-generated"] + - ["lang:alloc", "::len", "Argument[self].Field[crate::vec::Vec::len]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::push_within_capacity", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - - ["lang:alloc", "::try_with_capacity_in", "Argument[1]", "ReturnValue.Field[crate::raw_vec::RawVec::inner].Field[crate::raw_vec::RawVecInner::alloc]", "value", "dfc-generated"] + - ["lang:alloc", "::set_len", "Argument[0]", "Argument[self].Field[crate::vec::Vec::len]", "value", "dfc-generated"] + - ["lang:alloc", "::truncate", "Argument[0]", "Argument[self].Field[crate::vec::Vec::len]", "value", "dfc-generated"] + - ["lang:alloc", "::next", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::size_hint", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:alloc", "::new", "Argument[0]", "ReturnValue.Field[crate::vec::extract_if::ExtractIf::vec]", "value", "dfc-generated"] - ["lang:alloc", "::new", "Argument[1]", "ReturnValue.Field[crate::vec::extract_if::ExtractIf::pred]", "value", "dfc-generated"] - ["lang:alloc", "::as_inner", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::next_back", "Argument[self].Field[crate::vec::into_iter::IntoIter::end].Reference", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:alloc", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::fold", "Argument[1].ReturnValue", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:alloc", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::try_fold", "Argument[1]", "ReturnValue", "taint", "df-generated"] - ["lang:alloc", "::as_into_iter", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:alloc", "::allocator", "Argument[self].Field[crate::vec::into_iter::IntoIter::alloc]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::forget_allocation_drop_remaining", "Argument[self].Field[crate::vec::into_iter::IntoIter::buf]", "Argument[self].Field[crate::vec::into_iter::IntoIter::ptr]", "value", "dfc-generated"] + - ["lang:alloc", "::drop", "Argument[self].Field[crate::vec::set_len_on_drop::SetLenOnDrop::local_len]", "Argument[self].Field[crate::vec::set_len_on_drop::SetLenOnDrop::len].Reference", "value", "dfc-generated"] + - ["lang:alloc", "::current_len", "Argument[self].Field[crate::vec::set_len_on_drop::SetLenOnDrop::local_len]", "ReturnValue", "value", "dfc-generated"] - ["lang:alloc", "::new", "Argument[0].Reference", "ReturnValue.Field[crate::vec::set_len_on_drop::SetLenOnDrop::local_len]", "value", "dfc-generated"] - ["lang:alloc", "::new", "Argument[0]", "ReturnValue.Field[crate::vec::set_len_on_drop::SetLenOnDrop::len]", "value", "dfc-generated"] - ["lang:alloc", "::downcast", "Argument[self]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - - ["lang:alloc", "::spec_to_string", "Argument[self].Field[crate::borrow::Cow::Owned(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:alloc", "::spec_to_string", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:alloc", "<{766}::StringError as crate::error::Error>::description", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:alloc", "::from_elem", "Argument[1]", "ReturnValue.Field[crate::vec::Vec::len]", "value", "dfc-generated"] + - ["lang:alloc", "::spec_to_string", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:alloc", "::from_elem", "Argument[1]", "ReturnValue.Field[crate::vec::Vec::len]", "value", "dfc-generated"] - ["lang:alloc", "crate::collections::btree::mem::replace", "Argument[0].Reference", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:alloc", "crate::collections::btree::mem::replace", "Argument[1].ReturnValue", "Argument[0].Reference", "value", "dfc-generated"] - ["lang:alloc", "crate::collections::btree::mem::take_mut", "Argument[0].Reference", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:alloc", "crate::collections::btree::mem::take_mut", "Argument[1].ReturnValue", "Argument[0].Reference", "value", "dfc-generated"] + - ["lang:alloc", "crate::str::convert_while_ascii", "Argument[0]", "Argument[1]", "taint", "df-generated"] diff --git a/rust/ql/lib/ext/generated/rust/lang-core.model.yml b/rust/ql/lib/ext/generated/rust/lang-core.model.yml index 0bb74f5e412d..734b13027cd8 100644 --- a/rust/ql/lib/ext/generated/rust/lang-core.model.yml +++ b/rust/ql/lib/ext/generated/rust/lang-core.model.yml @@ -7,202 +7,13 @@ extensions: - ["lang:core", "<&_ as crate::borrow::Borrow>::borrow", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "<&_ as crate::clone::Clone>::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<&_ as crate::ops::deref::Deref>::deref", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "<&bool as crate::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&bool as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&bool as crate::ops::bit::BitOr>::bitor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&bool as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&bool as crate::ops::bit::BitXor>::bitxor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&bool as crate::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&bool as crate::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "<&crate::net::ip_addr::Ipv4Addr as crate::ops::bit::BitAnd>::bitand", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "<&crate::net::ip_addr::Ipv4Addr as crate::ops::bit::BitOr>::bitor", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<&crate::net::ip_addr::Ipv4Addr as crate::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "<&crate::net::ip_addr::Ipv6Addr as crate::ops::bit::BitAnd>::bitand", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "<&crate::net::ip_addr::Ipv6Addr as crate::ops::bit::BitOr>::bitor", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<&crate::net::ip_addr::Ipv6Addr as crate::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&crate::num::saturating::Saturating as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&crate::num::saturating::Saturating as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&crate::num::saturating::Saturating as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&crate::num::saturating::Saturating as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&crate::num::saturating::Saturating as crate::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&crate::num::wrapping::Wrapping as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&crate::num::wrapping::Wrapping as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&crate::num::wrapping::Wrapping as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&crate::num::wrapping::Wrapping as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&crate::num::wrapping::Wrapping as crate::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "<&crate::result::Result as crate::iter::traits::collect::IntoIterator>::into_iter", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f128 as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f128 as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f128 as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f128 as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f128 as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f128 as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f128 as crate::ops::arith::Neg>::neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f128 as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f128 as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f128 as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f128 as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f16 as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f16 as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f16 as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f16 as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f16 as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f16 as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f16 as crate::ops::arith::Neg>::neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f16 as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f16 as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f16 as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f16 as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f32 as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f32 as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f32 as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f32 as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f32 as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f32 as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f32 as crate::ops::arith::Neg>::neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f32 as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f32 as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f32 as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f32 as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f64 as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f64 as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f64 as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f64 as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f64 as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f64 as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f64 as crate::ops::arith::Neg>::neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f64 as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f64 as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f64 as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&f64 as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::arith::Neg>::neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::bit::BitOr>::bitor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::bit::BitXor>::bitxor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::bit::Shl>::shl", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::bit::Shl>::shl", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::bit::Shr>::shr", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i128 as crate::ops::bit::Shr>::shr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::arith::Neg>::neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::bit::BitOr>::bitor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::bit::BitXor>::bitxor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::bit::Shl>::shl", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::bit::Shl>::shl", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::bit::Shr>::shr", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i16 as crate::ops::bit::Shr>::shr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::arith::Neg>::neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::bit::BitOr>::bitor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::bit::BitXor>::bitxor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::bit::Shl>::shl", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::bit::Shl>::shl", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::bit::Shr>::shr", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i32 as crate::ops::bit::Shr>::shr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::arith::Neg>::neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::bit::BitOr>::bitor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::bit::BitXor>::bitxor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::bit::Shl>::shl", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::bit::Shl>::shl", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::bit::Shr>::shr", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i64 as crate::ops::bit::Shr>::shr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::arith::Neg>::neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::bit::BitOr>::bitor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::bit::BitXor>::bitxor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::bit::Shl>::shl", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::bit::Shl>::shl", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::bit::Shr>::shr", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&i8 as crate::ops::bit::Shr>::shr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::arith::Neg>::neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::bit::BitOr>::bitor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::bit::BitXor>::bitxor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::bit::Shl>::shl", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::bit::Shl>::shl", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::bit::Shr>::shr", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&isize as crate::ops::bit::Shr>::shr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "<&mut _ as crate::borrow::Borrow>::borrow", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "<&mut _ as crate::borrow::BorrowMut>::borrow_mut", "Argument[self].Reference.Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "<&mut _ as crate::iter::traits::double_ended::DoubleEndedIterator>::advance_back_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -210,8 +21,6 @@ extensions: - ["lang:core", "<&mut _ as crate::iter::traits::double_ended::DoubleEndedIteratorRefSpec>::spec_rfold", "Argument[1].ReturnValue", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "<&mut _ as crate::iter::traits::double_ended::DoubleEndedIteratorRefSpec>::spec_rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<&mut _ as crate::iter::traits::double_ended::DoubleEndedIteratorRefSpec>::spec_try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "<&mut _ as crate::iter::traits::double_ended::DoubleEndedIteratorRefSpec>::spec_try_rfold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "<&mut _ as crate::iter::traits::double_ended::DoubleEndedIteratorRefSpec>::spec_try_rfold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<&mut _ as crate::iter::traits::iterator::Iterator>::advance_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "<&mut _ as crate::iter::traits::iterator::Iterator>::next", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "<&mut _ as crate::iter::traits::iterator::Iterator>::nth", "Argument[self]", "ReturnValue", "taint", "df-generated"] @@ -219,152 +28,19 @@ extensions: - ["lang:core", "<&mut _ as crate::iter::traits::iterator::IteratorRefSpec>::spec_fold", "Argument[1].ReturnValue", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "<&mut _ as crate::iter::traits::iterator::IteratorRefSpec>::spec_fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<&mut _ as crate::iter::traits::iterator::IteratorRefSpec>::spec_try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "<&mut _ as crate::iter::traits::iterator::IteratorRefSpec>::spec_try_fold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "<&mut _ as crate::iter::traits::iterator::IteratorRefSpec>::spec_try_fold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<&mut _ as crate::ops::deref::Deref>::deref", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<&mut _ as crate::ops::deref::DerefMut>::deref_mut", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<&mut crate::result::Result as crate::iter::traits::collect::IntoIterator>::into_iter", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "<&str as crate::str::pattern::Pattern>::as_utf8_pattern", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "<&str as crate::str::pattern::Pattern>::into_searcher", "Argument[0]", "ReturnValue.Field[crate::str::pattern::StrSearcher::haystack]", "value", "dfc-generated"] - ["lang:core", "<&str as crate::str::pattern::Pattern>::into_searcher", "Argument[self]", "ReturnValue.Field[crate::str::pattern::StrSearcher::needle]", "value", "dfc-generated"] - - ["lang:core", "<&u128 as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::bit::BitOr>::bitor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::bit::BitXor>::bitxor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::bit::Shl>::shl", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::bit::Shl>::shl", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::bit::Shr>::shr", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u128 as crate::ops::bit::Shr>::shr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::bit::BitOr>::bitor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::bit::BitXor>::bitxor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::bit::Shl>::shl", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::bit::Shl>::shl", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::bit::Shr>::shr", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u16 as crate::ops::bit::Shr>::shr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::bit::BitOr>::bitor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::bit::BitXor>::bitxor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::bit::Shl>::shl", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::bit::Shl>::shl", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::bit::Shr>::shr", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u32 as crate::ops::bit::Shr>::shr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::bit::BitOr>::bitor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::bit::BitXor>::bitxor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::bit::Shl>::shl", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::bit::Shl>::shl", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::bit::Shr>::shr", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u64 as crate::ops::bit::Shr>::shr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::bit::BitOr>::bitor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::bit::BitXor>::bitxor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::bit::Shl>::shl", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::bit::Shl>::shl", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::bit::Shr>::shr", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&u8 as crate::ops::bit::Shr>::shr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::arith::Add>::add", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::arith::Add>::add", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::arith::Div>::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::arith::Div>::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::arith::Mul>::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::arith::Mul>::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::arith::Rem>::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::arith::Rem>::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::arith::Sub>::sub", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::bit::BitOr>::bitor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::bit::BitXor>::bitxor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::bit::BitXor>::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::bit::Not>::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::bit::Shl>::shl", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::bit::Shl>::shl", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::bit::Shr>::shr", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<&usize as crate::ops::bit::Shr>::shr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "<[_] as crate::convert::AsMut>::as_mut", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<[_] as crate::convert::AsRef>::as_ref", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "<[_] as crate::slice::CloneFromSpec>::spec_clone_from", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "<[_] as crate::slice::SlicePattern>::as_slice", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<[_]>::align_to", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "<[_]>::align_to_mut", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - - ["lang:core", "<[_]>::array_windows", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<[_]>::as_array", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<[_]>::as_mut_array", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "<[_]>::as_mut_ptr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "<[_]>::as_ptr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<[_]>::as_simd", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - - ["lang:core", "<[_]>::as_simd_mut", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "<[_]>::chunk_by", "Argument[0]", "ReturnValue.Field[crate::slice::iter::ChunkBy::predicate]", "value", "dfc-generated"] - ["lang:core", "<[_]>::chunk_by", "Argument[self]", "ReturnValue.Field[crate::slice::iter::ChunkBy::slice]", "value", "dfc-generated"] - ["lang:core", "<[_]>::chunk_by_mut", "Argument[0]", "ReturnValue.Field[crate::slice::iter::ChunkByMut::predicate]", "value", "dfc-generated"] @@ -375,10 +51,7 @@ extensions: - ["lang:core", "<[_]>::chunks_exact_mut", "Argument[0]", "ReturnValue.Field[crate::slice::iter::ChunksExactMut::chunk_size]", "value", "dfc-generated"] - ["lang:core", "<[_]>::chunks_mut", "Argument[0]", "ReturnValue.Field[crate::slice::iter::ChunksMut::chunk_size]", "value", "dfc-generated"] - ["lang:core", "<[_]>::chunks_mut", "Argument[self]", "ReturnValue.Field[crate::slice::iter::ChunksMut::v]", "value", "dfc-generated"] - - ["lang:core", "<[_]>::clone_from_slice", "Argument[0]", "Argument[self]", "taint", "df-generated"] - - ["lang:core", "<[_]>::partition_dedup", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "<[_]>::partition_dedup_by", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - - ["lang:core", "<[_]>::partition_dedup_by_key", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "<[_]>::rchunks", "Argument[0]", "ReturnValue.Field[crate::slice::iter::RChunks::chunk_size]", "value", "dfc-generated"] - ["lang:core", "<[_]>::rchunks", "Argument[self]", "ReturnValue.Field[crate::slice::iter::RChunks::v]", "value", "dfc-generated"] - ["lang:core", "<[_]>::rchunks_exact", "Argument[0]", "ReturnValue.Field[crate::slice::iter::RChunksExact::chunk_size]", "value", "dfc-generated"] @@ -407,11 +80,8 @@ extensions: - ["lang:core", "<[crate::ascii::ascii_char::AsciiChar]>::as_str", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "<[crate::mem::maybe_uninit::MaybeUninit]>::assume_init_mut", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "<[crate::mem::maybe_uninit::MaybeUninit]>::assume_init_ref", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<[crate::mem::maybe_uninit::MaybeUninit]>::write_clone_of_slice", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<[crate::mem::maybe_uninit::MaybeUninit]>::write_copy_of_slice", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<[u8]>::as_ascii", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "<[u8] as crate::num::dec2flt::common::ByteSlice>::parse_digits", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<[u8]>::as_ascii_unchecked", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<[u8]>::trim_ascii", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<[u8]>::trim_ascii_end", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<[u8]>::trim_ascii_start", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<[u8]>::utf8_chunks", "Argument[self]", "ReturnValue.Field[crate::str::lossy::Utf8Chunks::source]", "value", "dfc-generated"] @@ -419,20 +89,16 @@ extensions: - ["lang:core", "<_ as crate::async_iter::async_iter::IntoAsyncIterator>::into_async_iter", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<_ as crate::borrow::Borrow>::borrow", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<_ as crate::borrow::BorrowMut>::borrow_mut", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "<_ as crate::clone::uninit::CopySpec>::clone_one", "Argument[0].Reference", "Argument[1].Reference", "value", "dfc-generated"] - ["lang:core", "<_ as crate::clone::uninit::CopySpec>::clone_one", "Argument[0]", "Argument[1].Reference", "value", "dfc-generated"] - ["lang:core", "<_ as crate::convert::From>::from", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<_ as crate::future::into_future::IntoFuture>::into_future", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<_ as crate::iter::adapters::step_by::SpecRangeSetup>::setup", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<_ as crate::iter::traits::collect::IntoIterator>::into_iter", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "<_ as crate::ops::bit::BitOr>::bitor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "<_ as crate::slice::sort::shared::smallsort::StableSmallSortTypeImpl>::small_sort", "Argument[0]", "Argument[2]", "taint", "df-generated"] - - ["lang:core", "<_ as crate::slice::sort::shared::smallsort::UnstableSmallSortFreezeTypeImpl>::small_sort", "Argument[0]", "Argument[1]", "taint", "df-generated"] - ["lang:core", "<_ as crate::str::pattern::MultiCharEq>::matches", "Argument[0]", "Argument[self].Reference.Parameter[0]", "value", "dfc-generated"] - ["lang:core", "<_ as crate::str::pattern::MultiCharEq>::matches", "Argument[self].Reference.ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::clamp", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::clamp", "Argument[1]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::clamp", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::max", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::max", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::min", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -455,121 +121,212 @@ extensions: - ["lang:core", "::as_utf8_pattern", "Argument[self].Reference", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::str::pattern::Utf8Pattern::CharPattern(0)]", "value", "dfc-generated"] - ["lang:core", "::into_searcher", "Argument[0]", "ReturnValue.Field[crate::str::pattern::CharSearcher::haystack]", "value", "dfc-generated"] - ["lang:core", "::into_searcher", "Argument[self]", "ReturnValue.Field[crate::str::pattern::CharSearcher::needle]", "value", "dfc-generated"] - - ["lang:core", "::escape_debug", "Argument[self]", "ReturnValue.Field[crate::char::EscapeDebug(0)].Field[crate::char::EscapeDebugInner::Char(0)]", "value", "dfc-generated"] - - ["lang:core", "::escape_debug_ext", "Argument[self]", "ReturnValue.Field[crate::char::EscapeDebug(0)].Field[crate::char::EscapeDebugInner::Char(0)]", "value", "dfc-generated"] - ["lang:core", "::from_digit", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::to_ascii_lowercase", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::to_ascii_uppercase", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::align", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::align_to", "Argument[self].Field[crate::alloc::layout::Layout::align]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::alloc::layout::Layout::align]", "value", "dfc-generated"] + - ["lang:core", "::align_to", "Argument[self].Field[crate::alloc::layout::Layout::size]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::alloc::layout::Layout::size]", "value", "dfc-generated"] + - ["lang:core", "::extend_packed", "Argument[self].Field[crate::alloc::layout::Layout::align]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::alloc::layout::Layout::align]", "value", "dfc-generated"] - ["lang:core", "::from_size_align", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::alloc::layout::Layout::size]", "value", "dfc-generated"] - ["lang:core", "::from_size_align_unchecked", "Argument[0]", "ReturnValue.Field[crate::alloc::layout::Layout::size]", "value", "dfc-generated"] + - ["lang:core", "::repeat", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::repeat_packed", "Argument[self].Field[crate::alloc::layout::Layout::align]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::alloc::layout::Layout::align]", "value", "dfc-generated"] + - ["lang:core", "::size", "Argument[self].Field[crate::alloc::layout::Layout::size]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new_unchecked", "Argument[0]", "ReturnValue.Field[crate::array::iter::IntoIter::data]", "value", "dfc-generated"] - - ["lang:core", "::steps_between", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::steps_between", "Argument[1]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::new_unchecked", "Argument[1].Field[crate::ops::range::Range::end]", "ReturnValue.Field[crate::array::iter::IntoIter::alive].Field[crate::ops::index_range::IndexRange::end]", "value", "dfc-generated"] + - ["lang:core", "::new_unchecked", "Argument[1].Field[crate::ops::range::Range::start]", "ReturnValue.Field[crate::array::iter::IntoIter::alive].Field[crate::ops::index_range::IndexRange::start]", "value", "dfc-generated"] - ["lang:core", "::to_char", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::to_u8", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::try_capture", "Argument[self].Field[0].Reference", "Argument[0].Field[crate::asserting::Capture::elem].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::try_capture", "Argument[self].Field[crate::asserting::Wrapper(0)].Reference", "Argument[0].Field[crate::asserting::Capture::elem].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::borrow", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::borrow", "Argument[self].Field[crate::bstr::ByteStr(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::borrow_mut", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::borrow_mut", "Argument[self].Field[crate::bstr::ByteStr(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::as_mut", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::as_mut", "Argument[self].Field[crate::bstr::ByteStr(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::as_ref", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::as_ref", "Argument[self].Field[crate::bstr::ByteStr(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::as_ref", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::deref", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::deref", "Argument[self].Field[crate::bstr::ByteStr(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::deref_mut", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::deref_mut", "Argument[self].Field[crate::bstr::ByteStr(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::index", "Argument[self].Field[0].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::index", "Argument[self].Field[crate::bstr::ByteStr(0)].Element", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::index", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::index_mut", "Argument[self].Field[0].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::index_mut", "Argument[self].Field[crate::bstr::ByteStr(0)].Element", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::index_mut", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::as_bytes", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::as_bytes", "Argument[self].Field[crate::bstr::ByteStr(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::from_bytes", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_bytes_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::cell::BorrowRef::borrow]", "ReturnValue.Field[crate::cell::BorrowRef::borrow]", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::cell::Cell::value].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::as_array_of_cells", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::as_slice_of_cells", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::cell::Cell::value].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::cell::Cell::value].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::update", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::filter_map", "Argument[0].Field[crate::cell::Ref::borrow]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::cell::Ref::borrow]", "value", "dfc-generated"] - ["lang:core", "::filter_map", "Argument[0].Reference", "Argument[1].Parameter[0].Reference", "value", "dfc-generated"] - ["lang:core", "::filter_map", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:core", "::map", "Argument[0].Field[crate::cell::Ref::borrow]", "ReturnValue.Field[crate::cell::Ref::borrow]", "value", "dfc-generated"] - ["lang:core", "::map", "Argument[0].Reference", "Argument[1].Parameter[0].Reference", "value", "dfc-generated"] - - ["lang:core", "::map_split", "Argument[0].Reference", "Argument[1].Parameter[0].Reference", "value", "dfc-generated"] + - ["lang:core", "::map_split", "Argument[0]", "Argument[1]", "taint", "df-generated"] + - ["lang:core", "::map_split", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::cell::RefCell::value].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::cell::RefCell::value].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::cell::RefCell::value].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] + - ["lang:core", "::filter_map", "Argument[0].Field[crate::cell::RefMut::borrow]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::cell::RefMut::borrow]", "value", "dfc-generated"] - ["lang:core", "::filter_map", "Argument[0].Reference", "Argument[1].Parameter[0].Reference", "value", "dfc-generated"] - ["lang:core", "::filter_map", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:core", "::map", "Argument[0].Field[crate::cell::RefMut::borrow]", "ReturnValue.Field[crate::cell::RefMut::borrow]", "value", "dfc-generated"] - ["lang:core", "::map", "Argument[0].Reference", "Argument[1].Parameter[0].Reference", "value", "dfc-generated"] - - ["lang:core", "::map_split", "Argument[0].Reference", "Argument[1].Parameter[0].Reference", "value", "dfc-generated"] + - ["lang:core", "::map_split", "Argument[0]", "Argument[1]", "taint", "df-generated"] + - ["lang:core", "::map_split", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::cell::SyncUnsafeCell::value].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::cell::SyncUnsafeCell::value].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::cell::SyncUnsafeCell::value].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::raw_get", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::get_mut", "Argument[self].Field[crate::cell::UnsafeCell::value]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::raw_get", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::replace", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::get_or_init", "Argument[0].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::get_or_try_init", "Argument[0].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::get_or_try_init", "Argument[0].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::get_or_try_init", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::get_or_try_init", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::cell::once::OnceCell::inner].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::set", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:core", "::try_insert", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[1]", "value", "dfc-generated"] - - ["lang:core", "::try_insert", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::advance_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::next", "Argument[self].Field[0].Field[crate::char::EscapeDebugInner::Char(0)]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::char::EscapeDebug(0)].Field[crate::char::EscapeDebugInner::Char(0)]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::advance_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::advance_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::char::decode::DecodeUtf16::iter].Element", "Argument[self].Field[crate::char::decode::DecodeUtf16::buf].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::char::decode::DecodeUtf16::iter].Element", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::unpaired_surrogate", "Argument[self].Field[crate::char::decode::DecodeUtf16Error::code]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::then", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::then", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::then_with", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::then_with", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::cmp::Reverse(0)]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::clone_from", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::provide_ref", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::provide_ref_with", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::provide_value", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::provide_value_with", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::error::Source::current]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::as_request", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::advance_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::backslash", "Argument[0]", "ReturnValue.Field[crate::escape::EscapeIterInner::data].Element", "value", "dfc-generated"] - ["lang:core", "::as_ref", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::deref", "Argument[self].Field[crate::ffi::va_list::VaList::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::deref_mut", "Argument[self].Field[crate::ffi::va_list::VaList::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::with_copy", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::as_str", "Argument[self].Field[crate::fmt::Arguments::pieces].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::new_const", "Argument[0]", "ReturnValue.Field[crate::fmt::Arguments::pieces]", "value", "dfc-generated"] - ["lang:core", "::new_v1", "Argument[0]", "ReturnValue.Field[crate::fmt::Arguments::pieces]", "value", "dfc-generated"] - ["lang:core", "::new_v1", "Argument[1]", "ReturnValue.Field[crate::fmt::Arguments::args]", "value", "dfc-generated"] - ["lang:core", "::new_v1_formatted", "Argument[0]", "ReturnValue.Field[crate::fmt::Arguments::pieces]", "value", "dfc-generated"] - ["lang:core", "::new_v1_formatted", "Argument[1]", "ReturnValue.Field[crate::fmt::Arguments::args]", "value", "dfc-generated"] - ["lang:core", "::new_v1_formatted", "Argument[2]", "ReturnValue.Field[crate::fmt::Arguments::fmt].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::align", "Argument[self].Field[crate::fmt::Formatter::options].Field[crate::fmt::FormattingOptions::align]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::debug_list", "Argument[self]", "ReturnValue.Field[crate::fmt::builders::DebugList::inner].Field[crate::fmt::builders::DebugInner::fmt]", "value", "dfc-generated"] - ["lang:core", "::debug_map", "Argument[self]", "ReturnValue.Field[crate::fmt::builders::DebugMap::fmt]", "value", "dfc-generated"] - ["lang:core", "::debug_set", "Argument[self]", "ReturnValue.Field[crate::fmt::builders::DebugSet::inner].Field[crate::fmt::builders::DebugInner::fmt]", "value", "dfc-generated"] - ["lang:core", "::debug_struct", "Argument[self]", "ReturnValue.Field[crate::fmt::builders::DebugStruct::fmt]", "value", "dfc-generated"] - ["lang:core", "::debug_tuple", "Argument[self]", "ReturnValue.Field[crate::fmt::builders::DebugTuple::fmt]", "value", "dfc-generated"] + - ["lang:core", "::fill", "Argument[self].Field[crate::fmt::Formatter::options].Field[crate::fmt::FormattingOptions::fill]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::flags", "Argument[self].Field[crate::fmt::Formatter::options].Field[crate::fmt::FormattingOptions::flags]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::fmt::Formatter::buf]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::fmt::Formatter::options]", "value", "dfc-generated"] + - ["lang:core", "::options", "Argument[self].Field[crate::fmt::Formatter::options]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::padding", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::fmt::PostPadding::padding]", "value", "dfc-generated"] + - ["lang:core", "::padding", "Argument[self].Field[crate::fmt::Formatter::options].Field[crate::fmt::FormattingOptions::fill]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::fmt::PostPadding::fill]", "value", "dfc-generated"] + - ["lang:core", "::precision", "Argument[self].Field[crate::fmt::Formatter::options].Field[crate::fmt::FormattingOptions::precision]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::width", "Argument[self].Field[crate::fmt::Formatter::options].Field[crate::fmt::FormattingOptions::width]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::with_options", "Argument[0]", "ReturnValue.Field[crate::fmt::Formatter::options]", "value", "dfc-generated"] + - ["lang:core", "::with_options", "Argument[self].Field[crate::fmt::Formatter::buf]", "ReturnValue.Field[crate::fmt::Formatter::buf]", "value", "dfc-generated"] + - ["lang:core", "::align", "Argument[0]", "Argument[self].Field[crate::fmt::FormattingOptions::align]", "value", "dfc-generated"] + - ["lang:core", "::align", "Argument[0]", "ReturnValue.Field[crate::fmt::FormattingOptions::align]", "value", "dfc-generated"] - ["lang:core", "::align", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::alternate", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::create_formatter", "Argument[0]", "ReturnValue.Field[crate::fmt::Formatter::buf]", "value", "dfc-generated"] - ["lang:core", "::create_formatter", "Argument[self]", "ReturnValue.Field[crate::fmt::Formatter::options]", "value", "dfc-generated"] - ["lang:core", "::debug_as_hex", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::fill", "Argument[0]", "Argument[self].Field[crate::fmt::FormattingOptions::fill]", "value", "dfc-generated"] + - ["lang:core", "::fill", "Argument[0]", "ReturnValue.Field[crate::fmt::FormattingOptions::fill]", "value", "dfc-generated"] - ["lang:core", "::fill", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::flags", "Argument[0]", "Argument[self].Field[crate::fmt::FormattingOptions::flags]", "value", "dfc-generated"] + - ["lang:core", "::get_align", "Argument[self].Field[crate::fmt::FormattingOptions::align]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::get_fill", "Argument[self].Field[crate::fmt::FormattingOptions::fill]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::get_flags", "Argument[self].Field[crate::fmt::FormattingOptions::flags]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::get_precision", "Argument[self].Field[crate::fmt::FormattingOptions::precision]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::get_width", "Argument[self].Field[crate::fmt::FormattingOptions::width]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::precision", "Argument[0]", "Argument[self].Field[crate::fmt::FormattingOptions::precision]", "value", "dfc-generated"] + - ["lang:core", "::precision", "Argument[0]", "ReturnValue.Field[crate::fmt::FormattingOptions::precision]", "value", "dfc-generated"] - ["lang:core", "::precision", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::sign", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::sign_aware_zero_pad", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::width", "Argument[0]", "Argument[self].Field[crate::fmt::FormattingOptions::width]", "value", "dfc-generated"] + - ["lang:core", "::width", "Argument[0]", "ReturnValue.Field[crate::fmt::FormattingOptions::width]", "value", "dfc-generated"] - ["lang:core", "::width", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::entries", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::entry", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::entry_with", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::finish", "Argument[self].Field[crate::fmt::builders::DebugList::inner].Field[crate::fmt::builders::DebugInner::result]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::entries", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::entry", "Argument[self].Field[crate::fmt::builders::DebugMap::result].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::fmt::builders::DebugMap::result].Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:core", "::entry", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::finish", "Argument[self].Field[crate::fmt::builders::DebugMap::result].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:core", "::finish", "Argument[self].Field[crate::fmt::builders::DebugMap::result]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::finish_non_exhaustive", "Argument[self].Field[crate::fmt::builders::DebugMap::result].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:core", "::finish_non_exhaustive", "Argument[self].Field[crate::fmt::builders::DebugMap::result]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::key", "Argument[self].Field[crate::fmt::builders::DebugMap::result].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::fmt::builders::DebugMap::result].Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:core", "::key", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::key_with", "Argument[self].Field[crate::fmt::builders::DebugMap::result].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::fmt::builders::DebugMap::result].Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:core", "::key_with", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::value", "Argument[self].Field[crate::fmt::builders::DebugMap::result].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::fmt::builders::DebugMap::result].Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:core", "::value", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::value_with", "Argument[self].Field[crate::fmt::builders::DebugMap::result].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::fmt::builders::DebugMap::result].Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:core", "::value_with", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::entries", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::entry", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::entry_with", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::finish", "Argument[self].Field[crate::fmt::builders::DebugSet::inner].Field[crate::fmt::builders::DebugInner::result]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::finish_non_exhaustive", "Argument[self].Field[crate::fmt::builders::DebugSet::inner].Field[crate::fmt::builders::DebugInner::result]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::field", "Argument[self].Field[crate::fmt::builders::DebugStruct::result].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::fmt::builders::DebugStruct::result].Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:core", "::field", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::field_with", "Argument[self].Field[crate::fmt::builders::DebugStruct::result].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::fmt::builders::DebugStruct::result].Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:core", "::field_with", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::finish", "Argument[self].Field[crate::fmt::builders::DebugStruct::result].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:core", "::finish", "Argument[self].Field[crate::fmt::builders::DebugStruct::result]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::finish_non_exhaustive", "Argument[self].Field[crate::fmt::builders::DebugStruct::result].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:core", "::finish_non_exhaustive", "Argument[self].Field[crate::fmt::builders::DebugStruct::result]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::field", "Argument[self].Field[crate::fmt::builders::DebugTuple::result].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::fmt::builders::DebugTuple::result].Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:core", "::field", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::field_with", "Argument[self].Field[crate::fmt::builders::DebugTuple::result].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::fmt::builders::DebugTuple::result].Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:core", "::field_with", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::finish", "Argument[self].Field[crate::fmt::builders::DebugTuple::result].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:core", "::finish", "Argument[self].Field[crate::fmt::builders::DebugTuple::result]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::finish_non_exhaustive", "Argument[self].Field[crate::fmt::builders::DebugTuple::result].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:core", "::finish_non_exhaustive", "Argument[self].Field[crate::fmt::builders::DebugTuple::result]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fmt", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::fmt", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::fmt", "Argument[0]", "Argument[self]", "taint", "df-generated"] @@ -578,6 +335,7 @@ extensions: - ["lang:core", "::digit", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::digit", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::digit", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::as_usize", "Argument[self].Field[crate::fmt::rt::Argument::ty].Field[crate::fmt::rt::ArgumentType::Count(0)]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::from_usize", "Argument[0].Reference", "ReturnValue.Field[crate::fmt::rt::Argument::ty].Field[crate::fmt::rt::ArgumentType::Count(0)]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::fmt::rt::Placeholder::position]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::fmt::rt::Placeholder::fill]", "value", "dfc-generated"] @@ -587,202 +345,202 @@ extensions: - ["lang:core", "::new", "Argument[5]", "ReturnValue.Field[crate::fmt::rt::Placeholder::width]", "value", "dfc-generated"] - ["lang:core", "::take_output", "Argument[self].Reference.Field[crate::future::join::MaybeDone::Done(0)]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::into_inner", "Argument[self].Field[0].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::future::ready::Ready(0)].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::finish", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::new_with_keys", "Argument[0]", "ReturnValue.Field[crate::hash::sip::SipHasher13::hasher].Field[crate::hash::sip::Hasher::k0]", "value", "dfc-generated"] + - ["lang:core", "::new_with_keys", "Argument[1]", "ReturnValue.Field[crate::hash::sip::SipHasher13::hasher].Field[crate::hash::sip::Hasher::k1]", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::io::borrowed_buf::BorrowedBuf::buf]", "value", "dfc-generated"] - ["lang:core", "::clear", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::init_len", "Argument[self].Field[crate::io::borrowed_buf::BorrowedBuf::init]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::len", "Argument[self].Field[crate::io::borrowed_buf::BorrowedBuf::filled]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::set_init", "Argument[0]", "Argument[self].Field[crate::io::borrowed_buf::BorrowedBuf::init]", "value", "dfc-generated"] + - ["lang:core", "::set_init", "Argument[0]", "ReturnValue.Field[crate::io::borrowed_buf::BorrowedBuf::init]", "value", "dfc-generated"] + - ["lang:core", "::set_init", "Argument[self].Field[crate::io::borrowed_buf::BorrowedBuf::init]", "ReturnValue.Field[crate::io::borrowed_buf::BorrowedBuf::init]", "value", "dfc-generated"] - ["lang:core", "::set_init", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::unfilled", "Argument[self].Field[crate::io::borrowed_buf::BorrowedBuf::filled]", "ReturnValue.Field[crate::io::borrowed_buf::BorrowedCursor::start]", "value", "dfc-generated"] - ["lang:core", "::advance", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::advance_unchecked", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::advance_unchecked", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::capacity", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::ensure_init", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::reborrow", "Argument[self].Field[crate::io::borrowed_buf::BorrowedCursor::start]", "ReturnValue.Field[crate::io::borrowed_buf::BorrowedCursor::start]", "value", "dfc-generated"] + - ["lang:core", "::set_init", "Argument[self].Field[crate::io::borrowed_buf::BorrowedCursor::buf].Field[crate::io::borrowed_buf::BorrowedBuf::init]", "ReturnValue.Field[crate::io::borrowed_buf::BorrowedCursor::buf].Field[crate::io::borrowed_buf::BorrowedBuf::init]", "value", "dfc-generated"] - ["lang:core", "::set_init", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[0].Field[crate::ops::control_flow::ControlFlow::Break(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::written", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::fold", "Argument[0].Field[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::fold", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::fold", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::fold", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::into_remainder", "Argument[self].Field[crate::iter::adapters::array_chunks::ArrayChunks::remainder]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::array_chunks::ArrayChunks::iter]", "value", "dfc-generated"] - - ["lang:core", "::advance_back_by", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::rfold", "Argument[self].Field[0].Field[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[0].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[0].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::advance_by", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::fold", "Argument[self].Field[0].Field[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[0].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[0].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::advance_back_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::advance_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::chain::Chain::a].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::chain::Chain::b].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next_unchecked", "Argument[self].Field[crate::iter::adapters::cloned::Cloned::it].Element", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::cloned::Cloned::it]", "value", "dfc-generated"] - ["lang:core", "::advance_back_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::advance_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::copied::Copied::it]", "value", "dfc-generated"] - - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::cycle::Cycle::iter]", "value", "dfc-generated"] - - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::cycle::Cycle::orig]", "value", "dfc-generated"] + - ["lang:core", "::advance_by", "Argument[self].Field[crate::iter::adapters::cycle::Cycle::orig].Reference", "Argument[self].Field[crate::iter::adapters::cycle::Cycle::iter]", "value", "dfc-generated"] + - ["lang:core", "::advance_by", "Argument[self].Field[crate::iter::adapters::cycle::Cycle::orig]", "Argument[self].Field[crate::iter::adapters::cycle::Cycle::iter].Reference", "value", "dfc-generated"] + - ["lang:core", "::advance_by", "Argument[self].Field[crate::iter::adapters::cycle::Cycle::orig]", "Argument[self].Field[crate::iter::adapters::cycle::Cycle::iter]", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::try_fold", "Argument[self].Field[crate::iter::adapters::cycle::Cycle::orig].Reference", "Argument[self].Field[crate::iter::adapters::cycle::Cycle::iter]", "value", "dfc-generated"] + - ["lang:core", "::try_fold", "Argument[self].Field[crate::iter::adapters::cycle::Cycle::orig]", "Argument[self].Field[crate::iter::adapters::cycle::Cycle::iter].Reference", "value", "dfc-generated"] + - ["lang:core", "::try_fold", "Argument[self].Field[crate::iter::adapters::cycle::Cycle::orig]", "Argument[self].Field[crate::iter::adapters::cycle::Cycle::iter]", "value", "dfc-generated"] + - ["lang:core", "::new", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::advance_back_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::next_back", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::nth_back", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::__iterator_get_unchecked", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::__iterator_get_unchecked", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::advance_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::nth", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::adapters::enumerate::Enumerate::count]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[0]", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::adapters::enumerate::Enumerate::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Field[1]", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::adapters::enumerate::Enumerate::iter].Element", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::iter::adapters::enumerate::Enumerate::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Field[1]", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::iter::adapters::enumerate::Enumerate::iter].Element", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::enumerate::Enumerate::iter]", "value", "dfc-generated"] - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::filter::Filter::iter]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::filter::Filter::predicate]", "value", "dfc-generated"] - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::filter_map::FilterMap::iter]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::filter_map::FilterMap::f]", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::iter::adapters::flatten::FlatMap::inner].Reference", "ReturnValue.Field[crate::iter::adapters::flatten::FlatMap::inner]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::iter::adapters::flatten::FlatMap::inner]", "ReturnValue.Field[crate::iter::adapters::flatten::FlatMap::inner]", "value", "dfc-generated"] + - ["lang:core", "::advance_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::into_parts", "Argument[self].Field[crate::iter::adapters::flatten::FlatMap::inner].Field[crate::iter::adapters::flatten::FlattenCompat::backiter]", "ReturnValue.Field[2]", "value", "dfc-generated"] + - ["lang:core", "::into_parts", "Argument[self].Field[crate::iter::adapters::flatten::FlatMap::inner].Field[crate::iter::adapters::flatten::FlattenCompat::frontiter]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::iter::adapters::flatten::Flatten::inner].Reference", "ReturnValue.Field[crate::iter::adapters::flatten::Flatten::inner]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::iter::adapters::flatten::Flatten::inner]", "ReturnValue.Field[crate::iter::adapters::flatten::Flatten::inner]", "value", "dfc-generated"] + - ["lang:core", "::advance_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::iter::adapters::fuse::Fuse::iter]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::fuse::Fuse::iter].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::inspect::Inspect::iter]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::inspect::Inspect::f]", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::adapters::intersperse::Intersperse::separator].Reference", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::adapters::intersperse::Intersperse::separator]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::intersperse::Intersperse::separator]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::intersperse::IntersperseWith::separator]", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::__iterator_get_unchecked", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next_unchecked", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::iter::adapters::map::Map::iter]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::map::Map::iter]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::map::Map::f]", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[0].Field[crate::ops::control_flow::ControlFlow::Break(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::adapters::map_while::MapWhile::iter].Element", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::map_while::MapWhile::iter]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::map_while::MapWhile::predicate]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::iter::adapters::map_windows::Buffer::start]", "ReturnValue.Field[crate::iter::adapters::map_windows::Buffer::start]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::next", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::map_windows::MapWindows::f]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::rfold", "Argument[0]", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::try_rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::last", "Argument[self].Field[crate::iter::adapters::peekable::Peekable::peeked].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::adapters::peekable::Peekable::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::adapters::peekable::Peekable::peeked].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::iter::adapters::peekable::Peekable::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::iter::adapters::peekable::Peekable::peeked].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::peekable::Peekable::iter]", "value", "dfc-generated"] + - ["lang:core", "::peek", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::peek_mut", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::advance_back_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::iter::adapters::rev::Rev::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::iter::adapters::rev::Rev::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::advance_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::rev::Rev::iter]", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[0].Field[crate::ops::control_flow::ControlFlow::Break(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::adapters::scan::Scan::iter].Element", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::scan::Scan::iter]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::scan::Scan::state]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[2]", "ReturnValue.Field[crate::iter::adapters::scan::Scan::f]", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[0].Field[crate::ops::control_flow::ControlFlow::Break(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::last", "Argument[self].Field[crate::iter::adapters::skip::Skip::iter].Element", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::adapters::skip::Skip::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::iter::adapters::skip::Skip::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::iter::adapters::skip::Skip::iter].Element", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::skip::Skip::iter]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::skip::Skip::n]", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] @@ -791,55 +549,44 @@ extensions: - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::skip_while::SkipWhile::iter]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::skip_while::SkipWhile::predicate]", "value", "dfc-generated"] + - ["lang:core", "::spec_next_back", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::spec_rfold", "Argument[0]", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::spec_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::spec_rfold", "Argument[1].ReturnValue", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::spec_rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::spec_try_rfold", "Argument[0]", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::spec_try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::spec_try_rfold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::spec_try_rfold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::spec_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::spec_fold", "Argument[1].ReturnValue", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::spec_fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::spec_fold", "Argument[self].Field[crate::iter::adapters::step_by::StepBy::iter].Element", "Argument[1].Parameter[1]", "value", "dfc-generated"] + - ["lang:core", "::spec_fold", "Argument[self].Field[crate::iter::adapters::step_by::StepBy::iter].Field[crate::ops::range::Range::start]", "Argument[1].Parameter[1]", "value", "dfc-generated"] + - ["lang:core", "::spec_next", "Argument[self].Field[crate::iter::adapters::step_by::StepBy::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::spec_next", "Argument[self].Field[crate::iter::adapters::step_by::StepBy::iter].Field[crate::ops::range::Range::start]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::spec_nth", "Argument[self].Field[crate::iter::adapters::step_by::StepBy::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::spec_size_hint", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::spec_try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[0]", "Argument[1].Parameter[0]", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[0]", "Argument[1].Parameter[0]", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::spec_try_fold", "Argument[self].Field[crate::iter::adapters::step_by::StepBy::iter].Element", "Argument[1].Parameter[1]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::spec_fold", "Argument[0].Field[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::spec_fold", "Argument[0].Field[crate::ops::control_flow::ControlFlow::Break(0)].Field[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::spec_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::spec_fold", "Argument[1].ReturnValue", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::spec_fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::advance_back_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::nth_back", "Argument[self].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::rfold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[self].Field[crate::ops::control_flow::ControlFlow::Break(0)].Field[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::rfold", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[0].Field[crate::ops::control_flow::ControlFlow::Break(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::fold", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::fold", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::fold", "Argument[self].Field[crate::ops::control_flow::ControlFlow::Break(0)].Field[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::fold", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[0].Field[crate::ops::control_flow::ControlFlow::Break(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::len", "Argument[self].Field[crate::iter::adapters::take::Take::n]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::adapters::take::Take::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::iter::adapters::take::Take::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::size_hint", "Argument[self].Field[crate::iter::adapters::take::Take::n]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:core", "::size_hint", "Argument[self].Field[crate::iter::adapters::take::Take::n]", "ReturnValue.Field[1].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::take::Take::iter]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::take::Take::n]", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[0].Field[crate::ops::control_flow::ControlFlow::Break(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::adapters::take_while::TakeWhile::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::adapters::take_while::TakeWhile::iter].Element", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::take_while::TakeWhile::iter]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::take_while::TakeWhile::predicate]", "value", "dfc-generated"] @@ -851,91 +598,155 @@ extensions: - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::zip::Zip::a]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::zip::Zip::b]", "value", "dfc-generated"] - - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::iter::adapters::zip::Zip::a]", "value", "dfc-generated"] - - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::iter::adapters::zip::Zip::b]", "value", "dfc-generated"] + - ["lang:core", "::size_hint", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::next", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::sources::once_with::OnceWith::make].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::sources::once_with::OnceWith::make].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::iter::sources::repeat::Repeat::element].Reference", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::iter::sources::repeat::Repeat::element]", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::iter::sources::repeat::Repeat::element]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::iter::sources::repeat::Repeat::element].Reference", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::iter::sources::repeat::Repeat::element]", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::iter::sources::repeat::Repeat::element]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::sources::repeat::Repeat::element].Reference", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::sources::repeat::Repeat::element]", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::iter::sources::repeat::Repeat::element]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::iter::sources::repeat::Repeat::element].Reference", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::iter::sources::repeat::Repeat::element]", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::iter::sources::repeat::Repeat::element]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::iter::sources::repeat_n::RepeatN::count]", "ReturnValue.Field[crate::iter::sources::repeat_n::RepeatN::count]", "value", "dfc-generated"] - ["lang:core", "::advance_back_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::nth_back", "Argument[self].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::len", "Argument[self].Field[crate::iter::sources::repeat_n::RepeatN::count]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::advance_by", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::advance_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::advance_by", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::next", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::try_fold", "Argument[1]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::try_fold", "Argument[self]", "Argument[1]", "taint", "df-generated"] + - ["lang:core", "::next", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::deref", "Argument[self].Field[crate::mem::manually_drop::ManuallyDrop::value]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::deref_mut", "Argument[self].Field[crate::mem::manually_drop::ManuallyDrop::value]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::into_inner", "Argument[0].Field[crate::mem::manually_drop::ManuallyDrop::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::mem::manually_drop::ManuallyDrop::value]", "value", "dfc-generated"] + - ["lang:core", "::take", "Argument[0].Field[crate::mem::manually_drop::ManuallyDrop::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::as_mut_ptr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::as_ptr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::assume_init_mut", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::assume_init_ref", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::clone_from_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::copy_from_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::fill", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::fill_with", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::slice_as_mut_ptr", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::slice_as_ptr", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::slice_assume_init_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::slice_assume_init_ref", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::write", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::net::ip_addr::IpAddr::V4(0)].Field[crate::net::ip_addr::Ipv4Addr::octets]", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::net::ip_addr::IpAddr::V4(0)]", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::net::ip_addr::IpAddr::V6(0)].Field[crate::net::ip_addr::Ipv6Addr::octets]", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::net::ip_addr::IpAddr::V6(0)]", "value", "dfc-generated"] - - ["lang:core", "::to_canonical", "Argument[self].Field[crate::net::ip_addr::IpAddr::V6(0)].Reference", "ReturnValue.Field[crate::net::ip_addr::IpAddr::V6(0)]", "value", "dfc-generated"] - ["lang:core", "::to_canonical", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::net::ip_addr::Ipv4Addr::octets]", "value", "dfc-generated"] - ["lang:core", "::bitand", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::bitor", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::not", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::as_octets", "Argument[self].Field[crate::net::ip_addr::Ipv4Addr::octets]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::from_octets", "Argument[0]", "ReturnValue.Field[crate::net::ip_addr::Ipv4Addr::octets]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::net::ip_addr::Ipv4Addr::octets].Element", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::net::ip_addr::Ipv4Addr::octets].Element", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[2]", "ReturnValue.Field[crate::net::ip_addr::Ipv4Addr::octets].Element", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[3]", "ReturnValue.Field[crate::net::ip_addr::Ipv4Addr::octets].Element", "value", "dfc-generated"] + - ["lang:core", "::octets", "Argument[self].Field[crate::net::ip_addr::Ipv4Addr::octets]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::to_ipv6_compatible", "Argument[self].Field[crate::net::ip_addr::Ipv4Addr::octets].Element", "ReturnValue.Field[crate::net::ip_addr::Ipv6Addr::octets].Element", "value", "dfc-generated"] + - ["lang:core", "::to_ipv6_mapped", "Argument[self].Field[crate::net::ip_addr::Ipv4Addr::octets].Element", "ReturnValue.Field[crate::net::ip_addr::Ipv6Addr::octets].Element", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::net::ip_addr::Ipv6Addr::octets]", "value", "dfc-generated"] - ["lang:core", "::bitand", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::bitor", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::not", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::as_octets", "Argument[self].Field[crate::net::ip_addr::Ipv6Addr::octets]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::from_octets", "Argument[0]", "ReturnValue.Field[crate::net::ip_addr::Ipv6Addr::octets]", "value", "dfc-generated"] + - ["lang:core", "::octets", "Argument[self].Field[crate::net::ip_addr::Ipv6Addr::octets]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::to_canonical", "Argument[self].Reference", "ReturnValue.Field[crate::net::ip_addr::IpAddr::V6(0)]", "value", "dfc-generated"] + - ["lang:core", "::to_ipv4_mapped", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from", "Argument[0].Field[1]", "ReturnValue.Field[crate::net::socket_addr::SocketAddr::V4(0)].Field[crate::net::socket_addr::SocketAddrV4::port]", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0].Field[1]", "ReturnValue.Field[crate::net::socket_addr::SocketAddr::V6(0)].Field[crate::net::socket_addr::SocketAddrV6::port]", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::net::socket_addr::SocketAddr::V4(0)]", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::net::socket_addr::SocketAddr::V6(0)]", "value", "dfc-generated"] + - ["lang:core", "::new", "Argument[0].Field[crate::net::ip_addr::IpAddr::V4(0)]", "ReturnValue.Field[crate::net::socket_addr::SocketAddr::V4(0)].Field[crate::net::socket_addr::SocketAddrV4::ip]", "value", "dfc-generated"] + - ["lang:core", "::new", "Argument[0].Field[crate::net::ip_addr::IpAddr::V6(0)]", "ReturnValue.Field[crate::net::socket_addr::SocketAddr::V6(0)].Field[crate::net::socket_addr::SocketAddrV6::ip]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::net::socket_addr::SocketAddr::V4(0)].Field[crate::net::socket_addr::SocketAddrV4::port]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::net::socket_addr::SocketAddr::V6(0)].Field[crate::net::socket_addr::SocketAddrV6::port]", "value", "dfc-generated"] + - ["lang:core", "::ip", "Argument[self].Field[crate::net::socket_addr::SocketAddrV4::ip]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::net::socket_addr::SocketAddrV4::ip]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::net::socket_addr::SocketAddrV4::port]", "value", "dfc-generated"] + - ["lang:core", "::port", "Argument[self].Field[crate::net::socket_addr::SocketAddrV4::port]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::set_ip", "Argument[0]", "Argument[self].Field[crate::net::socket_addr::SocketAddrV4::ip]", "value", "dfc-generated"] + - ["lang:core", "::set_port", "Argument[0]", "Argument[self].Field[crate::net::socket_addr::SocketAddrV4::port]", "value", "dfc-generated"] + - ["lang:core", "::flowinfo", "Argument[self].Field[crate::net::socket_addr::SocketAddrV6::flowinfo]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::ip", "Argument[self].Field[crate::net::socket_addr::SocketAddrV6::ip]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::net::socket_addr::SocketAddrV6::ip]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::net::socket_addr::SocketAddrV6::port]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[2]", "ReturnValue.Field[crate::net::socket_addr::SocketAddrV6::flowinfo]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[3]", "ReturnValue.Field[crate::net::socket_addr::SocketAddrV6::scope_id]", "value", "dfc-generated"] + - ["lang:core", "::port", "Argument[self].Field[crate::net::socket_addr::SocketAddrV6::port]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::scope_id", "Argument[self].Field[crate::net::socket_addr::SocketAddrV6::scope_id]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::set_flowinfo", "Argument[0]", "Argument[self].Field[crate::net::socket_addr::SocketAddrV6::flowinfo]", "value", "dfc-generated"] + - ["lang:core", "::set_ip", "Argument[0]", "Argument[self].Field[crate::net::socket_addr::SocketAddrV6::ip]", "value", "dfc-generated"] + - ["lang:core", "::set_port", "Argument[0]", "Argument[self].Field[crate::net::socket_addr::SocketAddrV6::port]", "value", "dfc-generated"] + - ["lang:core", "::set_scope_id", "Argument[0]", "Argument[self].Field[crate::net::socket_addr::SocketAddrV6::scope_id]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::num::bignum::Big32x40::base]", "ReturnValue.Field[crate::num::bignum::Big32x40::base]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::num::bignum::Big32x40::size]", "ReturnValue.Field[crate::num::bignum::Big32x40::size]", "value", "dfc-generated"] + - ["lang:core", "::add", "Argument[0].Field[crate::num::bignum::Big32x40::size]", "Argument[self].Field[crate::num::bignum::Big32x40::size]", "value", "dfc-generated"] + - ["lang:core", "::add", "Argument[0].Field[crate::num::bignum::Big32x40::size]", "ReturnValue.Field[crate::num::bignum::Big32x40::size]", "value", "dfc-generated"] + - ["lang:core", "::add", "Argument[self].Field[crate::num::bignum::Big32x40::size]", "ReturnValue.Field[crate::num::bignum::Big32x40::size]", "value", "dfc-generated"] - ["lang:core", "::add", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::add_small", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::digits", "Argument[self].Field[crate::num::bignum::Big32x40::base].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::div_rem", "Argument[0].Field[crate::num::bignum::Big32x40::size]", "Argument[2].Field[crate::num::bignum::Big32x40::size]", "value", "dfc-generated"] - ["lang:core", "::div_rem_small", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::from_small", "Argument[0]", "ReturnValue.Field[crate::num::bignum::Big32x40::base].Element", "value", "dfc-generated"] - ["lang:core", "::from_u64", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_bit", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::get_bit", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::mul_digits", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::mul_pow2", "Argument[self].Field[crate::num::bignum::Big32x40::base].Element", "ReturnValue.Field[crate::num::bignum::Big32x40::base].Element", "value", "dfc-generated"] - ["lang:core", "::mul_pow2", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::mul_pow5", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::mul_small", "Argument[self].Field[crate::num::bignum::Big32x40::size]", "ReturnValue.Field[crate::num::bignum::Big32x40::size]", "value", "dfc-generated"] - ["lang:core", "::mul_small", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::sub", "Argument[0].Field[crate::num::bignum::Big32x40::size]", "Argument[self].Field[crate::num::bignum::Big32x40::size]", "value", "dfc-generated"] + - ["lang:core", "::sub", "Argument[0].Field[crate::num::bignum::Big32x40::size]", "ReturnValue.Field[crate::num::bignum::Big32x40::size]", "value", "dfc-generated"] + - ["lang:core", "::sub", "Argument[self].Field[crate::num::bignum::Big32x40::size]", "ReturnValue.Field[crate::num::bignum::Big32x40::size]", "value", "dfc-generated"] - ["lang:core", "::sub", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::num::bignum::tests::Big8x3::base]", "ReturnValue.Field[crate::num::bignum::tests::Big8x3::base]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::num::bignum::tests::Big8x3::size]", "ReturnValue.Field[crate::num::bignum::tests::Big8x3::size]", "value", "dfc-generated"] + - ["lang:core", "::add", "Argument[0].Field[crate::num::bignum::tests::Big8x3::size]", "Argument[self].Field[crate::num::bignum::tests::Big8x3::size]", "value", "dfc-generated"] + - ["lang:core", "::add", "Argument[0].Field[crate::num::bignum::tests::Big8x3::size]", "ReturnValue.Field[crate::num::bignum::tests::Big8x3::size]", "value", "dfc-generated"] + - ["lang:core", "::add", "Argument[self].Field[crate::num::bignum::tests::Big8x3::size]", "ReturnValue.Field[crate::num::bignum::tests::Big8x3::size]", "value", "dfc-generated"] - ["lang:core", "::add", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::add_small", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::digits", "Argument[self].Field[crate::num::bignum::tests::Big8x3::base].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::div_rem", "Argument[0].Field[crate::num::bignum::tests::Big8x3::size]", "Argument[2].Field[crate::num::bignum::tests::Big8x3::size]", "value", "dfc-generated"] - ["lang:core", "::div_rem_small", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::from_small", "Argument[0]", "ReturnValue.Field[crate::num::bignum::tests::Big8x3::base].Element", "value", "dfc-generated"] - ["lang:core", "::from_u64", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_bit", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::get_bit", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::mul_digits", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::mul_pow2", "Argument[self].Field[crate::num::bignum::tests::Big8x3::base].Element", "ReturnValue.Field[crate::num::bignum::tests::Big8x3::base].Element", "value", "dfc-generated"] - ["lang:core", "::mul_pow2", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::mul_pow5", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::mul_small", "Argument[self].Field[crate::num::bignum::tests::Big8x3::size]", "ReturnValue.Field[crate::num::bignum::tests::Big8x3::size]", "value", "dfc-generated"] - ["lang:core", "::mul_small", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::sub", "Argument[0].Field[crate::num::bignum::tests::Big8x3::size]", "Argument[self].Field[crate::num::bignum::tests::Big8x3::size]", "value", "dfc-generated"] + - ["lang:core", "::sub", "Argument[0].Field[crate::num::bignum::tests::Big8x3::size]", "ReturnValue.Field[crate::num::bignum::tests::Big8x3::size]", "value", "dfc-generated"] + - ["lang:core", "::sub", "Argument[self].Field[crate::num::bignum::tests::Big8x3::size]", "ReturnValue.Field[crate::num::bignum::tests::Big8x3::size]", "value", "dfc-generated"] - ["lang:core", "::sub", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::zero_pow2", "Argument[0]", "ReturnValue.Field[crate::num::dec2flt::common::BiasedFp::e]", "value", "dfc-generated"] + - ["lang:core", "::right_shift", "Argument[0]", "Argument[self]", "taint", "df-generated"] + - ["lang:core", "::try_add_digit", "Argument[0]", "Argument[self].Field[crate::num::dec2flt::decimal::Decimal::digits].Element", "value", "dfc-generated"] + - ["lang:core", "::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::mul", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::normalize", "Argument[self].Field[crate::num::diy_float::Fp::e]", "ReturnValue.Field[crate::num::diy_float::Fp::e]", "value", "dfc-generated"] + - ["lang:core", "::normalize", "Argument[self].Field[crate::num::diy_float::Fp::f]", "ReturnValue.Field[crate::num::diy_float::Fp::f]", "value", "dfc-generated"] - ["lang:core", "::normalize_to", "Argument[0]", "ReturnValue.Field[crate::num::diy_float::Fp::e]", "value", "dfc-generated"] + - ["lang:core", "::kind", "Argument[self].Field[crate::num::error::ParseIntError::kind]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::len", "Argument[self].Reference.Field[crate::num::fmt::Part::Zero(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::write", "Argument[self].Reference.Field[crate::num::fmt::Part::Zero(0)]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::num::niche_types::I32NotAllOnes(0)]", "value", "dfc-generated"] @@ -975,18 +786,12 @@ extensions: - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::num::niche_types::UsizeNoHighBit(0)]", "value", "dfc-generated"] - ["lang:core", "::new_unchecked", "Argument[0]", "ReturnValue.Field[crate::num::niche_types::UsizeNoHighBit(0)]", "value", "dfc-generated"] - ["lang:core", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::bitor", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::bitor_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::from_mut_unchecked", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new_unchecked", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::add_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - - ["lang:core", "::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::div", "Argument[self].Field[0]", "ReturnValue.Field[crate::num::saturating::Saturating(0)]", "value", "dfc-generated"] - - ["lang:core", "::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::mul_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - - ["lang:core", "::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::sub_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -999,16 +804,10 @@ extensions: - ["lang:core", "::bitxor", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::bitxor_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::abs", "Argument[self].Field[0]", "ReturnValue.Field[crate::num::saturating::Saturating(0)]", "value", "dfc-generated"] - ["lang:core", "::add_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - - ["lang:core", "::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::div", "Argument[self].Field[0]", "ReturnValue.Field[crate::num::wrapping::Wrapping(0)]", "value", "dfc-generated"] - - ["lang:core", "::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::mul_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::sub_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -1023,7 +822,6 @@ extensions: - ["lang:core", "::not", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::shl_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::shr_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - - ["lang:core", "::abs", "Argument[self].Field[0]", "ReturnValue.Field[crate::num::wrapping::Wrapping(0)]", "value", "dfc-generated"] - ["lang:core", "::from_residual", "Argument[0].Field[crate::ops::control_flow::ControlFlow::Break(0)]", "ReturnValue.Field[crate::ops::control_flow::ControlFlow::Break(0)]", "value", "dfc-generated"] - ["lang:core", "::branch", "Argument[self].Field[crate::ops::control_flow::ControlFlow::Break(0)]", "ReturnValue.Field[crate::ops::control_flow::ControlFlow::Break(0)].Field[crate::ops::control_flow::ControlFlow::Break(0)]", "value", "dfc-generated"] - ["lang:core", "::branch", "Argument[self].Field[crate::ops::control_flow::ControlFlow::Continue(0)]", "ReturnValue.Field[crate::ops::control_flow::ControlFlow::Continue(0)]", "value", "dfc-generated"] @@ -1039,48 +837,122 @@ extensions: - ["lang:core", "::map_continue", "Argument[0].ReturnValue", "ReturnValue.Field[crate::ops::control_flow::ControlFlow::Continue(0)]", "value", "dfc-generated"] - ["lang:core", "::map_continue", "Argument[self].Field[crate::ops::control_flow::ControlFlow::Break(0)]", "ReturnValue.Field[crate::ops::control_flow::ControlFlow::Break(0)]", "value", "dfc-generated"] - ["lang:core", "::map_continue", "Argument[self].Field[crate::ops::control_flow::ControlFlow::Continue(0)]", "Argument[0].Parameter[0]", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::ops::index_range::IndexRange::start]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::end", "Argument[self].Field[crate::ops::index_range::IndexRange::end]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new_unchecked", "Argument[0]", "ReturnValue.Field[crate::ops::index_range::IndexRange::start]", "value", "dfc-generated"] - ["lang:core", "::new_unchecked", "Argument[1]", "ReturnValue.Field[crate::ops::index_range::IndexRange::end]", "value", "dfc-generated"] + - ["lang:core", "::start", "Argument[self].Field[crate::ops::index_range::IndexRange::start]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::take_prefix", "Argument[self].Field[crate::ops::index_range::IndexRange::end]", "Argument[self].Field[crate::ops::index_range::IndexRange::start]", "value", "dfc-generated"] + - ["lang:core", "::take_prefix", "Argument[self].Field[crate::ops::index_range::IndexRange::end]", "ReturnValue.Field[crate::ops::index_range::IndexRange::end]", "value", "dfc-generated"] + - ["lang:core", "::take_prefix", "Argument[self].Field[crate::ops::index_range::IndexRange::start]", "ReturnValue.Field[crate::ops::index_range::IndexRange::start]", "value", "dfc-generated"] + - ["lang:core", "::take_suffix", "Argument[self].Field[crate::ops::index_range::IndexRange::end]", "ReturnValue.Field[crate::ops::index_range::IndexRange::end]", "value", "dfc-generated"] + - ["lang:core", "::take_suffix", "Argument[self].Field[crate::ops::index_range::IndexRange::start]", "Argument[self].Field[crate::ops::index_range::IndexRange::end]", "value", "dfc-generated"] + - ["lang:core", "::take_suffix", "Argument[self].Field[crate::ops::index_range::IndexRange::start]", "ReturnValue.Field[crate::ops::index_range::IndexRange::start]", "value", "dfc-generated"] - ["lang:core", "::zero_to", "Argument[0]", "ReturnValue.Field[crate::ops::index_range::IndexRange::end]", "value", "dfc-generated"] - ["lang:core", "::as_mut", "Argument[self].Reference.Field[crate::ops::range::Bound::Excluded(0)]", "ReturnValue.Field[crate::ops::range::Bound::Excluded(0)].Reference", "value", "dfc-generated"] - ["lang:core", "::as_mut", "Argument[self].Reference.Field[crate::ops::range::Bound::Included(0)]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)].Reference", "value", "dfc-generated"] - ["lang:core", "::as_ref", "Argument[self].Reference.Field[crate::ops::range::Bound::Excluded(0)]", "ReturnValue.Field[crate::ops::range::Bound::Excluded(0)].Reference", "value", "dfc-generated"] - ["lang:core", "::as_ref", "Argument[self].Reference.Field[crate::ops::range::Bound::Included(0)]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)].Reference", "value", "dfc-generated"] - - ["lang:core", "::cloned", "Argument[self].Field[crate::ops::range::Bound::Excluded(0)]", "ReturnValue.Field[crate::ops::range::Bound::Excluded(0)]", "value", "dfc-generated"] - - ["lang:core", "::cloned", "Argument[self].Field[crate::ops::range::Bound::Included(0)]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::cloned", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::map", "Argument[0].ReturnValue", "ReturnValue.Field[crate::ops::range::Bound::Excluded(0)]", "value", "dfc-generated"] - ["lang:core", "::map", "Argument[0].ReturnValue", "ReturnValue.Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] - ["lang:core", "::map", "Argument[self].Field[crate::ops::range::Bound::Excluded(0)]", "Argument[0].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::map", "Argument[self].Field[crate::ops::range::Bound::Included(0)]", "Argument[0].Parameter[0]", "value", "dfc-generated"] + - ["lang:core", "::from", "Argument[0].Field[crate::range::Range::end]", "ReturnValue.Field[crate::ops::range::Range::end]", "value", "dfc-generated"] + - ["lang:core", "::from", "Argument[0].Field[crate::range::Range::start]", "ReturnValue.Field[crate::ops::range::Range::start]", "value", "dfc-generated"] + - ["lang:core", "::setup", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::spec_next", "Argument[self].Field[crate::ops::range::Range::start]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::spec_next_back", "Argument[self].Field[crate::ops::range::Range::end].Reference", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::spec_next_back", "Argument[self].Field[crate::ops::range::Range::end]", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::spec_next_back", "Argument[self].Field[crate::ops::range::Range::end]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::spec_nth", "Argument[self].Field[crate::ops::range::Range::end].Reference", "Argument[self].Field[crate::ops::range::Range::start]", "value", "dfc-generated"] + - ["lang:core", "::spec_nth", "Argument[self].Field[crate::ops::range::Range::end]", "Argument[self].Field[crate::ops::range::Range::start].Reference", "value", "dfc-generated"] + - ["lang:core", "::spec_nth", "Argument[self].Field[crate::ops::range::Range::end]", "Argument[self].Field[crate::ops::range::Range::start]", "value", "dfc-generated"] + - ["lang:core", "::spec_nth_back", "Argument[self].Field[crate::ops::range::Range::end]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::spec_nth_back", "Argument[self].Field[crate::ops::range::Range::start]", "Argument[self].Field[crate::ops::range::Range::end]", "value", "dfc-generated"] + - ["lang:core", "::spec_nth_back", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_bounds", "Argument[self].Field[crate::ops::range::Range::end]", "ReturnValue.Field[1].Field[crate::ops::range::Bound::Excluded(0)]", "value", "dfc-generated"] + - ["lang:core", "::into_bounds", "Argument[self].Field[crate::ops::range::Range::start]", "ReturnValue.Field[0].Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::end_bound", "Argument[self].Field[crate::ops::range::Range::end]", "ReturnValue.Field[crate::ops::range::Bound::Excluded(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::end_bound", "Argument[self].Field[crate::ops::range::Range::end]", "ReturnValue.Field[crate::ops::range::Bound::Excluded(0)]", "value", "dfc-generated"] + - ["lang:core", "::start_bound", "Argument[self].Field[crate::ops::range::Range::start]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::start_bound", "Argument[self].Field[crate::ops::range::Range::start]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::from", "Argument[0].Field[crate::range::RangeFrom::start]", "ReturnValue.Field[crate::ops::range::RangeFrom::start]", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::ops::range::RangeFrom::start]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::into_bounds", "Argument[self].Field[crate::ops::range::RangeFrom::start]", "ReturnValue.Field[0].Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::bound", "Argument[self].Field[crate::ops::range::RangeFrom::start]", "ReturnValue.Field[1]", "value", "dfc-generated"] + - ["lang:core", "::start_bound", "Argument[self].Field[crate::ops::range::RangeFrom::start]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::start_bound", "Argument[self].Field[crate::ops::range::RangeFrom::start]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] - ["lang:core", "::get", "Argument[0]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::get_mut", "Argument[0]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::get_unchecked", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::get_unchecked_mut", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::index", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::index_mut", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::spec_next", "Argument[self].Field[crate::ops::range::RangeInclusive::start].Reference", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::spec_next", "Argument[self].Field[crate::ops::range::RangeInclusive::start]", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::spec_next", "Argument[self].Field[crate::ops::range::RangeInclusive::start]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::spec_next_back", "Argument[self].Field[crate::ops::range::RangeInclusive::end].Reference", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::spec_next_back", "Argument[self].Field[crate::ops::range::RangeInclusive::end]", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::spec_next_back", "Argument[self].Field[crate::ops::range::RangeInclusive::end]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::spec_try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::spec_try_fold", "Argument[self].Field[crate::ops::range::RangeInclusive::start].Reference", "Argument[1].Parameter[1]", "value", "dfc-generated"] + - ["lang:core", "::spec_try_fold", "Argument[self].Field[crate::ops::range::RangeInclusive::start]", "Argument[1].Parameter[1].Reference", "value", "dfc-generated"] + - ["lang:core", "::spec_try_fold", "Argument[self].Field[crate::ops::range::RangeInclusive::start]", "Argument[1].Parameter[1]", "value", "dfc-generated"] - ["lang:core", "::spec_try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_rfold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::try_fold", "Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::spec_try_rfold", "Argument[self].Field[crate::ops::range::RangeInclusive::end]", "Argument[1].Parameter[1]", "value", "dfc-generated"] + - ["lang:core", "::spec_try_rfold", "Argument[self].Field[crate::ops::range::RangeInclusive::start]", "Argument[1].Parameter[1]", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::ops::range::RangeInclusive::start].Reference", "Argument[self].Field[crate::ops::range::RangeInclusive::end]", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::ops::range::RangeInclusive::start]", "Argument[self].Field[crate::ops::range::RangeInclusive::end].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::ops::range::RangeInclusive::start]", "Argument[self].Field[crate::ops::range::RangeInclusive::end]", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::ops::range::RangeInclusive::end].Reference", "Argument[self].Field[crate::ops::range::RangeInclusive::start]", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::ops::range::RangeInclusive::end]", "Argument[self].Field[crate::ops::range::RangeInclusive::start].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::ops::range::RangeInclusive::end]", "Argument[self].Field[crate::ops::range::RangeInclusive::start]", "value", "dfc-generated"] + - ["lang:core", "::into_bounds", "Argument[self].Field[crate::ops::range::RangeInclusive::end]", "ReturnValue.Field[1].Field[crate::ops::range::Bound::Excluded(0)]", "value", "dfc-generated"] + - ["lang:core", "::into_bounds", "Argument[self].Field[crate::ops::range::RangeInclusive::end]", "ReturnValue.Field[1].Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::into_bounds", "Argument[self].Field[crate::ops::range::RangeInclusive::start]", "ReturnValue.Field[0].Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::end_bound", "Argument[self].Field[crate::ops::range::RangeInclusive::end]", "ReturnValue.Field[crate::ops::range::Bound::Excluded(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::end_bound", "Argument[self].Field[crate::ops::range::RangeInclusive::end]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::end_bound", "Argument[self].Field[crate::ops::range::RangeInclusive::end]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::start_bound", "Argument[self].Field[crate::ops::range::RangeInclusive::start]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::start_bound", "Argument[self].Field[crate::ops::range::RangeInclusive::start]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::end", "Argument[self].Field[crate::ops::range::RangeInclusive::end]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::ops::range::RangeInclusive::end]", "ReturnValue.Field[1]", "value", "dfc-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::ops::range::RangeInclusive::start]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::ops::range::RangeInclusive::start]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::ops::range::RangeInclusive::end]", "value", "dfc-generated"] + - ["lang:core", "::start", "Argument[self].Field[crate::ops::range::RangeInclusive::start]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::into_bounds", "Argument[self].Field[crate::ops::range::RangeTo::end]", "ReturnValue.Field[1].Field[crate::ops::range::Bound::Excluded(0)]", "value", "dfc-generated"] + - ["lang:core", "::bound", "Argument[self].Field[crate::ops::range::RangeTo::end]", "ReturnValue.Field[1]", "value", "dfc-generated"] + - ["lang:core", "::end_bound", "Argument[self].Field[crate::ops::range::RangeTo::end]", "ReturnValue.Field[crate::ops::range::Bound::Excluded(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::end_bound", "Argument[self].Field[crate::ops::range::RangeTo::end]", "ReturnValue.Field[crate::ops::range::Bound::Excluded(0)]", "value", "dfc-generated"] + - ["lang:core", "::into_bounds", "Argument[self].Field[crate::ops::range::RangeToInclusive::end]", "ReturnValue.Field[1].Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::bound", "Argument[self].Field[crate::ops::range::RangeToInclusive::end]", "ReturnValue.Field[1]", "value", "dfc-generated"] + - ["lang:core", "::end_bound", "Argument[self].Field[crate::ops::range::RangeToInclusive::end]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::end_bound", "Argument[self].Field[crate::ops::range::RangeToInclusive::end]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::branch", "Argument[self].Field[0]", "ReturnValue.Field[crate::ops::control_flow::ControlFlow::Continue(0)]", "value", "dfc-generated"] + - ["lang:core", "::branch", "Argument[self].Field[crate::ops::try_trait::NeverShortCircuit(0)]", "ReturnValue.Field[crate::ops::control_flow::ControlFlow::Continue(0)]", "value", "dfc-generated"] - ["lang:core", "::from_output", "Argument[0]", "ReturnValue.Field[crate::ops::try_trait::NeverShortCircuit(0)]", "value", "dfc-generated"] - ["lang:core", "::wrap_mut_1", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::wrap_mut_2", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::option::Item::opt].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::option::Item::opt]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::option::Iter::inner].Reference", "ReturnValue.Field[crate::option::Iter::inner]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::option::Iter::inner]", "ReturnValue.Field[crate::option::Iter::inner]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::option::Option::Some(0)].Reference", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::clone", "Argument[self].Field[crate::option::Option::Some(0)]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0].Reference.Field[crate::option::Option::Some(0)]", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::branch", "Argument[self].Field[crate::option::Option::Some(0)]", "ReturnValue.Field[crate::ops::control_flow::ControlFlow::Continue(0)]", "value", "dfc-generated"] - ["lang:core", "::from_output", "Argument[0]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::and", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::and_then", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::and_then", "Argument[self].Field[crate::option::Option::Some(0)].Field[0]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::and_then", "Argument[self].Field[crate::option::Option::Some(0)].Field[crate::path::Component::Normal(0)]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::and_then", "Argument[self].Field[crate::option::Option::Some(0)]", "Argument[0].Parameter[0]", "value", "dfc-generated"] - - ["lang:core", "::and_then", "Argument[self].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::as_mut", "Argument[self].Reference.Field[crate::option::Option::Some(0)]", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] - ["lang:core", "::as_ref", "Argument[self].Reference.Field[crate::option::Option::Some(0)]", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::cloned", "Argument[self].Field[crate::option::Option::Some(0)].Reference", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::cloned", "Argument[self].Field[crate::option::Option::Some(0)]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::copied", "Argument[self].Field[crate::option::Option::Some(0)].Reference", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::expect", "Argument[self].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] @@ -1098,15 +970,12 @@ extensions: - ["lang:core", "::is_none_or", "Argument[self].Field[crate::option::Option::Some(0)]", "Argument[0].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::is_some_and", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::is_some_and", "Argument[self].Field[crate::option::Option::Some(0)]", "Argument[0].Parameter[0]", "value", "dfc-generated"] - - ["lang:core", "::map", "Argument[0].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::map", "Argument[0].ReturnValue", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::map", "Argument[self].Field[crate::option::Option::Some(0)].Field[0]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[0]", "value", "dfc-generated"] - - ["lang:core", "::map", "Argument[self].Field[crate::option::Option::Some(0)]", "Argument[0].Parameter[0]", "value", "dfc-generated"] - - ["lang:core", "::map", "Argument[self].Field[crate::option::Option::Some(0)]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[1]", "value", "dfc-generated"] + - ["lang:core", "::map", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::map", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:core", "::map", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::map_or", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::map_or", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::map_or", "Argument[self].Field[crate::option::Option::Some(0)]", "Argument[1].Parameter[0]", "value", "dfc-generated"] - - ["lang:core", "::map_or", "Argument[self].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::map_or_else", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::map_or_else", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::map_or_else", "Argument[self].Field[crate::option::Option::Some(0)]", "Argument[1].Parameter[0]", "value", "dfc-generated"] @@ -1141,20 +1010,44 @@ extensions: - ["lang:core", "::zip_with", "Argument[0].Field[crate::option::Option::Some(0)]", "Argument[1].Parameter[1]", "value", "dfc-generated"] - ["lang:core", "::zip_with", "Argument[1].ReturnValue", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::zip_with", "Argument[self].Field[crate::option::Option::Some(0)]", "Argument[1].Parameter[0]", "value", "dfc-generated"] + - ["lang:core", "::column", "Argument[self].Field[crate::panic::location::Location::col]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::file", "Argument[self].Field[crate::panic::location::Location::file]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::internal_constructor", "Argument[0]", "ReturnValue.Field[crate::panic::location::Location::file]", "value", "dfc-generated"] - ["lang:core", "::internal_constructor", "Argument[1]", "ReturnValue.Field[crate::panic::location::Location::line]", "value", "dfc-generated"] - ["lang:core", "::internal_constructor", "Argument[2]", "ReturnValue.Field[crate::panic::location::Location::col]", "value", "dfc-generated"] + - ["lang:core", "::line", "Argument[self].Field[crate::panic::location::Location::line]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::can_unwind", "Argument[self].Field[crate::panic::panic_info::PanicInfo::can_unwind]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::force_no_backtrace", "Argument[self].Field[crate::panic::panic_info::PanicInfo::force_no_backtrace]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::location", "Argument[self].Field[crate::panic::panic_info::PanicInfo::location]", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::message", "Argument[self].Field[crate::panic::panic_info::PanicInfo::message]", "ReturnValue.Field[crate::panic::panic_info::PanicMessage::message]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::panic::panic_info::PanicInfo::message]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::panic::panic_info::PanicInfo::location]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[2]", "ReturnValue.Field[crate::panic::panic_info::PanicInfo::can_unwind]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[3]", "ReturnValue.Field[crate::panic::panic_info::PanicInfo::force_no_backtrace]", "value", "dfc-generated"] + - ["lang:core", "::as_str", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::deref", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::deref", "Argument[self].Field[crate::panic::unwind_safe::AssertUnwindSafe(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::deref_mut", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::deref_mut", "Argument[self].Field[crate::panic::unwind_safe::AssertUnwindSafe(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::call_once", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::deref", "Argument[self].Field[crate::pin::Pin::__pointer].Reference", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::deref_mut", "Argument[self].Field[crate::pin::Pin::__pointer].Reference", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::as_mut", "Argument[self].Field[crate::pin::Pin::__pointer].Reference", "ReturnValue.Field[crate::pin::Pin::__pointer].Reference", "value", "dfc-generated"] + - ["lang:core", "::as_ref", "Argument[self].Field[crate::pin::Pin::__pointer].Reference", "ReturnValue.Field[crate::pin::Pin::__pointer].Reference", "value", "dfc-generated"] + - ["lang:core", "::get_mut", "Argument[self].Field[crate::pin::Pin::__pointer]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::get_ref", "Argument[self].Field[crate::pin::Pin::__pointer]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::get_unchecked_mut", "Argument[self].Field[crate::pin::Pin::__pointer]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::into_inner", "Argument[0].Field[crate::pin::Pin::__pointer]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::into_inner_unchecked", "Argument[0].Field[crate::pin::Pin::__pointer]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::into_ref", "Argument[self].Field[crate::pin::Pin::__pointer]", "ReturnValue.Field[crate::pin::Pin::__pointer]", "value", "dfc-generated"] - ["lang:core", "::map_unchecked", "Argument[0].ReturnValue", "ReturnValue.Field[crate::pin::Pin::__pointer]", "value", "dfc-generated"] + - ["lang:core", "::map_unchecked", "Argument[self].Field[crate::pin::Pin::__pointer].Reference", "Argument[0].Parameter[0].Reference", "value", "dfc-generated"] - ["lang:core", "::map_unchecked_mut", "Argument[0].ReturnValue", "ReturnValue.Field[crate::pin::Pin::__pointer]", "value", "dfc-generated"] + - ["lang:core", "::map_unchecked_mut", "Argument[self].Field[crate::pin::Pin::__pointer].Field[0]", "ReturnValue.Field[crate::pin::Pin::__pointer].Reference", "value", "dfc-generated"] + - ["lang:core", "::map_unchecked_mut", "Argument[self].Field[crate::pin::Pin::__pointer]", "Argument[0].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::pin::Pin::__pointer]", "value", "dfc-generated"] - ["lang:core", "::new_unchecked", "Argument[0]", "ReturnValue.Field[crate::pin::Pin::__pointer]", "value", "dfc-generated"] + - ["lang:core", "::set", "Argument[0]", "Argument[self].Field[crate::pin::Pin::__pointer].Reference", "value", "dfc-generated"] - ["lang:core", "::static_mut", "Argument[0]", "ReturnValue.Field[crate::pin::Pin::__pointer]", "value", "dfc-generated"] - ["lang:core", "::static_ref", "Argument[0]", "ReturnValue.Field[crate::pin::Pin::__pointer]", "value", "dfc-generated"] - ["lang:core", "::as_usize", "Argument[self]", "ReturnValue", "taint", "df-generated"] @@ -1170,16 +1063,65 @@ extensions: - ["lang:core", "::sub", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::ptr::unique::Unique::pointer]", "value", "dfc-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::as_non_null_ptr", "Argument[self].Field[crate::ptr::unique::Unique::pointer]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new_unchecked", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::from", "Argument[0].Field[crate::ops::range::Range::end]", "ReturnValue.Field[crate::range::Range::end]", "value", "dfc-generated"] + - ["lang:core", "::from", "Argument[0].Field[crate::ops::range::Range::start]", "ReturnValue.Field[crate::range::Range::start]", "value", "dfc-generated"] + - ["lang:core", "::into_bounds", "Argument[self].Field[crate::range::Range::end]", "ReturnValue.Field[1].Field[crate::ops::range::Bound::Excluded(0)]", "value", "dfc-generated"] + - ["lang:core", "::into_bounds", "Argument[self].Field[crate::range::Range::start]", "ReturnValue.Field[0].Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::end_bound", "Argument[self].Field[crate::range::Range::end]", "ReturnValue.Field[crate::ops::range::Bound::Excluded(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::end_bound", "Argument[self].Field[crate::range::Range::end]", "ReturnValue.Field[crate::ops::range::Bound::Excluded(0)]", "value", "dfc-generated"] + - ["lang:core", "::start_bound", "Argument[self].Field[crate::range::Range::start]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::start_bound", "Argument[self].Field[crate::range::Range::start]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::from", "Argument[0].Field[crate::ops::range::RangeFrom::start]", "ReturnValue.Field[crate::range::RangeFrom::start]", "value", "dfc-generated"] + - ["lang:core", "::into_bounds", "Argument[self].Field[crate::range::RangeFrom::start]", "ReturnValue.Field[0].Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::start_bound", "Argument[self].Field[crate::range::RangeFrom::start]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::start_bound", "Argument[self].Field[crate::range::RangeFrom::start]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::from", "Argument[0].Field[crate::ops::range::RangeInclusive::end]", "ReturnValue.Field[crate::range::RangeInclusive::end]", "value", "dfc-generated"] + - ["lang:core", "::from", "Argument[0].Field[crate::ops::range::RangeInclusive::start]", "ReturnValue.Field[crate::range::RangeInclusive::start]", "value", "dfc-generated"] + - ["lang:core", "::into_bounds", "Argument[self].Field[crate::range::RangeInclusive::end]", "ReturnValue.Field[1].Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::into_bounds", "Argument[self].Field[crate::range::RangeInclusive::start]", "ReturnValue.Field[0].Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::end_bound", "Argument[self].Field[crate::range::RangeInclusive::end]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::end_bound", "Argument[self].Field[crate::range::RangeInclusive::end]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::start_bound", "Argument[self].Field[crate::range::RangeInclusive::start]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::start_bound", "Argument[self].Field[crate::range::RangeInclusive::start]", "ReturnValue.Field[crate::ops::range::Bound::Included(0)]", "value", "dfc-generated"] + - ["lang:core", "::into_slice_range", "Argument[self].Field[crate::range::RangeInclusive::start]", "ReturnValue.Field[crate::range::Range::start]", "value", "dfc-generated"] + - ["lang:core", "::advance_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::max", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::min", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::nth", "Argument[self].Field[0].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::range::iter::IterRange(0)].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::remainder", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::nth", "Argument[self].Field[0].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::range::iter::IterRangeFrom(0)].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::remainder", "Argument[self].Field[0].Field[crate::ops::range::RangeFrom::start]", "ReturnValue.Field[crate::range::RangeFrom::start]", "value", "dfc-generated"] + - ["lang:core", "::remainder", "Argument[self].Field[crate::range::iter::IterRangeFrom(0)].Field[crate::ops::range::RangeFrom::start]", "ReturnValue.Field[crate::range::RangeFrom::start]", "value", "dfc-generated"] - ["lang:core", "::advance_back_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::advance_by", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::clone", "Argument[self].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[crate::result::Result::Ok(0)]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] + - ["lang:core", "::max", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::min", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::nth", "Argument[self].Field[0].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::range::iter::IterRangeInclusive(0)].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::remainder", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::result::IntoIter::inner].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::result::IntoIter::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::result::IntoIter::inner].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::result::IntoIter::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::result::Iter::inner]", "ReturnValue.Field[crate::result::Iter::inner]", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::result::Iter::inner].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::result::Iter::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::result::Iter::inner].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::result::Iter::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::result::IterMut::inner].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::result::IterMut::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::result::IterMut::inner].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::result::IterMut::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::branch", "Argument[self].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::ops::control_flow::ControlFlow::Break(0)].Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:core", "::branch", "Argument[self].Field[crate::result::Result::Ok(0)]", "ReturnValue.Field[crate::ops::control_flow::ControlFlow::Continue(0)]", "value", "dfc-generated"] - ["lang:core", "::from_output", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] - ["lang:core", "::and", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::and", "Argument[self].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - - ["lang:core", "::and_then", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::and_then", "Argument[self].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:core", "::and_then", "Argument[self].Field[crate::result::Result::Ok(0)]", "Argument[0].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::as_deref", "Argument[self].Reference.Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::result::Result::Err(0)].Reference", "value", "dfc-generated"] @@ -1189,6 +1131,7 @@ extensions: - ["lang:core", "::as_ref", "Argument[self].Reference.Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::result::Result::Err(0)].Reference", "value", "dfc-generated"] - ["lang:core", "::as_ref", "Argument[self].Reference.Field[crate::result::Result::Ok(0)]", "ReturnValue.Field[crate::result::Result::Ok(0)].Reference", "value", "dfc-generated"] - ["lang:core", "::cloned", "Argument[self].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:core", "::cloned", "Argument[self].Field[crate::result::Result::Ok(0)].Reference", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] - ["lang:core", "::cloned", "Argument[self].Field[crate::result::Result::Ok(0)]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] - ["lang:core", "::copied", "Argument[self].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:core", "::copied", "Argument[self].Field[crate::result::Result::Ok(0)].Reference", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] @@ -1209,6 +1152,7 @@ extensions: - ["lang:core", "::iter_mut", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::map", "Argument[0].ReturnValue", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] - ["lang:core", "::map_err", "Argument[0].ReturnValue", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:core", "::map_err", "Argument[self].Field[crate::result::Result::Err(0)].Field[crate::sync::mpmc::error::SendTimeoutError::Disconnected(0)]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::sync::mpsc::TrySendError::Disconnected(0)]", "value", "dfc-generated"] - ["lang:core", "::map_err", "Argument[self].Field[crate::result::Result::Err(0)]", "Argument[0].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::map_err", "Argument[self].Field[crate::result::Result::Ok(0)]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] - ["lang:core", "::map_or", "Argument[0]", "ReturnValue", "value", "dfc-generated"] @@ -1240,29 +1184,80 @@ extensions: - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::new", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::slice::iter::ArrayChunks::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::slice::iter::ArrayChunks::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::remainder", "Argument[self].Field[crate::slice::iter::ArrayChunks::rem]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::into_remainder", "Argument[self].Field[crate::slice::iter::ArrayChunksMut::rem]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::count", "Argument[self].Field[crate::slice::iter::ArrayWindows::num]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::last", "Argument[self].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::size_hint", "Argument[self].Field[crate::slice::iter::ArrayWindows::num]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:core", "::size_hint", "Argument[self].Field[crate::slice::iter::ArrayWindows::num]", "ReturnValue.Field[1].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::ChunkBy::slice]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::ChunkBy::predicate]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::ChunkByMut::slice]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::ChunkByMut::predicate]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::Chunks::chunk_size]", "ReturnValue.Field[crate::slice::iter::Chunks::chunk_size]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::Chunks::v]", "ReturnValue.Field[crate::slice::iter::Chunks::v]", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::slice::iter::Chunks::v].Element", "Argument[self].Field[crate::slice::iter::Chunks::v].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::slice::iter::Chunks::v].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::last", "Argument[self].Field[crate::slice::iter::Chunks::v].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::slice::iter::Chunks::v].Element", "Argument[self].Field[crate::slice::iter::Chunks::v].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::slice::iter::Chunks::v].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::size_hint", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::Chunks::v]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::Chunks::chunk_size]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::ChunksExact::chunk_size]", "ReturnValue.Field[crate::slice::iter::ChunksExact::chunk_size]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::ChunksExact::rem]", "ReturnValue.Field[crate::slice::iter::ChunksExact::rem]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::ChunksExact::v]", "ReturnValue.Field[crate::slice::iter::ChunksExact::v]", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::slice::iter::ChunksExact::v].Element", "Argument[self].Field[crate::slice::iter::ChunksExact::v].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::slice::iter::ChunksExact::v].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::size_hint", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::ChunksExact::chunk_size]", "value", "dfc-generated"] + - ["lang:core", "::remainder", "Argument[self].Field[crate::slice::iter::ChunksExact::rem]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::size_hint", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_remainder", "Argument[self].Field[crate::slice::iter::ChunksExactMut::rem]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::ChunksExactMut::chunk_size]", "value", "dfc-generated"] + - ["lang:core", "::size_hint", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::ChunksMut::v]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::ChunksMut::chunk_size]", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::slice::iter::GenericSplitN::iter].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::size_hint", "Argument[self].Field[crate::slice::iter::GenericSplitN::count]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::Iter::_marker]", "ReturnValue.Field[crate::slice::iter::Iter::_marker]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::Iter::end_or_len]", "ReturnValue.Field[crate::slice::iter::Iter::end_or_len]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::Iter::ptr]", "ReturnValue.Field[crate::slice::iter::Iter::ptr]", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "Argument[1].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::RChunks::chunk_size]", "ReturnValue.Field[crate::slice::iter::RChunks::chunk_size]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::RChunks::v]", "ReturnValue.Field[crate::slice::iter::RChunks::v]", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::slice::iter::RChunks::v].Element", "Argument[self].Field[crate::slice::iter::RChunks::v].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::slice::iter::RChunks::v].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::last", "Argument[self].Field[crate::slice::iter::RChunks::v].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::slice::iter::RChunks::v].Element", "Argument[self].Field[crate::slice::iter::RChunks::v].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::slice::iter::RChunks::v].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::size_hint", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::RChunks::v]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::RChunks::chunk_size]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::RChunksExact::chunk_size]", "ReturnValue.Field[crate::slice::iter::RChunksExact::chunk_size]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::RChunksExact::rem]", "ReturnValue.Field[crate::slice::iter::RChunksExact::rem]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::RChunksExact::v]", "ReturnValue.Field[crate::slice::iter::RChunksExact::v]", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::slice::iter::RChunksExact::v].Element", "Argument[self].Field[crate::slice::iter::RChunksExact::v].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::slice::iter::RChunksExact::v].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::size_hint", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::RChunksExact::chunk_size]", "value", "dfc-generated"] + - ["lang:core", "::remainder", "Argument[self].Field[crate::slice::iter::RChunksExact::rem]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::size_hint", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_remainder", "Argument[self].Field[crate::slice::iter::RChunksExactMut::rem]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::RChunksExactMut::chunk_size]", "value", "dfc-generated"] + - ["lang:core", "::size_hint", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::RChunksMut::v]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::RChunksMut::chunk_size]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::RSplit::inner].Reference", "ReturnValue.Field[crate::slice::iter::RSplit::inner]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::RSplit::inner]", "ReturnValue.Field[crate::slice::iter::RSplit::inner]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::RSplit::inner].Field[crate::slice::iter::Split::v]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::RSplit::inner].Field[crate::slice::iter::Split::pred]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::RSplitMut::inner].Field[crate::slice::iter::SplitMut::v]", "value", "dfc-generated"] @@ -1271,27 +1266,52 @@ extensions: - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::RSplitN::inner].Field[crate::slice::iter::GenericSplitN::count]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::RSplitNMut::inner].Field[crate::slice::iter::GenericSplitN::iter]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::RSplitNMut::inner].Field[crate::slice::iter::GenericSplitN::count]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::finish", "Argument[self].Field[crate::slice::iter::Split::v]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::as_slice", "Argument[self].Field[crate::slice::iter::Split::v]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::Split::v]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::Split::pred]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::slice::iter::SplitInclusive::v].Element", "Argument[self].Field[crate::slice::iter::SplitInclusive::v].Reference", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::slice::iter::SplitInclusive::v].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::slice::iter::SplitInclusive::v].Element", "Argument[self].Field[crate::slice::iter::SplitInclusive::v].Reference", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::slice::iter::SplitInclusive::v].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::SplitInclusive::v]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::SplitInclusive::pred]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::SplitInclusiveMut::v]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::SplitInclusiveMut::pred]", "value", "dfc-generated"] + - ["lang:core", "::finish", "Argument[self].Field[crate::slice::iter::SplitMut::v]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::SplitMut::v]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::SplitMut::pred]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::SplitN::inner].Field[crate::slice::iter::GenericSplitN::iter]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::SplitN::inner].Field[crate::slice::iter::GenericSplitN::count]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::SplitNMut::inner].Field[crate::slice::iter::GenericSplitN::iter]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::SplitNMut::inner].Field[crate::slice::iter::GenericSplitN::count]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::Windows::size]", "ReturnValue.Field[crate::slice::iter::Windows::size]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::slice::iter::Windows::v]", "ReturnValue.Field[crate::slice::iter::Windows::v]", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::slice::iter::Windows::v].Element", "Argument[self].Field[crate::slice::iter::Windows::v].Reference", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self].Field[crate::slice::iter::Windows::v].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::slice::iter::Windows::v].Element", "Argument[self].Field[crate::slice::iter::Windows::v].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth_back", "Argument[self].Field[crate::slice::iter::Windows::v].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::last", "Argument[self].Field[crate::slice::iter::Windows::v].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::slice::iter::Windows::v].Element", "Argument[self].Field[crate::slice::iter::Windows::v].Reference", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::slice::iter::Windows::v].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::slice::iter::Windows::v].Element", "Argument[self].Field[crate::slice::iter::Windows::v].Reference", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::slice::iter::Windows::v].Element", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::slice::iter::Windows::v]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::slice::iter::Windows::size]", "value", "dfc-generated"] - - ["lang:core", "::call", "Argument[0].Field[0]", "ReturnValue.Field[crate::char::EscapeDebug(0)].Field[crate::char::EscapeDebugInner::Char(0)]", "value", "dfc-generated"] - - ["lang:core", "::call_mut", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::call_once", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::call", "Argument[0].Field[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::call_mut", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::call_once", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::error_len", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::valid_up_to", "Argument[self].Field[crate::str::error::Utf8Error::valid_up_to]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[0].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::nth", "Argument[self].Field[crate::str::iter::Bytes(0)].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::last", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::str::iter::CharIndices::front_offset]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[0]", "value", "dfc-generated"] + - ["lang:core", "::offset", "Argument[self].Field[crate::str::iter::CharIndices::front_offset]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self].Field[crate::str::iter::EncodeUtf16::extra]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] @@ -1299,105 +1319,121 @@ extensions: - ["lang:core", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::try_fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0].Field[0]", "ReturnValue.Field[crate::str::iter::MatchIndices(0)].Field[crate::str::iter::MatchIndicesInternal(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::str::iter::MatchIndices(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::str::iter::MatchIndicesInternal(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0].Field[0]", "ReturnValue.Field[crate::str::iter::Matches(0)].Field[crate::str::iter::MatchesInternal(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::str::iter::Matches(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::str::iter::MatchesInternal(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0].Field[0]", "ReturnValue.Field[crate::str::iter::RMatchIndices(0)].Field[crate::str::iter::MatchIndicesInternal(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::str::iter::RMatchIndices(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0].Field[0]", "ReturnValue.Field[crate::str::iter::RMatches(0)].Field[crate::str::iter::MatchesInternal(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::str::iter::RMatches(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::str::iter::RSplit(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::str::iter::RSplitN(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::str::iter::RSplitTerminator(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::str::iter::Split(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::str::iter::SplitInclusive(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::str::iter::SplitN(0)]", "value", "dfc-generated"] - - ["lang:core", "::clone", "Argument[self].Field[0]", "ReturnValue.Field[crate::str::iter::SplitTerminator(0)]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::str::iter::SplitInternal::matcher].Reference", "ReturnValue.Field[crate::str::iter::SplitInternal::matcher]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::str::iter::SplitInternal::matcher]", "ReturnValue.Field[crate::str::iter::SplitInternal::matcher]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::str::iter::SplitNInternal::iter].Reference", "ReturnValue.Field[crate::str::iter::SplitNInternal::iter]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self].Field[crate::str::iter::SplitNInternal::iter]", "ReturnValue.Field[crate::str::iter::SplitNInternal::iter]", "value", "dfc-generated"] + - ["lang:core", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::invalid", "Argument[self].Field[crate::str::lossy::Utf8Chunk::invalid]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::valid", "Argument[self].Field[crate::str::lossy::Utf8Chunk::valid]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::debug", "Argument[self].Field[crate::str::lossy::Utf8Chunks::source]", "ReturnValue.Field[crate::str::lossy::Debug(0)]", "value", "dfc-generated"] + - ["lang:core", "::next_back", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::next_match_back", "Argument[self].Field[crate::str::pattern::CharSearcher::finger]", "Argument[self].Field[crate::str::pattern::CharSearcher::finger_back]", "value", "dfc-generated"] + - ["lang:core", "::next_match_back", "Argument[self].Field[crate::str::pattern::CharSearcher::finger_back]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[0]", "value", "dfc-generated"] + - ["lang:core", "::haystack", "Argument[self].Field[crate::str::pattern::CharSearcher::haystack]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::next", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::next_match", "Argument[self].Field[crate::str::pattern::CharSearcher::finger]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[1]", "value", "dfc-generated"] + - ["lang:core", "::next_match", "Argument[self].Field[crate::str::pattern::CharSearcher::finger_back]", "Argument[self].Field[crate::str::pattern::CharSearcher::finger]", "value", "dfc-generated"] - ["lang:core", "::matching", "Argument[0]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[0]", "value", "dfc-generated"] - ["lang:core", "::matching", "Argument[1]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[1]", "value", "dfc-generated"] - ["lang:core", "::into_searcher", "Argument[0]", "ReturnValue.Field[crate::str::pattern::MultiCharEqSearcher::haystack]", "value", "dfc-generated"] - ["lang:core", "::into_searcher", "Argument[self].Field[0]", "ReturnValue.Field[crate::str::pattern::MultiCharEqSearcher::char_eq]", "value", "dfc-generated"] + - ["lang:core", "::into_searcher", "Argument[self].Field[crate::str::pattern::MultiCharEqPattern(0)]", "ReturnValue.Field[crate::str::pattern::MultiCharEqSearcher::char_eq]", "value", "dfc-generated"] + - ["lang:core", "::haystack", "Argument[self].Field[crate::str::pattern::MultiCharEqSearcher::haystack]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::matching", "Argument[0]", "ReturnValue.Field[crate::str::pattern::SearchStep::Match(0)]", "value", "dfc-generated"] - ["lang:core", "::matching", "Argument[1]", "ReturnValue.Field[crate::str::pattern::SearchStep::Match(1)]", "value", "dfc-generated"] - ["lang:core", "::rejecting", "Argument[0]", "ReturnValue.Field[crate::str::pattern::SearchStep::Reject(0)]", "value", "dfc-generated"] - ["lang:core", "::rejecting", "Argument[1]", "ReturnValue.Field[crate::str::pattern::SearchStep::Reject(1)]", "value", "dfc-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::haystack", "Argument[self].Field[crate::str::pattern::StrSearcher::haystack]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicI128::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::sync::atomic::AtomicI128::v].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicI128::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicI16::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::sync::atomic::AtomicI16::v].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicI16::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicI32::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::sync::atomic::AtomicI32::v].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicI32::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicI64::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::sync::atomic::AtomicI64::v].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicI64::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicI8::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::sync::atomic::AtomicI8::v].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicI8::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicIsize::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::sync::atomic::AtomicIsize::v].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicIsize::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicPtr::p].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::sync::atomic::AtomicPtr::p].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicPtr::p].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicU128::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::sync::atomic::AtomicU128::v].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicU128::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicU16::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::sync::atomic::AtomicU16::v].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicU16::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicU32::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::sync::atomic::AtomicU32::v].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicU32::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicU64::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::sync::atomic::AtomicU64::v].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicU64::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicU8::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::sync::atomic::AtomicU8::v].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicU8::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicUsize::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::get_mut_slice", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::sync::atomic::AtomicUsize::v].Field[crate::cell::UnsafeCell::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::atomic::AtomicUsize::v].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::exclusive::Exclusive::inner]", "value", "dfc-generated"] - ["lang:core", "::from_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::get_mut", "Argument[self].Field[crate::sync::exclusive::Exclusive::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::into_inner", "Argument[self].Field[crate::sync::exclusive::Exclusive::inner]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::exclusive::Exclusive::inner]", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue.Field[crate::task::poll::Poll::Ready(0)]", "value", "dfc-generated"] + - ["lang:core", "::branch", "Argument[self].Field[crate::task::poll::Poll::Ready(0)].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::ops::control_flow::ControlFlow::Break(0)].Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:core", "::branch", "Argument[self].Field[crate::task::poll::Poll::Ready(0)].Field[crate::result::Result::Ok(0)]", "ReturnValue.Field[crate::ops::control_flow::ControlFlow::Continue(0)].Field[crate::task::poll::Poll::Ready(0)]", "value", "dfc-generated"] + - ["lang:core", "::async_gen_ready", "Argument[0]", "ReturnValue.Field[crate::task::poll::Poll::Ready(0)].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:core", "::map", "Argument[0].ReturnValue", "ReturnValue.Field[crate::task::poll::Poll::Ready(0)]", "value", "dfc-generated"] - ["lang:core", "::map", "Argument[self].Field[crate::task::poll::Poll::Ready(0)]", "Argument[0].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::map_err", "Argument[0].ReturnValue", "ReturnValue.Field[crate::task::poll::Poll::Ready(0)].Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] @@ -1407,33 +1443,58 @@ extensions: - ["lang:core", "::map_ok", "Argument[self].Field[crate::task::poll::Poll::Ready(0)].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::task::poll::Poll::Ready(0)].Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:core", "::map_ok", "Argument[self].Field[crate::task::poll::Poll::Ready(0)].Field[crate::result::Result::Ok(0)]", "Argument[0].Parameter[0]", "value", "dfc-generated"] - ["lang:core", "::from_waker", "Argument[0]", "ReturnValue.Field[crate::task::wake::Context::waker]", "value", "dfc-generated"] + - ["lang:core", "::local_waker", "Argument[self].Field[crate::task::wake::Context::local_waker]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::waker", "Argument[self].Field[crate::task::wake::Context::waker]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:core", "::build", "Argument[self].Field[crate::task::wake::ContextBuilder::ext]", "ReturnValue.Field[crate::task::wake::Context::ext].Field[crate::panic::unwind_safe::AssertUnwindSafe(0)]", "value", "dfc-generated"] - ["lang:core", "::build", "Argument[self].Field[crate::task::wake::ContextBuilder::local_waker]", "ReturnValue.Field[crate::task::wake::Context::local_waker]", "value", "dfc-generated"] - ["lang:core", "::build", "Argument[self].Field[crate::task::wake::ContextBuilder::waker]", "ReturnValue.Field[crate::task::wake::Context::waker]", "value", "dfc-generated"] - ["lang:core", "::ext", "Argument[0]", "ReturnValue.Field[crate::task::wake::ContextBuilder::ext].Field[crate::task::wake::ExtData::Some(0)]", "value", "dfc-generated"] + - ["lang:core", "::from", "Argument[0].Field[crate::task::wake::Context::local_waker]", "ReturnValue.Field[crate::task::wake::ContextBuilder::local_waker]", "value", "dfc-generated"] + - ["lang:core", "::from", "Argument[0].Field[crate::task::wake::Context::waker]", "ReturnValue.Field[crate::task::wake::ContextBuilder::waker]", "value", "dfc-generated"] - ["lang:core", "::from_waker", "Argument[0]", "ReturnValue.Field[crate::task::wake::ContextBuilder::waker]", "value", "dfc-generated"] - ["lang:core", "::local_waker", "Argument[0]", "ReturnValue.Field[crate::task::wake::ContextBuilder::local_waker]", "value", "dfc-generated"] - ["lang:core", "::waker", "Argument[0]", "ReturnValue.Field[crate::task::wake::ContextBuilder::waker]", "value", "dfc-generated"] + - ["lang:core", "::clone_from", "Argument[0].Reference", "Argument[self].Reference", "value", "dfc-generated"] - ["lang:core", "::clone_from", "Argument[0]", "Argument[self].Reference", "value", "dfc-generated"] + - ["lang:core", "::data", "Argument[self].Field[crate::task::wake::LocalWaker::waker].Field[crate::task::wake::RawWaker::data]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::from_raw", "Argument[0]", "ReturnValue.Field[crate::task::wake::LocalWaker::waker]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::task::wake::LocalWaker::waker].Field[crate::task::wake::RawWaker::data]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::task::wake::LocalWaker::waker].Field[crate::task::wake::RawWaker::vtable]", "value", "dfc-generated"] + - ["lang:core", "::vtable", "Argument[self].Field[crate::task::wake::LocalWaker::waker].Field[crate::task::wake::RawWaker::vtable]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::task::wake::RawWaker::data]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::task::wake::RawWaker::vtable]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::task::wake::RawWakerVTable::clone]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::task::wake::RawWakerVTable::wake]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[2]", "ReturnValue.Field[crate::task::wake::RawWakerVTable::wake_by_ref]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[3]", "ReturnValue.Field[crate::task::wake::RawWakerVTable::drop]", "value", "dfc-generated"] + - ["lang:core", "::clone_from", "Argument[0].Reference", "Argument[self].Reference", "value", "dfc-generated"] - ["lang:core", "::clone_from", "Argument[0]", "Argument[self].Reference", "value", "dfc-generated"] + - ["lang:core", "::data", "Argument[self].Field[crate::task::wake::Waker::waker].Field[crate::task::wake::RawWaker::data]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::from_raw", "Argument[0]", "ReturnValue.Field[crate::task::wake::Waker::waker]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::task::wake::Waker::waker].Field[crate::task::wake::RawWaker::data]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::task::wake::Waker::waker].Field[crate::task::wake::RawWaker::vtable]", "value", "dfc-generated"] + - ["lang:core", "::vtable", "Argument[self].Field[crate::task::wake::Waker::waker].Field[crate::task::wake::RawWaker::vtable]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::add_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::div", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::mul_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:core", "::sub_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] + - ["lang:core", "::as_micros", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::as_millis", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::as_millis_f32", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::as_millis_f64", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::as_nanos", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::as_secs", "Argument[self].Field[crate::time::Duration::secs]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::as_secs_f32", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::as_secs_f64", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_div", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::checked_div", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::div_duration_f32", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::div_duration_f32", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::div_duration_f64", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::div_duration_f64", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_days", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_hours", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_micros", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -1445,9 +1506,7 @@ extensions: - ["lang:core", "::new", "Argument[0]", "ReturnValue.Field[crate::time::Duration::secs]", "value", "dfc-generated"] - ["lang:core", "::new", "Argument[1]", "ReturnValue.Field[crate::time::Duration::nanos].Field[crate::num::niche_types::Nanoseconds(0)]", "value", "dfc-generated"] - ["lang:core", "::saturating_mul", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::downcast_mut", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::downcast_mut_unchecked", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::downcast_ref", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::downcast_ref_unchecked", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::downcast_mut", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::downcast_ref", "Argument[self]", "ReturnValue", "taint", "df-generated"] @@ -1593,13 +1652,8 @@ extensions: - ["lang:core", "::abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::cast_unsigned", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_abs", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_ilog10", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_next_multiple_of", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -1611,35 +1665,17 @@ extensions: - ["lang:core", "::midpoint", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::midpoint", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::next_multiple_of", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::overflowing_abs", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_div", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_div_euclid", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::overflowing_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::overflowing_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::overflowing_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::overflowing_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::pow", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::saturating_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::saturating_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::strict_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_div_euclid", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::unsigned_abs", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::wrapping_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_div_euclid", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::try_from", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -1678,13 +1714,8 @@ extensions: - ["lang:core", "::abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::cast_unsigned", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_abs", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_ilog10", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_next_multiple_of", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -1696,35 +1727,17 @@ extensions: - ["lang:core", "::midpoint", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::midpoint", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::next_multiple_of", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::overflowing_abs", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_div", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_div_euclid", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::overflowing_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::overflowing_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::overflowing_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::overflowing_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::pow", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::saturating_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::saturating_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::strict_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_div_euclid", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::unsigned_abs", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::wrapping_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_div_euclid", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::try_from", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -1763,13 +1776,8 @@ extensions: - ["lang:core", "::abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::cast_unsigned", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_abs", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_ilog10", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_next_multiple_of", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -1781,35 +1789,17 @@ extensions: - ["lang:core", "::midpoint", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::midpoint", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::next_multiple_of", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::overflowing_abs", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_div", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_div_euclid", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::overflowing_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::overflowing_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::overflowing_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::overflowing_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::pow", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::saturating_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::saturating_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::strict_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_div_euclid", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::unsigned_abs", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::wrapping_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_div_euclid", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::try_from", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -1848,13 +1838,8 @@ extensions: - ["lang:core", "::abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::cast_unsigned", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_abs", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_ilog10", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_next_multiple_of", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -1866,35 +1851,17 @@ extensions: - ["lang:core", "::midpoint", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::midpoint", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::next_multiple_of", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::overflowing_abs", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_div", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_div_euclid", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::overflowing_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::overflowing_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::overflowing_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::overflowing_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::pow", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::saturating_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::saturating_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::strict_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_div_euclid", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::unsigned_abs", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::wrapping_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_div_euclid", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::try_from", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -1933,13 +1900,8 @@ extensions: - ["lang:core", "::abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::cast_unsigned", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_abs", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_ilog10", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_next_multiple_of", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -1951,35 +1913,17 @@ extensions: - ["lang:core", "::midpoint", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::midpoint", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::next_multiple_of", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::overflowing_abs", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_div", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_div_euclid", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::overflowing_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::overflowing_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::overflowing_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::overflowing_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::pow", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::saturating_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::saturating_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::strict_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_div_euclid", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::unsigned_abs", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::wrapping_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_div_euclid", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::try_from", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -2018,13 +1962,8 @@ extensions: - ["lang:core", "::abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::cast_unsigned", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_abs", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_ilog10", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_next_multiple_of", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -2036,44 +1975,27 @@ extensions: - ["lang:core", "::midpoint", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::midpoint", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::next_multiple_of", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::overflowing_abs", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_div", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_div_euclid", "Argument[self]", "ReturnValue.Field[0]", "value", "dfc-generated"] - ["lang:core", "::overflowing_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::overflowing_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::overflowing_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::overflowing_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::overflowing_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::pow", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::saturating_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::saturating_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::strict_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_div_euclid", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::strict_neg", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::strict_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::unsigned_abs", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::wrapping_abs", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_div", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_div_euclid", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::wrapping_rem", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::wrapping_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::as_mut", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "::as_ref", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::as_ref", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::as_bytes_mut", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::as_mut_ptr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::as_ptr", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::as_str", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "::ceil_char_boundary", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_utf8_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::from_utf8_unchecked_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::splitn", "Argument[0]", "ReturnValue.Field[crate::str::iter::SplitN(0)].Field[crate::str::iter::SplitNInternal::count]", "value", "dfc-generated"] - ["lang:core", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "::from", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::try_from", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -2109,11 +2031,7 @@ extensions: - ["lang:core", "::abs_diff", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::abs_diff", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::cast_signed", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_next_multiple_of", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -2136,8 +2054,6 @@ extensions: - ["lang:core", "::pow", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::saturating_div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::saturating_div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -2202,11 +2118,7 @@ extensions: - ["lang:core", "::abs_diff", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::abs_diff", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::cast_signed", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_next_multiple_of", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -2229,8 +2141,6 @@ extensions: - ["lang:core", "::pow", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::saturating_div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::saturating_div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -2295,11 +2205,7 @@ extensions: - ["lang:core", "::abs_diff", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::abs_diff", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::cast_signed", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_next_multiple_of", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -2322,8 +2228,6 @@ extensions: - ["lang:core", "::pow", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::saturating_div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::saturating_div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -2381,11 +2285,7 @@ extensions: - ["lang:core", "::abs_diff", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::abs_diff", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::cast_signed", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_next_multiple_of", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -2408,8 +2308,6 @@ extensions: - ["lang:core", "::pow", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::saturating_div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::saturating_div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -2475,11 +2373,7 @@ extensions: - ["lang:core", "::abs_diff", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::ascii_change_case_unchecked", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::cast_signed", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_next_multiple_of", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -2502,8 +2396,6 @@ extensions: - ["lang:core", "::pow", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::saturating_div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::saturating_div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -2565,11 +2457,7 @@ extensions: - ["lang:core", "::abs_diff", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::abs_diff", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::cast_signed", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_div_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::checked_next_multiple_of", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::checked_rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_ceil", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -2592,8 +2480,7 @@ extensions: - ["lang:core", "::pow", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::saturating_div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "::saturating_div", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "::repeat_u16", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "::strict_div_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] @@ -2672,13 +2559,13 @@ extensions: - ["lang:core", "crate::mem::take", "Argument[0].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "crate::mem::transmute_copy", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "crate::num::flt2dec::estimator::estimate_scaling_factor", "Argument[1]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "crate::num::flt2dec::strategy::dragon::format_exact", "Argument[1]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "crate::num::flt2dec::strategy::dragon::format_shortest", "Argument[1]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "crate::num::flt2dec::strategy::dragon::format_exact", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "crate::num::flt2dec::strategy::dragon::format_shortest", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "crate::num::flt2dec::strategy::dragon::mul_pow10", "Argument[0].Field[crate::num::bignum::Big32x40::base].Element", "ReturnValue.Field[crate::num::bignum::Big32x40::base].Element", "value", "dfc-generated"] + - ["lang:core", "crate::num::flt2dec::strategy::dragon::mul_pow10", "Argument[0].Field[crate::num::bignum::Big32x40::size]", "ReturnValue.Field[crate::num::bignum::Big32x40::size]", "value", "dfc-generated"] - ["lang:core", "crate::num::flt2dec::strategy::dragon::mul_pow10", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "crate::num::flt2dec::strategy::grisu::format_exact", "Argument[1]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "crate::num::flt2dec::strategy::grisu::format_exact_opt", "Argument[1]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "crate::num::flt2dec::strategy::grisu::format_shortest", "Argument[1]", "ReturnValue", "taint", "df-generated"] - - ["lang:core", "crate::num::flt2dec::strategy::grisu::format_shortest_opt", "Argument[1]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "crate::num::flt2dec::strategy::grisu::format_exact", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "crate::num::flt2dec::strategy::grisu::format_shortest", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "crate::num::flt2dec::to_exact_exp_str", "Argument[5].Element", "Argument[0].Parameter[1].Reference", "value", "dfc-generated"] - ["lang:core", "crate::num::flt2dec::to_exact_fixed_str", "Argument[4].Element", "Argument[0].Parameter[1].Reference", "value", "dfc-generated"] - ["lang:core", "crate::num::flt2dec::to_shortest_exp_str", "Argument[5]", "Argument[0].Parameter[1]", "value", "dfc-generated"] @@ -2698,13 +2585,16 @@ extensions: - ["lang:core", "crate::ptr::from_mut", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "crate::ptr::from_ref", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:core", "crate::ptr::replace", "Argument[0].Reference", "ReturnValue", "value", "dfc-generated"] + - ["lang:core", "crate::ptr::replace", "Argument[1]", "Argument[0].Reference", "value", "dfc-generated"] - ["lang:core", "crate::ptr::with_exposed_provenance", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "crate::ptr::with_exposed_provenance_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:core", "crate::slice::index::range", "Argument[1].Field[crate::ops::range::RangeTo::end]", "ReturnValue.Field[crate::ops::range::Range::end]", "value", "dfc-generated"] + - ["lang:core", "crate::slice::index::try_range", "Argument[1].Field[crate::ops::range::RangeTo::end]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::ops::range::Range::end]", "value", "dfc-generated"] - ["lang:core", "crate::slice::sort::shared::find_existing_run", "Argument[1].ReturnValue", "ReturnValue.Field[1]", "value", "dfc-generated"] - - ["lang:core", "crate::slice::sort::shared::pivot::choose_pivot", "Argument[0]", "Argument[1]", "taint", "df-generated"] - ["lang:core", "crate::slice::sort::shared::smallsort::sort4_stable", "Argument[0].Reference", "Argument[2].Parameter[1].Reference", "value", "dfc-generated"] + - ["lang:core", "crate::slice::sort::stable::drift::sort", "Argument[0].Element", "Argument[3].Parameter[1].Reference", "value", "dfc-generated"] + - ["lang:core", "crate::slice::sort::stable::quicksort::quicksort", "Argument[0].Element", "Argument[4].Parameter[1].Reference", "value", "dfc-generated"] + - ["lang:core", "crate::slice::sort::stable::sort", "Argument[0].Element", "Argument[1].Parameter[1].Reference", "value", "dfc-generated"] - ["lang:core", "crate::str::converts::from_utf8_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "crate::str::converts::from_utf8_unchecked_mut", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:core", "crate::str::validations::next_code_point", "Argument[0].Element", "ReturnValue", "value", "dfc-generated"] - - ["lang:core", "crate::unicode::unicode_data::conversions::to_lower", "Argument[0]", "ReturnValue.Element", "value", "dfc-generated"] - - ["lang:core", "crate::unicode::unicode_data::conversions::to_upper", "Argument[0]", "ReturnValue.Element", "value", "dfc-generated"] diff --git a/rust/ql/lib/ext/generated/rust/lang-proc_macro.model.yml b/rust/ql/lib/ext/generated/rust/lang-proc_macro.model.yml index 5ff016dcf3e6..8f45f5773b43 100644 --- a/rust/ql/lib/ext/generated/rust/lang-proc_macro.model.yml +++ b/rust/ql/lib/ext/generated/rust/lang-proc_macro.model.yml @@ -8,6 +8,14 @@ extensions: - ["lang:proc_macro", "<&[u8] as crate::bridge::Unmark>::unmark", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "<&[u8] as crate::bridge::rpc::DecodeMut>::decode", "Argument[0].Element", "Argument[0].Reference.Reference", "value", "dfc-generated"] - ["lang:proc_macro", "<&[u8] as crate::bridge::rpc::DecodeMut>::decode", "Argument[0].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:proc_macro", "<&crate::bridge::Marked as crate::bridge::Unmark>::unmark", "Argument[self].Field[crate::bridge::Marked::value]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:proc_macro", "<&crate::bridge::Marked as crate::bridge::rpc::Decode>::decode", "Argument[1].Field[crate::bridge::server::HandleStore::FreeFunctions].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:proc_macro", "<&crate::bridge::Marked as crate::bridge::rpc::Decode>::decode", "Argument[1].Field[crate::bridge::server::HandleStore::SourceFile].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:proc_macro", "<&crate::bridge::Marked as crate::bridge::rpc::Decode>::decode", "Argument[1].Field[crate::bridge::server::HandleStore::TokenStream].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:proc_macro", "<&mut crate::bridge::Marked as crate::bridge::Unmark>::unmark", "Argument[self].Field[crate::bridge::Marked::value]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:proc_macro", "<&mut crate::bridge::Marked as crate::bridge::rpc::DecodeMut>::decode", "Argument[1].Field[crate::bridge::server::HandleStore::FreeFunctions].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:proc_macro", "<&mut crate::bridge::Marked as crate::bridge::rpc::DecodeMut>::decode", "Argument[1].Field[crate::bridge::server::HandleStore::SourceFile].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:proc_macro", "<&mut crate::bridge::Marked as crate::bridge::rpc::DecodeMut>::decode", "Argument[1].Field[crate::bridge::server::HandleStore::TokenStream].Element", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:proc_macro", "<&str as crate::bridge::Mark>::mark", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "<&str as crate::bridge::Unmark>::unmark", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::mark", "Argument[0]", "ReturnValue", "value", "dfc-generated"] @@ -16,11 +24,28 @@ extensions: - ["lang:proc_macro", "::unmark", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::mark", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::unmark", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:proc_macro", "::delimiter", "Argument[self].Field[0].Field[crate::bridge::Group::delimiter]", "ReturnValue", "value", "dfc-generated"] + - ["lang:proc_macro", "::delimiter", "Argument[self].Field[crate::Group(0)].Field[crate::bridge::Group::delimiter]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::new", "Argument[0]", "ReturnValue.Field[crate::Group(0)].Field[crate::bridge::Group::delimiter]", "value", "dfc-generated"] - ["lang:proc_macro", "::new", "Argument[1].Field[0]", "ReturnValue.Field[crate::Group(0)].Field[crate::bridge::Group::stream]", "value", "dfc-generated"] + - ["lang:proc_macro", "::new", "Argument[1].Field[crate::TokenStream(0)]", "ReturnValue.Field[crate::Group(0)].Field[crate::bridge::Group::stream]", "value", "dfc-generated"] + - ["lang:proc_macro", "::stream", "Argument[self].Field[0].Field[crate::bridge::Group::stream]", "ReturnValue.Field[crate::TokenStream(0)]", "value", "dfc-generated"] + - ["lang:proc_macro", "::stream", "Argument[self].Field[crate::Group(0)].Field[crate::bridge::Group::stream]", "ReturnValue.Field[crate::TokenStream(0)]", "value", "dfc-generated"] - ["lang:proc_macro", "::new", "Argument[1].Field[0]", "ReturnValue.Field[crate::Ident(0)].Field[crate::bridge::Ident::span]", "value", "dfc-generated"] + - ["lang:proc_macro", "::new", "Argument[1].Field[crate::Span(0)]", "ReturnValue.Field[crate::Ident(0)].Field[crate::bridge::Ident::span]", "value", "dfc-generated"] - ["lang:proc_macro", "::new_raw", "Argument[1].Field[0]", "ReturnValue.Field[crate::Ident(0)].Field[crate::bridge::Ident::span]", "value", "dfc-generated"] + - ["lang:proc_macro", "::new_raw", "Argument[1].Field[crate::Span(0)]", "ReturnValue.Field[crate::Ident(0)].Field[crate::bridge::Ident::span]", "value", "dfc-generated"] + - ["lang:proc_macro", "::set_span", "Argument[0]", "Argument[self]", "taint", "df-generated"] + - ["lang:proc_macro", "::span", "Argument[self].Field[0].Field[crate::bridge::Ident::span]", "ReturnValue.Field[crate::Span(0)]", "value", "dfc-generated"] + - ["lang:proc_macro", "::span", "Argument[self].Field[crate::Ident(0)].Field[crate::bridge::Ident::span]", "ReturnValue.Field[crate::Span(0)]", "value", "dfc-generated"] + - ["lang:proc_macro", "::set_span", "Argument[0]", "Argument[self]", "taint", "df-generated"] + - ["lang:proc_macro", "::span", "Argument[self].Field[0].Field[crate::bridge::Literal::span]", "ReturnValue.Field[crate::Span(0)]", "value", "dfc-generated"] + - ["lang:proc_macro", "::span", "Argument[self].Field[crate::Literal(0)].Field[crate::bridge::Literal::span]", "ReturnValue.Field[crate::Span(0)]", "value", "dfc-generated"] + - ["lang:proc_macro", "::as_char", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:proc_macro", "::new", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:proc_macro", "::set_span", "Argument[0]", "Argument[self]", "taint", "df-generated"] + - ["lang:proc_macro", "::span", "Argument[self].Field[0].Field[crate::bridge::Punct::span]", "ReturnValue.Field[crate::Span(0)]", "value", "dfc-generated"] + - ["lang:proc_macro", "::span", "Argument[self].Field[crate::Punct(0)].Field[crate::bridge::Punct::span]", "ReturnValue.Field[crate::Span(0)]", "value", "dfc-generated"] - ["lang:proc_macro", "::mark", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::unmark", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::into_token_stream", "Argument[self]", "ReturnValue", "value", "dfc-generated"] @@ -33,15 +58,8 @@ extensions: - ["lang:proc_macro", "::from_single", "Argument[0]", "ReturnValue.Field[crate::bridge::DelimSpan::open]", "value", "dfc-generated"] - ["lang:proc_macro", "::mark", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::unmark", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:proc_macro", "::decode", "Argument[0].Element", "ReturnValue.Field[crate::bridge::LitKind::ByteStrRaw(0)]", "value", "dfc-generated"] - - ["lang:proc_macro", "::decode", "Argument[0].Element", "ReturnValue.Field[crate::bridge::LitKind::CStrRaw(0)]", "value", "dfc-generated"] - - ["lang:proc_macro", "::decode", "Argument[0].Element", "ReturnValue.Field[crate::bridge::LitKind::StrRaw(0)]", "value", "dfc-generated"] - - ["lang:proc_macro", "::decode", "Argument[0].Element", "ReturnValue.Field[crate::bridge::Literal::kind].Field[crate::bridge::LitKind::ByteStrRaw(0)]", "value", "dfc-generated"] - - ["lang:proc_macro", "::decode", "Argument[0].Element", "ReturnValue.Field[crate::bridge::Literal::kind].Field[crate::bridge::LitKind::CStrRaw(0)]", "value", "dfc-generated"] - - ["lang:proc_macro", "::decode", "Argument[0].Element", "ReturnValue.Field[crate::bridge::Literal::kind].Field[crate::bridge::LitKind::StrRaw(0)]", "value", "dfc-generated"] - ["lang:proc_macro", "::mark", "Argument[0]", "ReturnValue.Field[crate::bridge::Marked::value]", "value", "dfc-generated"] - - ["lang:proc_macro", "::decode", "Argument[0].Element", "ReturnValue.Field[crate::bridge::Punct::ch]", "value", "dfc-generated"] - - ["lang:proc_macro", "::decode", "Argument[0].Element", "ReturnValue.Field[crate::bridge::TokenTree::Punct(0)].Field[crate::bridge::Punct::ch]", "value", "dfc-generated"] + - ["lang:proc_macro", "::unmark", "Argument[self].Field[crate::bridge::Marked::value]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::take", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::attr", "Argument[0]", "ReturnValue.Field[crate::bridge::client::ProcMacro::Attr::name]", "value", "dfc-generated"] @@ -51,26 +69,38 @@ extensions: - ["lang:proc_macro", "::name", "Argument[self].Field[crate::bridge::client::ProcMacro::Attr::name]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::name", "Argument[self].Field[crate::bridge::client::ProcMacro::Bang::name]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::name", "Argument[self].Field[crate::bridge::client::ProcMacro::CustomDerive::trait_name]", "ReturnValue", "value", "dfc-generated"] + - ["lang:proc_macro", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::clone", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:proc_macro", "::clone", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::clone", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::from", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:proc_macro", "::call", "Argument[0]", "Argument[self]", "taint", "df-generated"] + - ["lang:proc_macro", "::call", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:proc_macro", "::finish", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:proc_macro", "::copy", "Argument[self].Field[crate::bridge::handle::InternedStore::owned].Element", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::new", "Argument[0]", "ReturnValue.Field[crate::bridge::handle::InternedStore::owned].Field[crate::bridge::handle::OwnedStore::counter]", "value", "dfc-generated"] - ["lang:proc_macro", "::new", "Argument[0]", "ReturnValue.Field[crate::bridge::handle::OwnedStore::counter]", "value", "dfc-generated"] - ["lang:proc_macro", "::as_str", "Argument[self].Field[crate::bridge::rpc::PanicMessage::StaticStr(0)]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:proc_macro", "::as_str", "Argument[self].Field[crate::bridge::rpc::PanicMessage::String(0)]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:proc_macro", "::dispatch", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::run_bridge_and_client", "Argument[2].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::new", "Argument[0]", "ReturnValue.Field[crate::bridge::server::MaybeCrossThread::cross_thread]", "value", "dfc-generated"] - ["lang:proc_macro", "::run_bridge_and_client", "Argument[2].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::next", "Argument[self].Field[0].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:proc_macro", "::next", "Argument[self].Field[crate::diagnostic::Children(0)].Element", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:proc_macro", "::error", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::help", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:proc_macro", "::level", "Argument[self].Field[crate::diagnostic::Diagnostic::level]", "ReturnValue", "value", "dfc-generated"] + - ["lang:proc_macro", "::message", "Argument[self].Field[crate::diagnostic::Diagnostic::message]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:proc_macro", "::new", "Argument[0]", "ReturnValue.Field[crate::diagnostic::Diagnostic::level]", "value", "dfc-generated"] - ["lang:proc_macro", "::note", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:proc_macro", "::set_level", "Argument[0]", "Argument[self].Field[crate::diagnostic::Diagnostic::level]", "value", "dfc-generated"] - ["lang:proc_macro", "::span_error", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::span_help", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::span_note", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::span_warning", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::spanned", "Argument[1]", "ReturnValue.Field[crate::diagnostic::Diagnostic::level]", "value", "dfc-generated"] + - ["lang:proc_macro", "::spans", "Argument[self].Field[crate::diagnostic::Diagnostic::spans]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:proc_macro", "::warning", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::mark", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:proc_macro", "::unmark", "Argument[self]", "ReturnValue", "value", "dfc-generated"] diff --git a/rust/ql/lib/ext/generated/rust/lang-std.model.yml b/rust/ql/lib/ext/generated/rust/lang-std.model.yml index 4a1103eaa48f..00d31391a4dc 100644 --- a/rust/ql/lib/ext/generated/rust/lang-std.model.yml +++ b/rust/ql/lib/ext/generated/rust/lang-std.model.yml @@ -11,130 +11,318 @@ extensions: - ["lang:std", "<&[u8] as crate::io::Read>::read_to_end", "Argument[self].Element", "Argument[self].Reference.Reference", "value", "dfc-generated"] - ["lang:std", "<&[u8] as crate::io::Read>::read_to_string", "Argument[self].Element", "Argument[self].Reference.Reference", "value", "dfc-generated"] - ["lang:std", "<&[u8] as crate::io::copy::BufferedReaderSpec>::copy_to", "Argument[self].Element", "Argument[self].Reference.Reference", "value", "dfc-generated"] - - ["lang:std", "<&crate::collections::hash::set::HashSet as crate::ops::arith::Sub>::sub", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:std", "<&crate::collections::hash::set::HashSet as crate::ops::bit::BitAnd>::bitand", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:std", "<&crate::collections::hash::set::HashSet as crate::ops::bit::BitAnd>::bitand", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "<&crate::io::stdio::Stdin as crate::io::Read>::read", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "<&crate::io::stdio::Stdin as crate::io::Read>::read_exact", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "<&crate::io::stdio::Stdin as crate::io::Read>::read_to_string", "Argument[self]", "Argument[0]", "taint", "df-generated"] - ["lang:std", "<&crate::os::unix::net::listener::UnixListener as crate::iter::traits::collect::IntoIterator>::into_iter", "Argument[self]", "ReturnValue.Field[crate::os::unix::net::listener::Incoming::listener]", "value", "dfc-generated"] - ["lang:std", "<&crate::sync::mpmc::Receiver as crate::iter::traits::collect::IntoIterator>::into_iter", "Argument[self]", "ReturnValue.Field[crate::sync::mpmc::Iter::rx]", "value", "dfc-generated"] - ["lang:std", "<&crate::sync::mpsc::Receiver as crate::iter::traits::collect::IntoIterator>::into_iter", "Argument[self]", "ReturnValue.Field[crate::sync::mpsc::Iter::rx]", "value", "dfc-generated"] + - ["lang:std", "<&mut _ as crate::io::BufRead>::read_line", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "<&mut _ as crate::io::BufRead>::read_until", "Argument[self]", "Argument[1]", "taint", "df-generated"] + - ["lang:std", "<&mut _ as crate::io::Read>::read", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "<&mut _ as crate::io::Read>::read_exact", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "<&mut _ as crate::io::Read>::read_to_end", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "<&mut _ as crate::io::Read>::read_to_string", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read_line", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read_until", "Argument[self]", "Argument[1]", "taint", "df-generated"] + - ["lang:std", "::read", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read_exact", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read_to_string", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::and_modify", "Argument[self].Field[crate::collections::hash::map::Entry::Occupied(0)]", "ReturnValue.Field[crate::collections::hash::map::Entry::Occupied(0)]", "value", "dfc-generated"] - ["lang:std", "::and_modify", "Argument[self].Field[crate::collections::hash::map::Entry::Vacant(0)]", "ReturnValue.Field[crate::collections::hash::map::Entry::Vacant(0)]", "value", "dfc-generated"] + - ["lang:std", "::insert_entry", "Argument[self].Field[crate::collections::hash::map::Entry::Occupied(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::map::HashMap::base].Reference", "ReturnValue.Field[crate::collections::hash::map::HashMap::base]", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::map::HashMap::base]", "ReturnValue.Field[crate::collections::hash::map::HashMap::base].Reference", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::map::HashMap::base]", "ReturnValue.Field[crate::collections::hash::map::HashMap::base]", "value", "dfc-generated"] - ["lang:std", "::raw_entry", "Argument[self]", "ReturnValue.Field[crate::collections::hash::map::RawEntryBuilder::map]", "value", "dfc-generated"] - ["lang:std", "::raw_entry_mut", "Argument[self]", "ReturnValue.Field[crate::collections::hash::map::RawEntryBuilderMut::map]", "value", "dfc-generated"] - ["lang:std", "::try_insert", "Argument[1]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::collections::hash::map::OccupiedError::value]", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::map::Iter::base].Reference", "ReturnValue.Field[crate::collections::hash::map::Iter::base]", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::map::Iter::base]", "ReturnValue.Field[crate::collections::hash::map::Iter::base].Reference", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::map::Iter::base]", "ReturnValue.Field[crate::collections::hash::map::Iter::base]", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::and_modify", "Argument[self].Field[crate::collections::hash::map::RawEntryMut::Occupied(0)]", "ReturnValue.Field[crate::collections::hash::map::RawEntryMut::Occupied(0)]", "value", "dfc-generated"] - ["lang:std", "::and_modify", "Argument[self].Field[crate::collections::hash::map::RawEntryMut::Vacant(0)]", "ReturnValue.Field[crate::collections::hash::map::RawEntryMut::Vacant(0)]", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::insert", "Argument[self].Field[crate::collections::hash::set::Entry::Occupied(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::set::HashSet::base].Reference", "ReturnValue.Field[crate::collections::hash::set::HashSet::base]", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::set::HashSet::base]", "ReturnValue.Field[crate::collections::hash::set::HashSet::base].Reference", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::set::HashSet::base]", "ReturnValue.Field[crate::collections::hash::set::HashSet::base]", "value", "dfc-generated"] - ["lang:std", "::difference", "Argument[0]", "ReturnValue.Field[crate::collections::hash::set::Difference::other]", "value", "dfc-generated"] - ["lang:std", "::intersection", "Argument[0]", "ReturnValue.Field[crate::collections::hash::set::Intersection::other]", "value", "dfc-generated"] - ["lang:std", "::intersection", "Argument[self]", "ReturnValue.Field[crate::collections::hash::set::Intersection::other]", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::set::Iter::base].Reference", "ReturnValue.Field[crate::collections::hash::set::Iter::base]", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::set::Iter::base]", "ReturnValue.Field[crate::collections::hash::set::Iter::base].Reference", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::set::Iter::base]", "ReturnValue.Field[crate::collections::hash::set::Iter::base]", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::set::SymmetricDifference::iter].Reference", "ReturnValue.Field[crate::collections::hash::set::SymmetricDifference::iter]", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::set::SymmetricDifference::iter]", "ReturnValue.Field[crate::collections::hash::set::SymmetricDifference::iter].Reference", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::set::SymmetricDifference::iter]", "ReturnValue.Field[crate::collections::hash::set::SymmetricDifference::iter]", "value", "dfc-generated"] - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::set::Union::iter].Reference", "ReturnValue.Field[crate::collections::hash::set::Union::iter]", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::set::Union::iter]", "ReturnValue.Field[crate::collections::hash::set::Union::iter].Reference", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::collections::hash::set::Union::iter]", "ReturnValue.Field[crate::collections::hash::set::Union::iter]", "value", "dfc-generated"] - ["lang:std", "::fold", "Argument[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::fold", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::from", "Argument[0]", "ReturnValue.Field[crate::error::Report::error]", "value", "dfc-generated"] + - ["lang:std", "::pretty", "Argument[0]", "Argument[self].Field[crate::error::Report::pretty]", "value", "dfc-generated"] + - ["lang:std", "::pretty", "Argument[0]", "ReturnValue.Field[crate::error::Report::pretty]", "value", "dfc-generated"] - ["lang:std", "::pretty", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::show_backtrace", "Argument[0]", "Argument[self].Field[crate::error::Report::show_backtrace]", "value", "dfc-generated"] + - ["lang:std", "::show_backtrace", "Argument[0]", "ReturnValue.Field[crate::error::Report::show_backtrace]", "value", "dfc-generated"] - ["lang:std", "::show_backtrace", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::as_ref", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::as_bytes", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::ffi::os_str::OsStr::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_encoded_bytes", "Argument[self].Field[crate::ffi::os_str::OsStr::inner].Field[crate::sys::os_str::bytes::Slice::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::display", "Argument[self]", "ReturnValue.Field[crate::ffi::os_str::Display::os_str]", "value", "dfc-generated"] - ["lang:std", "::borrow", "Argument[self].Element", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::as_ref", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:std", "::from", "Argument[0].Field[crate::borrow::Cow::Owned(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::from", "Argument[0].Field[crate::path::PathBuf::inner]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::deref", "Argument[self].Element", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::deref_mut", "Argument[self].Element", "ReturnValue.Reference", "value", "dfc-generated"] - - ["lang:std", "::from_str", "Argument[0].Field[crate::borrow::Cow::Owned(0)]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] + - ["lang:std", "::into_vec", "Argument[self].Field[crate::ffi::os_str::OsString::inner].Field[crate::sys::os_str::bytes::Buf::inner]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::ffi::os_str::OsString::inner]", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::ffi::os_str::OsString::inner]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::as_os_str", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::from_encoded_bytes_unchecked", "Argument[0]", "ReturnValue.Field[crate::ffi::os_str::OsString::inner].Field[crate::sys::os_str::bytes::Buf::inner]", "value", "dfc-generated"] + - ["lang:std", "::into_encoded_bytes", "Argument[self].Field[crate::ffi::os_str::OsString::inner].Field[crate::sys::os_str::bytes::Buf::inner]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::mode", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::as_inner_mut", "Argument[self].Field[crate::fs::DirBuilder::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::recursive", "Argument[0]", "Argument[self].Field[crate::fs::DirBuilder::recursive]", "value", "dfc-generated"] + - ["lang:std", "::recursive", "Argument[0]", "ReturnValue.Field[crate::fs::DirBuilder::recursive]", "value", "dfc-generated"] - ["lang:std", "::recursive", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::as_inner", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::fs::DirEntry(0)]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::fs::File::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::fs::File::inner]", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::fs::File::inner]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::set_created", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::as_inner_mut", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner_mut", "Argument[self].Field[crate::fs::FileTimes(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::set_accessed", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::set_modified", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::as_inner", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::fs::FileType(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::as_inner", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::fs::Metadata(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::fs::Metadata(0)]", "value", "dfc-generated"] - ["lang:std", "::custom_flags", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::mode", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::as_inner", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::fs::OpenOptions(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::as_inner_mut", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner_mut", "Argument[self].Field[crate::fs::OpenOptions(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::append", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::create", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::create_new", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::read", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::truncate", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::write", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:std", "::from_mode", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:std", "::set_mode", "Argument[0]", "Argument[self]", "taint", "df-generated"] + - ["lang:std", "::mode", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::as_inner", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::fs::Permissions(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::fs::Permissions(0)]", "value", "dfc-generated"] + - ["lang:std", "::read_until", "Argument[self]", "Argument[1]", "taint", "df-generated"] + - ["lang:std", "::read", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::get_mut", "Argument[self].Field[crate::io::Chain::first]", "ReturnValue.Field[0].Reference", "value", "dfc-generated"] + - ["lang:std", "::get_mut", "Argument[self].Field[crate::io::Chain::second]", "ReturnValue.Field[1].Reference", "value", "dfc-generated"] + - ["lang:std", "::get_ref", "Argument[self].Field[crate::io::Chain::first]", "ReturnValue.Field[0].Reference", "value", "dfc-generated"] + - ["lang:std", "::get_ref", "Argument[self].Field[crate::io::Chain::second]", "ReturnValue.Field[1].Reference", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::io::Chain::first]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::io::Chain::second]", "ReturnValue.Field[1]", "value", "dfc-generated"] - ["lang:std", "::advance_slices", "Argument[0].Reference.Element", "Argument[0].Reference.Reference", "value", "dfc-generated"] - ["lang:std", "::advance_slices", "Argument[0].Reference.Element", "Argument[0].Reference.Reference", "value", "dfc-generated"] + - ["lang:std", "::next", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::next", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::read", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::lower_bound", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::upper_bound", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::get_mut", "Argument[self].Field[crate::io::Take::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::get_ref", "Argument[self].Field[crate::io::Take::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::io::Take::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::limit", "Argument[self].Field[crate::io::Take::limit]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::set_limit", "Argument[0]", "Argument[self].Field[crate::io::Take::limit]", "value", "dfc-generated"] + - ["lang:std", "::write", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::error", "Argument[self].Field[1]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::error", "Argument[self].Field[crate::io::buffered::IntoInnerError(1)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::into_error", "Argument[self].Field[1]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_error", "Argument[self].Field[crate::io::buffered::IntoInnerError(1)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::into_inner", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:std", "::into_parts", "Argument[self].Field[0]", "ReturnValue.Field[1]", "value", "dfc-generated"] - - ["lang:std", "::into_parts", "Argument[self].Field[1]", "ReturnValue.Field[0]", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::io::buffered::IntoInnerError(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_parts", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::consume", "Argument[0]", "Argument[self]", "taint", "df-generated"] + - ["lang:std", "::read", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::read_buf", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::read_exact", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read_vectored", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::get_mut", "Argument[self].Field[crate::io::buffered::bufreader::BufReader::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::get_ref", "Argument[self].Field[crate::io::buffered::bufreader::BufReader::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::io::buffered::bufreader::BufReader::inner]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::io::buffered::bufreader::BufReader::inner]", "value", "dfc-generated"] + - ["lang:std", "::seek_relative", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:std", "::with_buffer", "Argument[0]", "ReturnValue.Field[crate::io::buffered::bufreader::BufReader::inner]", "value", "dfc-generated"] - ["lang:std", "::with_buffer", "Argument[1]", "ReturnValue.Field[crate::io::buffered::bufreader::BufReader::buf]", "value", "dfc-generated"] - ["lang:std", "::with_capacity", "Argument[1]", "ReturnValue.Field[crate::io::buffered::bufreader::BufReader::inner]", "value", "dfc-generated"] - - ["lang:std", "::into_inner", "Argument[self]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::io::buffered::IntoInnerError(0)]", "value", "dfc-generated"] + - ["lang:std", "::consume", "Argument[self].Field[crate::io::buffered::bufreader::buffer::Buffer::filled]", "Argument[self].Field[crate::io::buffered::bufreader::buffer::Buffer::pos]", "value", "dfc-generated"] + - ["lang:std", "::filled", "Argument[self].Field[crate::io::buffered::bufreader::buffer::Buffer::filled]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::pos", "Argument[self].Field[crate::io::buffered::bufreader::buffer::Buffer::pos]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::buffer", "Argument[self].Field[crate::io::buffered::bufwriter::BufWriter::buf]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::buffer_mut", "Argument[self].Field[crate::io::buffered::bufwriter::BufWriter::buf]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::get_mut", "Argument[self].Field[crate::io::buffered::bufwriter::BufWriter::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::get_ref", "Argument[self].Field[crate::io::buffered::bufwriter::BufWriter::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::io::buffered::bufwriter::BufWriter::inner]", "value", "dfc-generated"] - ["lang:std", "::with_buffer", "Argument[0]", "ReturnValue.Field[crate::io::buffered::bufwriter::BufWriter::inner]", "value", "dfc-generated"] - ["lang:std", "::with_buffer", "Argument[1]", "ReturnValue.Field[crate::io::buffered::bufwriter::BufWriter::buf]", "value", "dfc-generated"] - ["lang:std", "::with_capacity", "Argument[1]", "ReturnValue.Field[crate::io::buffered::bufwriter::BufWriter::inner]", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::io::buffered::bufwriter::WriterPanicked::buf]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::io::buffered::linewriter::LineWriter::inner].Field[crate::io::buffered::bufwriter::BufWriter::inner]", "value", "dfc-generated"] - ["lang:std", "::with_capacity", "Argument[1]", "ReturnValue.Field[crate::io::buffered::linewriter::LineWriter::inner].Field[crate::io::buffered::bufwriter::BufWriter::inner]", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::io::buffered::linewritershim::LineWriterShim::buffer]", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::clone_from", "Argument[0].Field[crate::io::cursor::Cursor::inner]", "Argument[self].Field[crate::io::cursor::Cursor::inner].Reference", "value", "dfc-generated"] + - ["lang:std", "::clone_from", "Argument[0].Field[crate::io::cursor::Cursor::inner]", "Argument[self].Field[crate::io::cursor::Cursor::inner]", "value", "dfc-generated"] + - ["lang:std", "::clone_from", "Argument[0].Field[crate::io::cursor::Cursor::pos]", "Argument[self].Field[crate::io::cursor::Cursor::pos]", "value", "dfc-generated"] + - ["lang:std", "::seek", "Argument[0].Field[crate::io::SeekFrom::Start(0)]", "Argument[self].Field[crate::io::cursor::Cursor::pos]", "value", "dfc-generated"] + - ["lang:std", "::seek", "Argument[0].Field[crate::io::SeekFrom::Start(0)]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] + - ["lang:std", "::seek", "Argument[self].Field[crate::io::cursor::Cursor::pos]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] + - ["lang:std", "::stream_position", "Argument[self].Field[crate::io::cursor::Cursor::pos]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] + - ["lang:std", "::get_mut", "Argument[self].Field[crate::io::cursor::Cursor::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::get_ref", "Argument[self].Field[crate::io::cursor::Cursor::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::io::cursor::Cursor::inner]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::io::cursor::Cursor::inner]", "value", "dfc-generated"] + - ["lang:std", "::position", "Argument[self].Field[crate::io::cursor::Cursor::pos]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::set_position", "Argument[0]", "Argument[self].Field[crate::io::cursor::Cursor::pos]", "value", "dfc-generated"] - ["lang:std", "::from", "Argument[0].Field[1]", "ReturnValue", "value", "dfc-generated"] - - ["lang:std", "::new_simple_message", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::from", "Argument[0].Field[crate::io::buffered::IntoInnerError(1)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read_exact", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read_to_string", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::lines", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::read_line", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::fill_buf", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::read_line", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read_until", "Argument[self]", "Argument[1]", "taint", "df-generated"] + - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read_to_string", "Argument[self]", "Argument[0]", "taint", "df-generated"] - ["lang:std", "::as_inner", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::net::tcp::TcpListener(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::net::tcp::TcpListener(0)]", "value", "dfc-generated"] - ["lang:std", "::into_inner", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::net::tcp::TcpListener(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::incoming", "Argument[self]", "ReturnValue.Field[crate::net::tcp::Incoming::listener]", "value", "dfc-generated"] - ["lang:std", "::into_incoming", "Argument[self]", "ReturnValue.Field[crate::net::tcp::IntoIncoming::listener]", "value", "dfc-generated"] - ["lang:std", "::as_inner", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::net::tcp::TcpStream(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::net::tcp::TcpStream(0)]", "value", "dfc-generated"] - ["lang:std", "::into_inner", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::net::tcp::TcpStream(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::as_inner", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::net::udp::UdpSocket(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::net::udp::UdpSocket(0)]", "value", "dfc-generated"] - ["lang:std", "::into_inner", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::net::udp::UdpSocket(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::as_fd", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - - ["lang:std", "::borrow_raw", "Argument[0]", "ReturnValue.Field[crate::os::fd::owned::BorrowedFd::fd].Field[crate::num::niche_types::I32NotAllOnes(0)]", "value", "dfc-generated"] - - ["lang:std", "::from_raw_fd", "Argument[0]", "ReturnValue.Field[crate::os::fd::owned::OwnedFd::fd].Field[crate::num::niche_types::I32NotAllOnes(0)]", "value", "dfc-generated"] - ["lang:std", "::from_parts", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::os::unix::net::addr::SocketAddr::addr]", "value", "dfc-generated"] - ["lang:std", "::from_parts", "Argument[1]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::os::unix::net::addr::SocketAddr::len]", "value", "dfc-generated"] - - ["lang:std", "::new", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::as_inner", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::os::unix::net::datagram::UnixDatagram(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::incoming", "Argument[self]", "ReturnValue.Field[crate::os::unix::net::listener::Incoming::listener]", "value", "dfc-generated"] - ["lang:std", "::as_inner", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::os::unix::net::stream::UnixStream(0)]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::can_unwind", "Argument[self].Field[crate::panic::PanicHookInfo::can_unwind]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::force_no_backtrace", "Argument[self].Field[crate::panic::PanicHookInfo::force_no_backtrace]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::location", "Argument[self].Field[crate::panic::PanicHookInfo::location]", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::panic::PanicHookInfo::location]", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[1]", "ReturnValue.Field[crate::panic::PanicHookInfo::payload]", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[2]", "ReturnValue.Field[crate::panic::PanicHookInfo::can_unwind]", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[3]", "ReturnValue.Field[crate::panic::PanicHookInfo::force_no_backtrace]", "value", "dfc-generated"] + - ["lang:std", "::payload", "Argument[self].Field[crate::panic::PanicHookInfo::payload]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::next", "Argument[self].Field[crate::path::Ancestors::next]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::as_ref", "Argument[self].Field[crate::path::Component::Normal(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::as_ref", "Argument[self].Reference.Field[crate::path::Component::Normal(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::as_os_str", "Argument[self].Field[crate::path::Component::Normal(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::next_back", "Argument[self].Field[crate::path::Components::path].Element", "Argument[self].Field[crate::path::Components::path].Reference", "value", "dfc-generated"] + - ["lang:std", "::next", "Argument[self].Field[crate::path::Components::path].Element", "Argument[self].Field[crate::path::Components::path].Reference", "value", "dfc-generated"] + - ["lang:std", "::as_ref", "Argument[self].Field[crate::path::Path::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::as_ref", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::ancestors", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::as_mut_os_str", "Argument[self].Field[crate::path::Path::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_os_str", "Argument[self].Field[crate::path::Path::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::display", "Argument[self].Field[crate::path::Path::inner]", "ReturnValue.Field[crate::path::Display::inner].Field[crate::ffi::os_str::Display::os_str]", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::as_ref", "Argument[self].Field[crate::path::PathBuf::inner].Element", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::as_ref", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:std", "::from", "Argument[0].Field[crate::borrow::Cow::Owned(0)].Field[crate::borrow::Cow::Owned(0)]", "ReturnValue.Field[crate::path::PathBuf::inner]", "value", "dfc-generated"] - - ["lang:std", "::from", "Argument[0].Field[crate::borrow::Cow::Owned(0)].Field[crate::borrow::Cow::Owned(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:std", "::from", "Argument[0].Field[crate::borrow::Cow::Owned(0)]", "ReturnValue.Field[crate::path::PathBuf::inner]", "value", "dfc-generated"] - - ["lang:std", "::from", "Argument[0].Field[crate::borrow::Cow::Owned(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::from", "Argument[0].Field[crate::path::PathBuf::inner].Field[crate::path::PathBuf::inner]", "ReturnValue.Field[crate::path::PathBuf::inner]", "value", "dfc-generated"] + - ["lang:std", "::from", "Argument[0].Field[crate::path::PathBuf::inner]", "ReturnValue.Field[crate::path::PathBuf::inner]", "value", "dfc-generated"] - ["lang:std", "::from", "Argument[0]", "ReturnValue.Field[crate::path::PathBuf::inner]", "value", "dfc-generated"] - - ["lang:std", "::from_str", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::from_str", "Argument[0].Field[crate::path::PathBuf::inner].Field[crate::path::PathBuf::inner]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::path::PathBuf::inner]", "value", "dfc-generated"] + - ["lang:std", "::from_str", "Argument[0].Field[crate::path::PathBuf::inner]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::path::PathBuf::inner]", "value", "dfc-generated"] + - ["lang:std", "::from_str", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::path::PathBuf::inner]", "value", "dfc-generated"] + - ["lang:std", "::as_mut_os_string", "Argument[self].Field[crate::path::PathBuf::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::as_path", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_os_string", "Argument[self].Field[crate::path::PathBuf::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::as_os_str", "Argument[self].Field[crate::path::PrefixComponent::raw]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::kind", "Argument[self].Field[crate::path::PrefixComponent::parsed]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::process::Child::handle]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0].Field[0]", "ReturnValue.Field[crate::process::Child::handle]", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::process::Child::handle]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::id", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::process::ChildStderr::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::process::ChildStderr::inner]", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::process::ChildStderr::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::process::ChildStdin::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::process::ChildStdin::inner]", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::process::ChildStdin::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::process::ChildStdout::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::process::ChildStdout::inner]", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::process::ChildStdout::inner]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::arg0", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::gid", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::groups", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::pre_exec", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::process_group", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::uid", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::process::Command::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner_mut", "Argument[self].Field[crate::process::Command::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::arg", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::args", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::current_dir", "Argument[self]", "ReturnValue", "value", "dfc-generated"] @@ -145,32 +333,54 @@ extensions: - ["lang:std", "::stderr", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::stdin", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::stdout", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:std", "::from", "Argument[0]", "ReturnValue.Field[crate::process::ExitCode(0)].Field[crate::sys::pal::unix::process::process_common::ExitCode(0)]", "value", "dfc-generated"] - ["lang:std", "::report", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::as_inner", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::process::ExitCode(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::process::ExitCode(0)]", "value", "dfc-generated"] - ["lang:std", "::to_i32", "Argument[self]", "ReturnValue", "taint", "df-generated"] - - ["lang:std", "::from_raw", "Argument[0]", "ReturnValue.Field[crate::process::ExitStatus(0)].Field[crate::sys::pal::unix::process::process_inner::ExitStatus(0)]", "value", "dfc-generated"] - ["lang:std", "::as_inner", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::process::ExitStatus(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::process::ExitStatus(0)]", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::process::Stdio(0)]", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::barrier::Barrier::num_threads]", "value", "dfc-generated"] - ["lang:std", "::is_leader", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::is_leader", "Argument[self].Field[crate::sync::barrier::BarrierWaitResult(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::iter", "Argument[self]", "ReturnValue.Field[crate::sync::mpmc::Iter::rx]", "value", "dfc-generated"] - ["lang:std", "::try_iter", "Argument[self]", "ReturnValue.Field[crate::sync::mpmc::TryIter::rx]", "value", "dfc-generated"] + - ["lang:std", "::capacity", "Argument[self].Field[crate::sync::mpmc::array::Channel::cap]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:std", "::len", "Argument[self].Field[crate::sync::mpmc::array::Channel::cap]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::send", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::sync::mpmc::error::SendTimeoutError::Timeout(0)]", "value", "dfc-generated"] + - ["lang:std", "::try_send", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::sync::mpsc::TrySendError::Full(0)]", "value", "dfc-generated"] - ["lang:std", "::with_capacity", "Argument[0]", "ReturnValue.Field[crate::sync::mpmc::array::Channel::cap]", "value", "dfc-generated"] - ["lang:std", "::write", "Argument[1]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:std", "::acquire", "Argument[self].Field[crate::sync::mpmc::counter::Receiver::counter]", "ReturnValue.Field[crate::sync::mpmc::counter::Receiver::counter]", "value", "dfc-generated"] + - ["lang:std", "::acquire", "Argument[self].Field[crate::sync::mpmc::counter::Sender::counter]", "ReturnValue.Field[crate::sync::mpmc::counter::Sender::counter]", "value", "dfc-generated"] + - ["lang:std", "::from", "Argument[0].Field[crate::sync::mpsc::SendError(0)]", "ReturnValue.Field[crate::sync::mpmc::error::SendTimeoutError::Disconnected(0)]", "value", "dfc-generated"] - ["lang:std", "::write", "Argument[1]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:std", "::hook", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::mpmc::select::Selected::Operation(0)].Field[crate::sync::mpmc::select::Operation(0)]", "value", "dfc-generated"] - ["lang:std", "::into", "Argument[self].Field[crate::sync::mpmc::select::Selected::Operation(0)].Field[crate::sync::mpmc::select::Operation(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::deref", "Argument[self].Field[crate::sync::mpmc::utils::CachePadded::value]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::deref_mut", "Argument[self].Field[crate::sync::mpmc::utils::CachePadded::value]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::mpmc::utils::CachePadded::value]", "value", "dfc-generated"] + - ["lang:std", "::send", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::sync::mpmc::error::SendTimeoutError::Disconnected(0)]", "value", "dfc-generated"] + - ["lang:std", "::try_send", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::sync::mpsc::TrySendError::Disconnected(0)]", "value", "dfc-generated"] + - ["lang:std", "::try_send", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::sync::mpsc::TrySendError::Full(0)]", "value", "dfc-generated"] - ["lang:std", "::write", "Argument[1]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:std", "::iter", "Argument[self]", "ReturnValue.Field[crate::sync::mpsc::Iter::rx]", "value", "dfc-generated"] - ["lang:std", "::try_iter", "Argument[self]", "ReturnValue.Field[crate::sync::mpsc::TryIter::rx]", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::sync::mpsc::Sender::inner].Reference", "ReturnValue.Field[crate::sync::mpsc::Sender::inner]", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::sync::mpsc::Sender::inner]", "ReturnValue.Field[crate::sync::mpsc::Sender::inner].Reference", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::sync::mpsc::Sender::inner]", "ReturnValue.Field[crate::sync::mpsc::Sender::inner]", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::sync::mpsc::SyncSender::inner].Reference", "ReturnValue.Field[crate::sync::mpsc::SyncSender::inner]", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::sync::mpsc::SyncSender::inner]", "ReturnValue.Field[crate::sync::mpsc::SyncSender::inner].Reference", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::sync::mpsc::SyncSender::inner]", "ReturnValue.Field[crate::sync::mpsc::SyncSender::inner]", "value", "dfc-generated"] - ["lang:std", "::from", "Argument[0].Field[crate::sync::mpsc::SendError(0)]", "ReturnValue.Field[crate::sync::mpsc::TrySendError::Disconnected(0)]", "value", "dfc-generated"] - ["lang:std", "::set", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:std", "::try_insert", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[1]", "value", "dfc-generated"] + - ["lang:std", "::get_mut", "Argument[self].Field[crate::sync::poison::PoisonError::data]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::get_ref", "Argument[self].Field[crate::sync::poison::PoisonError::data]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::sync::poison::PoisonError::data]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::poison::PoisonError::data]", "value", "dfc-generated"] - ["lang:std", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::poison::TryLockError::Poisoned(0)]", "value", "dfc-generated"] - ["lang:std", "::cause", "Argument[self].Reference.Field[crate::sync::poison::TryLockError::Poisoned(0)]", "ReturnValue.Field[crate::option::Option::Some(0)].Reference", "value", "dfc-generated"] @@ -183,90 +393,185 @@ extensions: - ["lang:std", "::wait_while", "Argument[0].Reference", "Argument[1].Parameter[0].Reference", "value", "dfc-generated"] - ["lang:std", "::wait_while", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] - ["lang:std", "::timed_out", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:std", "::map", "Argument[1]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::timed_out", "Argument[self].Field[crate::sync::poison::condvar::WaitTimeoutResult(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::try_map", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:std", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::poison::mutex::Mutex::data].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::sync::poison::mutex::Mutex::data].Field[crate::cell::UnsafeCell::value]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::sync::poison::PoisonError::data]", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::sync::poison::mutex::Mutex::data].Field[crate::cell::UnsafeCell::value]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] - ["lang:std", "::lock", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::sync::poison::mutex::MutexGuard::lock]", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::poison::mutex::Mutex::data].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - ["lang:std", "::replace", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::sync::poison::PoisonError::data]", "value", "dfc-generated"] - ["lang:std", "::set", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::sync::poison::PoisonError::data]", "value", "dfc-generated"] - - ["lang:std", "::try_lock", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::sync::poison::mutex::MutexGuard::lock]", "value", "dfc-generated"] - - ["lang:std", "::try_lock", "Argument[self]", "ReturnValue.Field[crate::sync::poison::mutex::MutexGuard::lock]", "value", "dfc-generated"] - - ["lang:std", "::map", "Argument[1]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::try_map", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - - ["lang:std", "::map", "Argument[1]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::is_poisoned", "Argument[self].Field[crate::sync::poison::once::OnceState::inner].Field[crate::sys::sync::once::queue::OnceState::poisoned]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::try_map", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - - ["lang:std", "::map", "Argument[1]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::try_map", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:std", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::poison::rwlock::RwLock::data].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::sync::poison::rwlock::RwLock::data].Field[crate::cell::UnsafeCell::value]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::sync::poison::PoisonError::data]", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::sync::poison::rwlock::RwLock::data].Field[crate::cell::UnsafeCell::value]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::poison::rwlock::RwLock::data].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] + - ["lang:std", "::read", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::replace", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::sync::poison::PoisonError::data]", "value", "dfc-generated"] - ["lang:std", "::set", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)].Field[crate::sync::poison::PoisonError::data]", "value", "dfc-generated"] - - ["lang:std", "::try_write", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::sync::poison::rwlock::RwLockWriteGuard::lock]", "value", "dfc-generated"] - - ["lang:std", "::try_write", "Argument[self]", "ReturnValue.Field[crate::sync::poison::rwlock::RwLockWriteGuard::lock]", "value", "dfc-generated"] - ["lang:std", "::write", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::sync::poison::rwlock::RwLockWriteGuard::lock]", "value", "dfc-generated"] - - ["lang:std", "::map", "Argument[1]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::try_map", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - - ["lang:std", "::map", "Argument[1]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::downgrade", "Argument[0].Field[crate::sync::poison::rwlock::RwLockWriteGuard::lock].Field[crate::sync::poison::rwlock::RwLock::inner]", "ReturnValue.Field[crate::sync::poison::rwlock::RwLockReadGuard::inner_lock].Reference", "value", "dfc-generated"] - ["lang:std", "::try_map", "Argument[0]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - - ["lang:std", "::from", "Argument[0]", "ReturnValue.Field[crate::sync::reentrant_lock::ReentrantLock::data]", "value", "dfc-generated"] + - ["lang:std", "::get_mut", "Argument[self].Field[crate::sync::reentrant_lock::ReentrantLock::data]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::sync::reentrant_lock::ReentrantLock::data]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::lock", "Argument[self]", "ReturnValue.Field[crate::sync::reentrant_lock::ReentrantLockGuard::lock]", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::sync::reentrant_lock::ReentrantLock::data]", "value", "dfc-generated"] - ["lang:std", "::try_lock", "Argument[self]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::sync::reentrant_lock::ReentrantLockGuard::lock]", "value", "dfc-generated"] + - ["lang:std", "::deref", "Argument[self].Field[crate::sync::reentrant_lock::ReentrantLockGuard::lock].Field[crate::sync::reentrant_lock::ReentrantLock::data]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::port", "Argument[self].Field[crate::sys::net::connection::socket::LookupHost::port]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::sys::net::connection::socket::TcpListener::inner]", "value", "dfc-generated"] - ["lang:std", "::bind", "Argument[0].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::bind", "Argument[0].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_socket", "Argument[self].Field[crate::sys::net::connection::socket::TcpListener::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::socket", "Argument[self].Field[crate::sys::net::connection::socket::TcpListener::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::sys::net::connection::socket::TcpStream::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::sys::net::connection::socket::TcpStream::inner]", "value", "dfc-generated"] - ["lang:std", "::connect", "Argument[0].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::connect", "Argument[0].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_socket", "Argument[self].Field[crate::sys::net::connection::socket::TcpStream::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::socket", "Argument[self].Field[crate::sys::net::connection::socket::TcpStream::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::sys::net::connection::socket::UdpSocket::inner]", "value", "dfc-generated"] - ["lang:std", "::bind", "Argument[0].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::bind", "Argument[0].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::connect", "Argument[0].Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::connect", "Argument[0].Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_socket", "Argument[self].Field[crate::sys::net::connection::socket::UdpSocket::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::socket", "Argument[self].Field[crate::sys::net::connection::socket::UdpSocket::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::as_inner", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] - - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::sys::net::connection::socket::unix::Socket(0)]", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::sys::net::connection::socket::unix::Socket(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::into_inner", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::sys::net::connection::socket::unix::Socket(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::sys::os_str::bytes::Buf::inner].Reference", "ReturnValue.Field[crate::sys::os_str::bytes::Buf::inner]", "value", "dfc-generated"] + - ["lang:std", "::clone", "Argument[self].Field[crate::sys::os_str::bytes::Buf::inner]", "ReturnValue.Field[crate::sys::os_str::bytes::Buf::inner]", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::sys::os_str::bytes::Buf::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::sys::os_str::bytes::Buf::inner]", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::sys::os_str::bytes::Buf::inner]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::from_encoded_bytes_unchecked", "Argument[0]", "ReturnValue.Field[crate::sys::os_str::bytes::Buf::inner]", "value", "dfc-generated"] + - ["lang:std", "::into_encoded_bytes", "Argument[self].Field[crate::sys::os_str::bytes::Buf::inner]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::as_encoded_bytes", "Argument[self].Field[crate::sys::os_str::bytes::Slice::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::as_inner", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] - - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::sys::pal::unix::fd::FileDesc(0)]", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::sys::pal::unix::fd::FileDesc(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::into_inner", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::sys::pal::unix::fd::FileDesc(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::set_mode", "Argument[0]", "Argument[self]", "taint", "df-generated"] + - ["lang:std", "::ino", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::as_inner", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::sys::pal::unix::fs::File(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::as_inner_mut", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] - - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::sys::pal::unix::fs::File(0)]", "value", "dfc-generated"] + - ["lang:std", "::as_inner_mut", "Argument[self].Field[crate::sys::pal::unix::fs::File(0)]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::into_inner", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::sys::pal::unix::fs::File(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::sys::pal::unix::fs::FileAttr::stat]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::file_type", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::perm", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::size", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue", "taint", "df-generated"] - - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::sys::pal::unix::pipe::AnonPipe(0)]", "value", "dfc-generated"] + - ["lang:std", "::mode", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::set_accessed", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::fs::FileTimes::accessed].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:std", "::set_created", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::fs::FileTimes::created].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:std", "::set_modified", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::fs::FileTimes::modified].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:std", "::append", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::fs::OpenOptions::append]", "value", "dfc-generated"] + - ["lang:std", "::create", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::fs::OpenOptions::create]", "value", "dfc-generated"] + - ["lang:std", "::create_new", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::fs::OpenOptions::create_new]", "value", "dfc-generated"] + - ["lang:std", "::custom_flags", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::fs::OpenOptions::custom_flags]", "value", "dfc-generated"] + - ["lang:std", "::mode", "Argument[0]", "Argument[self]", "taint", "df-generated"] + - ["lang:std", "::read", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::fs::OpenOptions::read]", "value", "dfc-generated"] + - ["lang:std", "::truncate", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::fs::OpenOptions::truncate]", "value", "dfc-generated"] + - ["lang:std", "::write", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::fs::OpenOptions::write]", "value", "dfc-generated"] + - ["lang:std", "::read", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0]", "taint", "df-generated"] + - ["lang:std", "::read_to_string", "Argument[self]", "Argument[0]", "taint", "df-generated"] - ["lang:std", "::into_inner", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::sys::pal::unix::pipe::AnonPipe(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::as_file_desc", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_file_desc", "Argument[self].Field[crate::sys::pal::unix::pipe::AnonPipe(0)]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0]", "taint", "df-generated"] - ["lang:std", "::fd", "Argument[self].Reference.Field[crate::sys::pal::unix::process::process_common::ChildStdio::Explicit(0)]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:std", "::from", "Argument[0]", "ReturnValue.Field[crate::sys::pal::unix::process::process_common::ExitCode(0)]", "value", "dfc-generated"] + - ["lang:std", "::env_mut", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::env]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::get_argv", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::argv].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::get_argv", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::argv].Field[crate::sys::pal::unix::process::process_common::Argv(0)]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::get_closures", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::closures]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::get_gid", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::gid]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::get_pgroup", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::pgroup]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::get_program_cstr", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::program].Reference", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::get_program_kind", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::program_kind]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::get_uid", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::uid]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::gid", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::gid].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:std", "::pgroup", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::pgroup].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:std", "::saw_nul", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::saw_nul]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::stderr", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::stderr].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:std", "::stdin", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::stdin].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:std", "::stdout", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::stdout].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:std", "::uid", "Argument[0]", "Argument[self].Field[crate::sys::pal::unix::process::process_common::Command::uid].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:std", "::as_i32", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::from", "Argument[0].Field[0]", "ReturnValue.Field[crate::sys::pal::unix::process::process_common::Stdio::Fd(0)]", "value", "dfc-generated"] + - ["lang:std", "::from", "Argument[0].Field[crate::sys::pal::unix::fs::File(0)]", "ReturnValue.Field[crate::sys::pal::unix::process::process_common::Stdio::Fd(0)]", "value", "dfc-generated"] + - ["lang:std", "::from", "Argument[0].Field[crate::sys::pal::unix::pipe::AnonPipe(0)]", "ReturnValue.Field[crate::sys::pal::unix::process::process_common::Stdio::Fd(0)]", "value", "dfc-generated"] - ["lang:std", "::from", "Argument[0]", "ReturnValue.Field[crate::sys::pal::unix::process::process_inner::ExitStatus(0)]", "value", "dfc-generated"] - ["lang:std", "::into_raw", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_raw", "Argument[self].Field[crate::sys::pal::unix::process::process_inner::ExitStatus(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::sys::pal::unix::process::process_inner::ExitStatus(0)]", "value", "dfc-generated"] - - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::sys::pal::unix::time::Timespec::tv_sec]", "value", "dfc-generated"] + - ["lang:std", "::id", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::id", "Argument[self].Field[crate::sys::pal::unix::thread::Thread::id]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::checked_sub_instant", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::checked_sub_instant", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::sub_time", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::sub_time", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::sub_timespec", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::sub_timespec", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::sys::pal::unix::weak::DlsymWeak::name]", "value", "dfc-generated"] + - ["lang:std", "::get", "Argument[self].Field[crate::sys::pal::unix::weak::ExternWeak::weak_ptr]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::sys::pal::unix::weak::ExternWeak::weak_ptr]", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::sys::personality::dwarf::DwarfReader::ptr]", "value", "dfc-generated"] + - ["lang:std", "::is_poisoned", "Argument[self].Field[crate::sys::sync::once::queue::OnceState::poisoned]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::sys::thread_local::native::eager::Storage::val].Field[crate::cell::UnsafeCell::value]", "value", "dfc-generated"] - - ["lang:std", "::new", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::does_clear", "Argument[self].Field[crate::sys_common::process::CommandEnv::clear]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::from_char", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::from_u32", "Argument[0]", "ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::sys_common::wtf8::CodePoint::value]", "value", "dfc-generated"] - ["lang:std", "::from_u32_unchecked", "Argument[0]", "ReturnValue.Field[crate::sys_common::wtf8::CodePoint::value]", "value", "dfc-generated"] + - ["lang:std", "::to_lead_surrogate", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::to_trail_surrogate", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::to_u32", "Argument[self].Field[crate::sys_common::wtf8::CodePoint::value]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::next", "Argument[self].Field[crate::sys_common::wtf8::EncodeWide::extra]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:std", "::index", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::sys_common::wtf8::Wtf8::bytes]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_bytes", "Argument[self].Field[crate::sys_common::wtf8::Wtf8::bytes]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::ascii_byte_at", "Argument[self].Field[crate::sys_common::wtf8::Wtf8::bytes].Element", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::from_bytes_unchecked", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::from_str", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::from_bytes_unchecked", "Argument[0]", "ReturnValue.Field[crate::sys_common::wtf8::Wtf8Buf::bytes]", "value", "dfc-generated"] + - ["lang:std", "::into_bytes", "Argument[self].Field[crate::sys_common::wtf8::Wtf8Buf::bytes]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::into_string", "Argument[self]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] + - ["lang:std", "::next", "Argument[self]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "::name", "Argument[0]", "Argument[self].Field[crate::thread::Builder::name].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:std", "::name", "Argument[0]", "ReturnValue.Field[crate::thread::Builder::name].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:std", "::name", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::no_hooks", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::stack_size", "Argument[0]", "Argument[self].Field[crate::thread::Builder::stack_size].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] + - ["lang:std", "::stack_size", "Argument[0]", "ReturnValue.Field[crate::thread::Builder::stack_size].Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - ["lang:std", "::stack_size", "Argument[self]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[0].Field[crate::thread::JoinInner::native]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_inner", "Argument[self].Field[crate::thread::JoinHandle(0)].Field[crate::thread::JoinInner::native]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[0].Field[crate::thread::JoinInner::native]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::thread::JoinHandle(0)].Field[crate::thread::JoinInner::native]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::thread", "Argument[self].Field[0].Field[crate::thread::JoinInner::thread]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::thread", "Argument[self].Field[crate::thread::JoinHandle(0)].Field[crate::thread::JoinInner::thread]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::as_u64", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::as_u64", "Argument[self].Field[crate::thread::ThreadId(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::new", "Argument[0]", "ReturnValue.Field[crate::thread::local::LocalKey::inner]", "value", "dfc-generated"] - ["lang:std", "::try_with", "Argument[0].ReturnValue", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] - ["lang:std", "::with", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::with_borrow", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::with_borrow_mut", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::thread", "Argument[self].Field[0].Field[crate::thread::JoinInner::thread]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::thread", "Argument[self].Field[crate::thread::scoped::ScopedJoinHandle(0)].Field[crate::thread::JoinInner::thread]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "::as_cstr", "Argument[self].Field[crate::thread::thread_name_string::ThreadNameString::inner]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "::add_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:std", "::sub_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:std", "::elapsed", "Argument[self]", "ReturnValue", "taint", "df-generated"] @@ -274,7 +579,10 @@ extensions: - ["lang:std", "::sub_assign", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:std", "::from_inner", "Argument[0]", "ReturnValue.Field[crate::time::SystemTime(0)]", "value", "dfc-generated"] - ["lang:std", "::into_inner", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::into_inner", "Argument[self].Field[crate::time::SystemTime(0)]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::duration", "Argument[self].Field[0]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::duration", "Argument[self].Field[crate::time::SystemTimeError(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "::copy_from", "Argument[0]", "Argument[self]", "taint", "df-generated"] - ["lang:std", "::fract", "Argument[self]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::rem_euclid", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "::rem_euclid", "Argument[self]", "ReturnValue", "taint", "df-generated"] @@ -290,25 +598,26 @@ extensions: - ["lang:std", "::as_raw_fd", "Argument[self].Reference", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::from_raw_fd", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "::into_raw_fd", "Argument[self]", "ReturnValue", "value", "dfc-generated"] - - ["lang:std", "<{486}::StaticStrPayload as crate::panic::PanicPayload>::as_str", "Argument[self].Field[0]", "ReturnValue.Field[crate::option::Option::Some(0)]", "value", "dfc-generated"] - - ["lang:std", "<{486}::StaticStrPayload as crate::panic::PanicPayload>::get", "Argument[self].Field[0]", "ReturnValue.Reference", "value", "dfc-generated"] - - ["lang:std", "<{491}::RewrapBox as crate::panic::PanicPayload>::get", "Argument[self].Field[0].Reference", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "crate::backtrace::helper::lazy_resolve", "Argument[0]", "ReturnValue", "value", "dfc-generated"] - - ["lang:std", "crate::io::append_to_string", "Argument[1].ReturnValue.Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:std", "crate::io::append_to_string", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - - ["lang:std", "crate::io::default_read_buf", "Argument[0].ReturnValue.Field[crate::option::Option::Some(0)]", "ReturnValue", "value", "dfc-generated"] - - ["lang:std", "crate::io::default_read_buf", "Argument[0].ReturnValue.Field[crate::result::Result::Ok(0)]", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "crate::io::default_read_buf", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "crate::io::default_read_exact", "Argument[0]", "Argument[1]", "taint", "df-generated"] - ["lang:std", "crate::io::default_read_vectored", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "crate::io::default_write_vectored", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] + - ["lang:std", "crate::io::read_to_string", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "crate::io::util::repeat", "Argument[0]", "ReturnValue.Field[crate::io::util::Repeat::byte]", "value", "dfc-generated"] - ["lang:std", "crate::sync::poison::map_result", "Argument[0]", "Argument[1]", "taint", "df-generated"] - ["lang:std", "crate::sync::poison::map_result", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "crate::sync::poison::map_result", "Argument[1]", "ReturnValue", "taint", "df-generated"] + - ["lang:std", "crate::sync::poison::mutex::guard_lock", "Argument[0].Field[crate::sync::poison::mutex::MutexGuard::lock].Field[crate::sync::poison::mutex::Mutex::inner]", "ReturnValue.Reference", "value", "dfc-generated"] + - ["lang:std", "crate::sync::poison::mutex::guard_poison", "Argument[0].Field[crate::sync::poison::mutex::MutexGuard::lock].Field[crate::sync::poison::mutex::Mutex::poison]", "ReturnValue.Reference", "value", "dfc-generated"] - ["lang:std", "crate::sys::backtrace::__rust_begin_short_backtrace", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "crate::sys::backtrace::__rust_end_short_backtrace", "Argument[0].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "crate::sys::pal::common::small_c_string::run_path_with_cstr", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "crate::sys::pal::common::small_c_string::run_with_cstr", "Argument[1].ReturnValue", "ReturnValue", "value", "dfc-generated"] - ["lang:std", "crate::sys::pal::unix::cvt", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "value", "dfc-generated"] + - ["lang:std", "crate::sys::pal::unix::pipe::read2", "Argument[0]", "Argument[1]", "taint", "df-generated"] + - ["lang:std", "crate::sys::pal::unix::pipe::read2", "Argument[2]", "Argument[3]", "taint", "df-generated"] - ["lang:std", "crate::sys_common::ignore_notfound", "Argument[0].Field[crate::result::Result::Err(0)]", "ReturnValue.Field[crate::result::Result::Err(0)]", "value", "dfc-generated"] - ["lang:std", "crate::sys_common::mul_div_u64", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["lang:std", "crate::sys_common::mul_div_u64", "Argument[1]", "ReturnValue", "taint", "df-generated"] diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index 6c2a7c2ba85b..85d42df2ca3f 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -862,7 +862,6 @@ localStep | main.rs:577:36:577:41 | [post] MacroExpr | main.rs:577:36:577:41 | [post] ...::new(...) | storeStep | file://:0:0:0:0 | [summary] to write: Argument[0].Field[crate::option::Option::Some(0)] in lang:core::_::::zip_with | Some | file://:0:0:0:0 | [post] [summary param] 0 in lang:core::_::::zip_with | -| file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0].Reference in lang:alloc::_::::retain | &ref | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0] in lang:alloc::_::::retain | | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0].Reference in lang:alloc::_::::retain_mut | &ref | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0] in lang:alloc::_::::retain_mut | | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0].Reference in lang:core::_::::take_if | &ref | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0] in lang:core::_::::take_if | | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[1].Reference in lang:core::_::crate::num::flt2dec::to_exact_exp_str | &ref | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[1] in lang:core::_::crate::num::flt2dec::to_exact_exp_str | @@ -871,6 +870,7 @@ storeStep | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:alloc::_::crate::collections::btree::mem::replace | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:alloc::_::crate::collections::btree::mem::replace | | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:alloc::_::crate::collections::btree::mem::take_mut | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:alloc::_::crate::collections::btree::mem::take_mut | | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:core::_::crate::mem::replace | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:core::_::crate::mem::replace | +| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:core::_::crate::ptr::replace | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:core::_::crate::ptr::replace | | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:core::_::crate::ptr::write | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:core::_::crate::ptr::write | | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:core::_::crate::ptr::write_unaligned | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:core::_::crate::ptr::write_unaligned | | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:core::_::crate::ptr::write_volatile | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:core::_::crate::ptr::write_volatile | @@ -906,11 +906,10 @@ storeStep | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0] in lang:proc_macro::_::crate::bridge::client::state::set | function argument at 0 | file://:0:0:0:0 | [post] [summary param] 1 in lang:proc_macro::_::crate::bridge::client::state::set | | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0].Reference in lang:core::_::::filter_map | &ref | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0] in lang:core::_::::filter_map | | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0].Reference in lang:core::_::::map | &ref | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0] in lang:core::_::::map | -| file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0].Reference in lang:core::_::::map_split | &ref | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0] in lang:core::_::::map_split | | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0].Reference in lang:core::_::::filter_map | &ref | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0] in lang:core::_::::filter_map | | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0].Reference in lang:core::_::::map | &ref | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0] in lang:core::_::::map | -| file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0].Reference in lang:core::_::::map_split | &ref | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0] in lang:core::_::::map_split | | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0].Reference in lang:std::_::::wait_while | &ref | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0] in lang:std::_::::wait_while | +| file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[1].Reference in lang:core::_::crate::slice::sort::stable::sort | &ref | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[1] in lang:core::_::crate::slice::sort::stable::sort | | file://:0:0:0:0 | [summary] to write: Argument[1].Reference in lang:core::_::<_ as crate::clone::uninit::CopySpec>::clone_one | &ref | file://:0:0:0:0 | [post] [summary param] 1 in lang:core::_::<_ as crate::clone::uninit::CopySpec>::clone_one | | file://:0:0:0:0 | [summary] to write: Argument[1].Reference in lang:std::_::crate::io::BufRead::read_until | &ref | file://:0:0:0:0 | [post] [summary param] 1 in lang:std::_::crate::io::BufRead::read_until | | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[0].Reference in lang:core::_::crate::cmp::max_by | &ref | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[0] in lang:core::_::crate::cmp::max_by | @@ -924,6 +923,8 @@ storeStep | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[1].Reference in lang:core::_::crate::cmp::min_by | &ref | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[1] in lang:core::_::crate::cmp::min_by | | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[1].Reference in lang:core::_::crate::cmp::minmax_by | &ref | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[1] in lang:core::_::crate::cmp::minmax_by | | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[1].Reference in lang:core::_::crate::slice::sort::shared::smallsort::sort4_stable | &ref | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[1] in lang:core::_::crate::slice::sort::shared::smallsort::sort4_stable | +| file://:0:0:0:0 | [summary] to write: Argument[3].Parameter[1].Reference in lang:core::_::crate::slice::sort::stable::drift::sort | &ref | file://:0:0:0:0 | [summary] to write: Argument[3].Parameter[1] in lang:core::_::crate::slice::sort::stable::drift::sort | +| file://:0:0:0:0 | [summary] to write: Argument[4].Parameter[1].Reference in lang:core::_::crate::slice::sort::stable::quicksort::quicksort | &ref | file://:0:0:0:0 | [summary] to write: Argument[4].Parameter[1] in lang:core::_::crate::slice::sort::stable::quicksort::quicksort | | file://:0:0:0:0 | [summary] to write: Argument[self].Element in lang:core::_::::for_each | element | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::::for_each | | file://:0:0:0:0 | [summary] to write: Argument[self].Element in lang:core::_::::map | element | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::::map | | file://:0:0:0:0 | [summary] to write: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::for_each | element | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::for_each | @@ -931,7 +932,6 @@ storeStep | file://:0:0:0:0 | [summary] to write: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::and_then | Some | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::::and_then | | file://:0:0:0:0 | [summary] to write: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::is_none_or | Some | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::::is_none_or | | file://:0:0:0:0 | [summary] to write: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::is_some_and | Some | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::::is_some_and | -| file://:0:0:0:0 | [summary] to write: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::map | Some | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::::map | | file://:0:0:0:0 | [summary] to write: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::map_or | Some | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::::map_or | | file://:0:0:0:0 | [summary] to write: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::map_or_else | Some | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::::map_or_else | | file://:0:0:0:0 | [summary] to write: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::zip_with | Some | file://:0:0:0:0 | [post] [summary param] self in lang:core::_::::zip_with | @@ -971,64 +971,56 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Element in lang:core::_::crate::cmp::minmax_by | element | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::crate::cmp::minmax_by | | file://:0:0:0:0 | [summary] to write: ReturnValue.Element in lang:core::_::crate::cmp::minmax_by_key | element | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::crate::cmp::minmax_by_key | | file://:0:0:0:0 | [summary] to write: ReturnValue.Element in lang:core::_::crate::iter::traits::iterator::Iterator::collect | element | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::crate::iter::traits::iterator::Iterator::collect | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Element in lang:core::_::crate::unicode::unicode_data::conversions::to_lower | element | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::crate::unicode::unicode_data::conversions::to_lower | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Element in lang:core::_::crate::unicode::unicode_data::conversions::to_upper | element | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::crate::unicode::unicode_data::conversions::to_upper | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::<[_]>::align_to | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<[_]>::align_to | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::<[_]>::align_to_mut | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<[_]>::align_to_mut | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::<[_]>::as_simd | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<[_]>::as_simd | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::<[_]>::as_simd_mut | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<[_]>::as_simd_mut | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::<[_]>::partition_dedup | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<[_]>::partition_dedup | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::<[_]>::partition_dedup_by | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<[_]>::partition_dedup_by | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::<[_]>::partition_dedup_by_key | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<[_]>::partition_dedup_by_key | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::div_rem_small | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::div_rem_small | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::div_rem_small | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::div_rem_small | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::unzip | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::unzip | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_abs | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_abs | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_div | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_div | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_div_euclid | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_div_euclid | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_abs | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_abs | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_div | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_div | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_div_euclid | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_div_euclid | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_abs | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_abs | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_div | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_div | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_div_euclid | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_div_euclid | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_abs | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_abs | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_div | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_div | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_div_euclid | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_div_euclid | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_abs | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_abs | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_div | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_div | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_div_euclid | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_div_euclid | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_abs | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_abs | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_div | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_div | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::overflowing_div_euclid | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::overflowing_div_euclid | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:std::_::::into_parts | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::::into_parts | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0].Field[crate::option::Option::Some(0)] in lang:core::_::::unzip | Some | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[0] in lang:core::_::::unzip | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[1] in lang:alloc::_::::find_lower_bound_edge | tuple.1 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::find_lower_bound_edge | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[1] in lang:alloc::_::::find_upper_bound_edge | tuple.1 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::find_upper_bound_edge | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[1] in lang:core::_::::unzip | tuple.1 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::unzip | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[1] in lang:core::_::crate::slice::sort::shared::find_existing_run | tuple.1 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::crate::slice::sort::shared::find_existing_run | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[1] in lang:std::_::::into_parts | tuple.1 | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::::into_parts | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[1].Field[crate::option::Option::Some(0)] in lang:core::_::::unzip | Some | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[1] in lang:core::_::::unzip | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::then | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::then | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::then_some | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::then_some | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::nth_back | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::nth_back | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::nth_back | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::nth_back | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::get | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::get | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::get_mut | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::get_mut | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::clone | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::clone | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::from | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::from | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::from_output | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::from_output | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::and_then | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::and_then | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::as_mut | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::as_mut | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::as_ref | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::as_ref | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::cloned | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::cloned | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::copied | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::copied | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::map | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::map | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::zip | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::zip | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::zip_with | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::zip_with | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::nth | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::nth | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::nth | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::nth | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::nth | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::nth | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::err | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::err | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::ok | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::ok | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::transpose | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::transpose | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::last | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::last | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::next | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::next | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::nth | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::nth | +| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::nth | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::nth | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::matching | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::matching | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::checked_abs | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::checked_abs | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::checked_next_multiple_of | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::checked_next_multiple_of | @@ -1051,11 +1043,8 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::crate::iter::traits::iterator::Iterator::next | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::crate::iter::traits::iterator::Iterator::next | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::crate::iter::traits::iterator::Iterator::nth | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::crate::iter::traits::iterator::Iterator::nth | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:proc_macro::_::::next | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:proc_macro::_::::next | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:std::_::<{486}::StaticStrPayload as crate::panic::PanicPayload>::as_str | Some | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<{486}::StaticStrPayload as crate::panic::PanicPayload>::as_str | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Field[0] in lang:core::_::::map | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::map | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Field[0] in lang:core::_::::zip | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::zip | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Field[0] in lang:core::_::::matching | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::matching | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Field[1] in lang:core::_::::map | tuple.1 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::map | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Field[1] in lang:core::_::::zip | tuple.1 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::zip | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Field[1] in lang:core::_::::matching | tuple.1 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::matching | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)].Field[crate::result::Result::Err(0)] in lang:core::_::::transpose | Err | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::transpose | @@ -1067,8 +1056,6 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:alloc::_::::downcast | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::downcast | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:alloc::_::::left_kv | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::left_kv | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:alloc::_::::right_kv | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::right_kv | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:alloc::_::::ascend | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::ascend | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:alloc::_::::choose_parent_kv | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::choose_parent_kv | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:alloc::_::::try_from | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::try_from | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:alloc::_::::downcast | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::downcast | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:alloc::_::::try_unwrap | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::try_unwrap | @@ -1084,7 +1071,6 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:core::_::::ok_or | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::ok_or | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:core::_::::ok_or_else | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::ok_or_else | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:core::_::::transpose | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::transpose | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:core::_::::clone | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::clone | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:core::_::::and | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::and | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:core::_::::and_then | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::and_then | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:core::_::::as_deref | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::as_deref | @@ -1107,7 +1093,6 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:std::_::::try_map | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::::try_map | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:std::_::::try_map | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::::try_map | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:std::_::::into_string | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::::into_string | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:std::_::crate::io::append_to_string | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::crate::io::append_to_string | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:std::_::crate::sys_common::ignore_notfound | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::crate::sys_common::ignore_notfound | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:std::_::crate::thread::current::set_current | Err | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::crate::thread::current::set_current | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)].Field[1] in lang:core::_::::try_insert | tuple.1 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:core::_::::try_insert | @@ -1117,7 +1102,6 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)].Reference in lang:core::_::::as_mut | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:core::_::::as_mut | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)].Reference in lang:core::_::::as_ref | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:core::_::::as_ref | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:alloc::_::::search_tree_for_bifurcation | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::search_tree_for_bifurcation | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:alloc::_::::from_str | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::from_str | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:alloc::_::::parse | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::parse | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::align_to | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::align_to | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::array | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::array | @@ -1126,11 +1110,9 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::from_size_align | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::from_size_align | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::repeat | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::repeat | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::repeat_packed | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::repeat_packed | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_insert | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::try_insert | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::ok_or | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::ok_or | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::ok_or_else | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::ok_or_else | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::transpose | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::transpose | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::clone | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::clone | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::from_output | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::from_output | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::as_mut | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::as_mut | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::as_ref | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::::as_ref | @@ -1167,7 +1149,6 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:std::_::::wait_timeout_while | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::::wait_timeout_while | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)] in lang:core::_::::transpose | Some | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::transpose | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | Some | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::::chunk | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Reference in lang:core::_::::try_insert | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_insert | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Reference in lang:core::_::::as_mut | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::as_mut | | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Reference in lang:core::_::::as_ref | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::as_ref | | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:alloc::_::::borrow | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::borrow | @@ -1203,7 +1184,6 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:alloc::_::::as_ref | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::as_ref | | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:alloc::_::::borrow | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::borrow | | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:alloc::_::::borrow_mut | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::::borrow_mut | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:alloc::_::<{766}::StringError as crate::error::Error>::description | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::<{766}::StringError as crate::error::Error>::description | | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:core::_::<&_ as crate::borrow::Borrow>::borrow | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<&_ as crate::borrow::Borrow>::borrow | | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:core::_::<&mut _ as crate::borrow::Borrow>::borrow | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<&mut _ as crate::borrow::Borrow>::borrow | | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:core::_::<&mut _ as crate::borrow::BorrowMut>::borrow_mut | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<&mut _ as crate::borrow::BorrowMut>::borrow_mut | @@ -1249,8 +1229,6 @@ storeStep | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:std::_::::as_inner | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::::as_inner | | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:std::_::::as_inner_mut | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::::as_inner_mut | | file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:std::_::::as_file_desc | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::::as_file_desc | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:std::_::<{486}::StaticStrPayload as crate::panic::PanicPayload>::get | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<{486}::StaticStrPayload as crate::panic::PanicPayload>::get | -| file://:0:0:0:0 | [summary] to write: ReturnValue.Reference in lang:std::_::<{491}::RewrapBox as crate::panic::PanicPayload>::get | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<{491}::RewrapBox as crate::panic::PanicPayload>::get | | main.rs:97:14:97:22 | source(...) | tuple.0 | main.rs:97:13:97:26 | TupleExpr | | main.rs:97:25:97:25 | 2 | tuple.1 | main.rs:97:13:97:26 | TupleExpr | | main.rs:103:14:103:14 | 2 | tuple.0 | main.rs:103:13:103:30 | TupleExpr | @@ -1341,11 +1319,13 @@ storeStep | main.rs:522:15:522:15 | b | &ref | main.rs:522:14:522:15 | &b | | main.rs:545:27:545:27 | 0 | Some | main.rs:545:22:545:28 | Some(...) | readStep +| file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::::clone_from | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:alloc::_::::clone_from | | file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::::allocator | tuple.1 | file://:0:0:0:0 | [summary] read: Argument[0].Field[1] in lang:alloc::_::::allocator | | file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::::as_mut_ptr | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:alloc::_::::as_mut_ptr | | file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::::as_ptr | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:alloc::_::::as_ptr | | file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::::into_inner | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:alloc::_::::into_inner | | file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::::visit_nodes_in_order | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:alloc::_::::visit_nodes_in_order | +| file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::::fold | Ok | file://:0:0:0:0 | [summary] read: Argument[0].Field[crate::result::Result::Ok(0)] in lang:alloc::_::::fold | | file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::::try_rfold | Ok | file://:0:0:0:0 | [summary] read: Argument[0].Field[crate::result::Result::Ok(0)] in lang:alloc::_::::try_rfold | | file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::::try_rfold | Some | file://:0:0:0:0 | [summary] read: Argument[0].Field[crate::option::Option::Some(0)] in lang:alloc::_::::try_rfold | | file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::::try_fold | Ok | file://:0:0:0:0 | [summary] read: Argument[0].Field[crate::result::Result::Ok(0)] in lang:alloc::_::::try_fold | @@ -1360,38 +1340,27 @@ readStep | file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::crate::collections::btree::mem::replace | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:alloc::_::crate::collections::btree::mem::replace | | file://:0:0:0:0 | [summary param] 0 in lang:alloc::_::crate::collections::btree::mem::take_mut | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:alloc::_::crate::collections::btree::mem::take_mut | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::<_ as crate::array::SpecArrayClone>::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::<_ as crate::array::SpecArrayClone>::clone | +| file://:0:0:0:0 | [summary param] 0 in lang:core::_::<_ as crate::clone::uninit::CopySpec>::clone_one | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::<_ as crate::clone::uninit::CopySpec>::clone_one | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::then | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::then | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::update | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::update | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::filter_map | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::filter_map | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::map | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::map | -| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::map_split | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::map_split | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::filter_map | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::filter_map | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::map | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::map | -| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::map_split | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::map_split | -| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::get_or_init | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::get_or_init | -| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::get_or_try_init | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::get_or_try_init | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::then_with | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::then_with | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::with_copy | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::with_copy | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::fold | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[0].Field[0] in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::try_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::try_fold | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::try_fold | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::spec_fold | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[0].Field[0] in lang:core::_::::spec_fold | -| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::rfold | -| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::fold | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::from | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::from | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::and_then | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::and_then | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::is_none_or | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::is_none_or | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::is_some_and | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::is_some_and | -| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::map | element | file://:0:0:0:0 | [summary] read: Argument[0].Element in lang:core::_::::map | -| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::map | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::map | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::map_or_else | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::map_or_else | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::ok_or_else | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::ok_or_else | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::or_else | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::or_else | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::unwrap_or_else | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::unwrap_or_else | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::zip | Some | file://:0:0:0:0 | [summary] read: Argument[0].Field[crate::option::Option::Some(0)] in lang:core::_::::zip | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::zip_with | Some | file://:0:0:0:0 | [summary] read: Argument[0].Field[crate::option::Option::Some(0)] in lang:core::_::::zip_with | -| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::and_then | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::and_then | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::is_err_and | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::is_err_and | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::is_ok_and | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::is_ok_and | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::map | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::map | @@ -1400,6 +1369,8 @@ readStep | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::or_else | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::or_else | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::unwrap_or_else | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::unwrap_or_else | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::call | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[0].Field[0] in lang:core::_::::call | +| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::clone_from | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::clone_from | +| file://:0:0:0:0 | [summary param] 0 in lang:core::_::::clone_from | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::clone_from | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::index | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::index | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::::index_mut | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::index_mut | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::crate::mem::copy | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::crate::mem::copy | @@ -1411,6 +1382,9 @@ readStep | file://:0:0:0:0 | [summary param] 0 in lang:core::_::crate::ptr::read_volatile | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::crate::ptr::read_volatile | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::crate::ptr::replace | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::crate::ptr::replace | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::crate::slice::sort::shared::smallsort::sort4_stable | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::crate::slice::sort::shared::smallsort::sort4_stable | +| file://:0:0:0:0 | [summary param] 0 in lang:core::_::crate::slice::sort::stable::drift::sort | element | file://:0:0:0:0 | [summary] read: Argument[0].Element in lang:core::_::crate::slice::sort::stable::drift::sort | +| file://:0:0:0:0 | [summary param] 0 in lang:core::_::crate::slice::sort::stable::quicksort::quicksort | element | file://:0:0:0:0 | [summary] read: Argument[0].Element in lang:core::_::crate::slice::sort::stable::quicksort::quicksort | +| file://:0:0:0:0 | [summary param] 0 in lang:core::_::crate::slice::sort::stable::sort | element | file://:0:0:0:0 | [summary] read: Argument[0].Element in lang:core::_::crate::slice::sort::stable::sort | | file://:0:0:0:0 | [summary param] 0 in lang:core::_::crate::str::validations::next_code_point | element | file://:0:0:0:0 | [summary] read: Argument[0].Element in lang:core::_::crate::str::validations::next_code_point | | file://:0:0:0:0 | [summary param] 0 in lang:proc_macro::_::<&[u8] as crate::bridge::rpc::DecodeMut>::decode | element | file://:0:0:0:0 | [summary] read: Argument[0].Element in lang:proc_macro::_::<&[u8] as crate::bridge::rpc::DecodeMut>::decode | | file://:0:0:0:0 | [summary param] 0 in lang:proc_macro::_::::decode | element | file://:0:0:0:0 | [summary] read: Argument[0].Element in lang:proc_macro::_::::decode | @@ -1420,7 +1394,6 @@ readStep | file://:0:0:0:0 | [summary param] 0 in lang:std::_::::advance_slices | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:std::_::::advance_slices | | file://:0:0:0:0 | [summary param] 0 in lang:std::_::::advance_slices | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:std::_::::advance_slices | | file://:0:0:0:0 | [summary param] 0 in lang:std::_::::from | tuple.1 | file://:0:0:0:0 | [summary] read: Argument[0].Field[1] in lang:std::_::::from | -| file://:0:0:0:0 | [summary param] 0 in lang:std::_::::new | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:std::_::::new | | file://:0:0:0:0 | [summary param] 0 in lang:std::_::::wait_timeout_while | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:std::_::::wait_timeout_while | | file://:0:0:0:0 | [summary param] 0 in lang:std::_::::wait_while | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:std::_::::wait_while | | file://:0:0:0:0 | [summary param] 0 in lang:std::_::::bind | Ok | file://:0:0:0:0 | [summary] read: Argument[0].Field[crate::result::Result::Ok(0)] in lang:std::_::::bind | @@ -1433,7 +1406,8 @@ readStep | file://:0:0:0:0 | [summary param] 0 in lang:std::_::::connect | Some | file://:0:0:0:0 | [summary] read: Argument[0].Field[crate::option::Option::Some(0)] in lang:std::_::::connect | | file://:0:0:0:0 | [summary param] 0 in lang:std::_::::try_with | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:std::_::::try_with | | file://:0:0:0:0 | [summary param] 0 in lang:std::_::::with | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:std::_::::with | -| file://:0:0:0:0 | [summary param] 0 in lang:std::_::crate::io::default_read_buf | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:std::_::crate::io::default_read_buf | +| file://:0:0:0:0 | [summary param] 0 in lang:std::_::::with_borrow | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:std::_::::with_borrow | +| file://:0:0:0:0 | [summary param] 0 in lang:std::_::::with_borrow_mut | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:std::_::::with_borrow_mut | | file://:0:0:0:0 | [summary param] 0 in lang:std::_::crate::io::default_read_vectored | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:std::_::crate::io::default_read_vectored | | file://:0:0:0:0 | [summary param] 0 in lang:std::_::crate::io::default_write_vectored | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:std::_::crate::io::default_write_vectored | | file://:0:0:0:0 | [summary param] 0 in lang:std::_::crate::sys::backtrace::__rust_begin_short_backtrace | function return | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:std::_::crate::sys::backtrace::__rust_begin_short_backtrace | @@ -1447,72 +1421,43 @@ readStep | file://:0:0:0:0 | [summary param] 1 in lang:alloc::_::crate::collections::btree::mem::replace | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:alloc::_::crate::collections::btree::mem::replace | | file://:0:0:0:0 | [summary param] 1 in lang:alloc::_::crate::collections::btree::mem::take_mut | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:alloc::_::crate::collections::btree::mem::take_mut | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::<&mut _ as crate::iter::traits::double_ended::DoubleEndedIteratorRefSpec>::spec_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::<&mut _ as crate::iter::traits::double_ended::DoubleEndedIteratorRefSpec>::spec_rfold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::<&mut _ as crate::iter::traits::double_ended::DoubleEndedIteratorRefSpec>::spec_try_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::<&mut _ as crate::iter::traits::double_ended::DoubleEndedIteratorRefSpec>::spec_try_rfold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::<&mut _ as crate::iter::traits::iterator::IteratorRefSpec>::spec_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::<&mut _ as crate::iter::traits::iterator::IteratorRefSpec>::spec_fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::<&mut _ as crate::iter::traits::iterator::IteratorRefSpec>::spec_try_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::<&mut _ as crate::iter::traits::iterator::IteratorRefSpec>::spec_try_fold | +| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::rfold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::rfold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::rfold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::rfold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::rfold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::rfold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::rfold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::rfold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::rfold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::rfold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::rfold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | +| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::rfold | +| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::rfold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::spec_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::spec_rfold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::spec_try_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::spec_try_rfold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::spec_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::spec_fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::rfold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::spec_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::spec_fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::rfold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::spec_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::spec_fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_rfold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::try_fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::map_or | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::map_or | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::map_or_else | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::map_or_else | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::zip_with | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::zip_with | @@ -1521,11 +1466,28 @@ readStep | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::fold | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::crate::array::drain::drain_array_with | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::crate::array::drain::drain_array_with | | file://:0:0:0:0 | [summary param] 1 in lang:core::_::crate::slice::sort::shared::find_existing_run | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::crate::slice::sort::shared::find_existing_run | | file://:0:0:0:0 | [summary param] 1 in lang:proc_macro::_::crate::bridge::client::state::set | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:proc_macro::_::crate::bridge::client::state::set | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | +| file://:0:0:0:0 | [summary param] 1 in lang:std::_::::fold | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::::fold | | file://:0:0:0:0 | [summary param] 1 in lang:std::_::crate::io::append_to_string | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::crate::io::append_to_string | | file://:0:0:0:0 | [summary param] 1 in lang:std::_::crate::sys::pal::common::small_c_string::run_path_with_cstr | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::crate::sys::pal::common::small_c_string::run_path_with_cstr | | file://:0:0:0:0 | [summary param] 1 in lang:std::_::crate::sys::pal::common::small_c_string::run_with_cstr | function return | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::crate::sys::pal::common::small_c_string::run_with_cstr | @@ -1535,6 +1497,8 @@ readStep | file://:0:0:0:0 | [summary param] 5 in lang:core::_::crate::num::flt2dec::to_exact_exp_str | element | file://:0:0:0:0 | [summary] read: Argument[5].Element in lang:core::_::crate::num::flt2dec::to_exact_exp_str | | file://:0:0:0:0 | [summary param] self in lang:alloc::_::<&&str as crate::string::SpecToString>::spec_to_string | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::<&&str as crate::string::SpecToString>::spec_to_string | | file://:0:0:0:0 | [summary param] self in lang:alloc::_::<&str as crate::string::SpecToString>::spec_to_string | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::<&str as crate::string::SpecToString>::spec_to_string | +| file://:0:0:0:0 | [summary param] self in lang:alloc::_::<_ as crate::borrow::ToOwned>::clone_into | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::<_ as crate::borrow::ToOwned>::clone_into | +| file://:0:0:0:0 | [summary param] self in lang:alloc::_::<_ as crate::borrow::ToOwned>::to_owned | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::<_ as crate::borrow::ToOwned>::to_owned | | file://:0:0:0:0 | [summary param] self in lang:alloc::_::::borrow | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::::borrow | | file://:0:0:0:0 | [summary param] self in lang:alloc::_::::borrow | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::::borrow | | file://:0:0:0:0 | [summary param] self in lang:alloc::_::::borrow_mut | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::::borrow_mut | @@ -1553,8 +1517,6 @@ readStep | file://:0:0:0:0 | [summary param] self in lang:alloc::_::::as_bytes | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:alloc::_::::as_bytes | | file://:0:0:0:0 | [summary param] self in lang:alloc::_::::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::::clone | | file://:0:0:0:0 | [summary param] self in lang:alloc::_::::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::::clone | -| file://:0:0:0:0 | [summary param] self in lang:alloc::_::::split_off | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::::split_off | -| file://:0:0:0:0 | [summary param] self in lang:alloc::_::::retain | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:alloc::_::::retain | | file://:0:0:0:0 | [summary param] self in lang:alloc::_::::retain_mut | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:alloc::_::::retain_mut | | file://:0:0:0:0 | [summary param] self in lang:alloc::_::::as_c_str | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::::as_c_str | | file://:0:0:0:0 | [summary param] self in lang:alloc::_::::into_vec | tuple.1 | file://:0:0:0:0 | [summary] read: Argument[self].Field[1] in lang:alloc::_::::into_vec | @@ -1571,10 +1533,13 @@ readStep | file://:0:0:0:0 | [summary param] self in lang:alloc::_::::as_ref | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::::as_ref | | file://:0:0:0:0 | [summary param] self in lang:alloc::_::::borrow | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:alloc::_::::borrow | | file://:0:0:0:0 | [summary param] self in lang:alloc::_::::borrow_mut | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:alloc::_::::borrow_mut | -| file://:0:0:0:0 | [summary param] self in lang:alloc::_::<{766}::StringError as crate::error::Error>::description | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:alloc::_::<{766}::StringError as crate::error::Error>::description | | file://:0:0:0:0 | [summary param] self in lang:core::_::<&_ as crate::borrow::Borrow>::borrow | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::<&_ as crate::borrow::Borrow>::borrow | | file://:0:0:0:0 | [summary param] self in lang:core::_::<&_ as crate::clone::Clone>::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::<&_ as crate::clone::Clone>::clone | | file://:0:0:0:0 | [summary param] self in lang:core::_::<&_ as crate::ops::deref::Deref>::deref | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::<&_ as crate::ops::deref::Deref>::deref | +| file://:0:0:0:0 | [summary param] self in lang:core::_::<&crate::net::ip_addr::Ipv4Addr as crate::ops::bit::BitAnd>::bitand | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::<&crate::net::ip_addr::Ipv4Addr as crate::ops::bit::BitAnd>::bitand | +| file://:0:0:0:0 | [summary param] self in lang:core::_::<&crate::net::ip_addr::Ipv4Addr as crate::ops::bit::BitOr>::bitor | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::<&crate::net::ip_addr::Ipv4Addr as crate::ops::bit::BitOr>::bitor | +| file://:0:0:0:0 | [summary param] self in lang:core::_::<&crate::net::ip_addr::Ipv6Addr as crate::ops::bit::BitAnd>::bitand | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::<&crate::net::ip_addr::Ipv6Addr as crate::ops::bit::BitAnd>::bitand | +| file://:0:0:0:0 | [summary param] self in lang:core::_::<&crate::net::ip_addr::Ipv6Addr as crate::ops::bit::BitOr>::bitor | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::<&crate::net::ip_addr::Ipv6Addr as crate::ops::bit::BitOr>::bitor | | file://:0:0:0:0 | [summary param] self in lang:core::_::<&mut _ as crate::borrow::Borrow>::borrow | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::<&mut _ as crate::borrow::Borrow>::borrow | | file://:0:0:0:0 | [summary param] self in lang:core::_::<&mut _ as crate::borrow::BorrowMut>::borrow_mut | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::<&mut _ as crate::borrow::BorrowMut>::borrow_mut | | file://:0:0:0:0 | [summary param] self in lang:core::_::<&mut _ as crate::ops::deref::Deref>::deref | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::<&mut _ as crate::ops::deref::Deref>::deref | @@ -1594,13 +1559,7 @@ readStep | file://:0:0:0:0 | [summary param] self in lang:core::_::::index_mut | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::index_mut | | file://:0:0:0:0 | [summary param] self in lang:core::_::::as_bytes | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::as_bytes | | file://:0:0:0:0 | [summary param] self in lang:core::_::::into_inner | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::into_inner | -| file://:0:0:0:0 | [summary param] self in lang:core::_::::fold | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] self in lang:core::_::::rfold | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::rfold | -| file://:0:0:0:0 | [summary param] self in lang:core::_::::try_rfold | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary param] self in lang:core::_::::fold | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::fold | -| file://:0:0:0:0 | [summary param] self in lang:core::_::::try_fold | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary param] self in lang:core::_::::rfold | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::rfold | -| file://:0:0:0:0 | [summary param] self in lang:core::_::::fold | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::fold | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::nth_back | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::nth_back | | file://:0:0:0:0 | [summary param] self in lang:core::_::::nth_back | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::nth_back | | file://:0:0:0:0 | [summary param] self in lang:core::_::::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::::clone | | file://:0:0:0:0 | [summary param] self in lang:core::_::::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::::clone | @@ -1623,7 +1582,6 @@ readStep | file://:0:0:0:0 | [summary param] self in lang:core::_::::insert | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::::insert | | file://:0:0:0:0 | [summary param] self in lang:core::_::::is_none_or | Some | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::is_none_or | | file://:0:0:0:0 | [summary param] self in lang:core::_::::is_some_and | Some | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::is_some_and | -| file://:0:0:0:0 | [summary param] self in lang:core::_::::map | Some | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::map | | file://:0:0:0:0 | [summary param] self in lang:core::_::::map_or | Some | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::map_or | | file://:0:0:0:0 | [summary param] self in lang:core::_::::map_or_else | Some | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::map_or_else | | file://:0:0:0:0 | [summary param] self in lang:core::_::::ok_or | Some | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::ok_or | @@ -1645,8 +1603,9 @@ readStep | file://:0:0:0:0 | [summary param] self in lang:core::_::::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::::clone | | file://:0:0:0:0 | [summary param] self in lang:core::_::::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::::clone | | file://:0:0:0:0 | [summary param] self in lang:core::_::::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::::clone | -| file://:0:0:0:0 | [summary param] self in lang:core::_::::clone | Err | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Err(0)] in lang:core::_::::clone | -| file://:0:0:0:0 | [summary param] self in lang:core::_::::clone | Ok | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Ok(0)] in lang:core::_::::clone | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::nth | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::nth | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::nth | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::nth | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::nth | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::nth | | file://:0:0:0:0 | [summary param] self in lang:core::_::::and | Err | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Err(0)] in lang:core::_::::and | | file://:0:0:0:0 | [summary param] self in lang:core::_::::and_then | Err | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Err(0)] in lang:core::_::::and_then | | file://:0:0:0:0 | [summary param] self in lang:core::_::::and_then | Ok | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Ok(0)] in lang:core::_::::and_then | @@ -1686,11 +1645,13 @@ readStep | file://:0:0:0:0 | [summary param] self in lang:core::_::::unwrap_or_else | Err | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Err(0)] in lang:core::_::::unwrap_or_else | | file://:0:0:0:0 | [summary param] self in lang:core::_::::unwrap_or_else | Ok | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Ok(0)] in lang:core::_::::unwrap_or_else | | file://:0:0:0:0 | [summary param] self in lang:core::_::::unwrap_unchecked | Ok | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Ok(0)] in lang:core::_::::unwrap_unchecked | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::last | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::last | | file://:0:0:0:0 | [summary param] self in lang:core::_::::collect | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::collect | | file://:0:0:0:0 | [summary param] self in lang:core::_::::for_each | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::for_each | | file://:0:0:0:0 | [summary param] self in lang:core::_::::map | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::map | | file://:0:0:0:0 | [summary param] self in lang:core::_::::next | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::next | | file://:0:0:0:0 | [summary param] self in lang:core::_::::nth | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::::nth | +| file://:0:0:0:0 | [summary param] self in lang:core::_::::nth | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::nth | | file://:0:0:0:0 | [summary param] self in lang:core::_::::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::::clone | | file://:0:0:0:0 | [summary param] self in lang:core::_::::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::::clone | | file://:0:0:0:0 | [summary param] self in lang:core::_::::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:core::_::::clone | @@ -1714,6 +1675,8 @@ readStep | file://:0:0:0:0 | [summary param] self in lang:core::_::crate::iter::traits::iterator::Iterator::nth | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:core::_::crate::iter::traits::iterator::Iterator::nth | | file://:0:0:0:0 | [summary param] self in lang:proc_macro::_::::take | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:proc_macro::_::::take | | file://:0:0:0:0 | [summary param] self in lang:proc_macro::_::::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:proc_macro::_::::clone | +| file://:0:0:0:0 | [summary param] self in lang:proc_macro::_::::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:proc_macro::_::::clone | +| file://:0:0:0:0 | [summary param] self in lang:proc_macro::_::::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:proc_macro::_::::clone | | file://:0:0:0:0 | [summary param] self in lang:proc_macro::_::::next | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:proc_macro::_::::next | | file://:0:0:0:0 | [summary param] self in lang:std::_::<&[u8] as crate::io::BufRead>::consume | element | file://:0:0:0:0 | [summary] read: Argument[self].Element in lang:std::_::<&[u8] as crate::io::BufRead>::consume | | file://:0:0:0:0 | [summary param] self in lang:std::_::<&[u8] as crate::io::BufRead>::fill_buf | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:std::_::<&[u8] as crate::io::BufRead>::fill_buf | @@ -1735,8 +1698,6 @@ readStep | file://:0:0:0:0 | [summary param] self in lang:std::_::::error | tuple.1 | file://:0:0:0:0 | [summary] read: Argument[self].Field[1] in lang:std::_::::error | | file://:0:0:0:0 | [summary param] self in lang:std::_::::into_error | tuple.1 | file://:0:0:0:0 | [summary] read: Argument[self].Field[1] in lang:std::_::::into_error | | file://:0:0:0:0 | [summary param] self in lang:std::_::::into_inner | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:std::_::::into_inner | -| file://:0:0:0:0 | [summary param] self in lang:std::_::::into_parts | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:std::_::::into_parts | -| file://:0:0:0:0 | [summary param] self in lang:std::_::::into_parts | tuple.1 | file://:0:0:0:0 | [summary] read: Argument[self].Field[1] in lang:std::_::::into_parts | | file://:0:0:0:0 | [summary param] self in lang:std::_::::as_inner | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:std::_::::as_inner | | file://:0:0:0:0 | [summary param] self in lang:std::_::::into_inner | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:std::_::::into_inner | | file://:0:0:0:0 | [summary param] self in lang:std::_::::as_inner | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:std::_::::as_inner | @@ -1764,97 +1725,39 @@ readStep | file://:0:0:0:0 | [summary param] self in lang:std::_::::into_inner | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:std::_::::into_inner | | file://:0:0:0:0 | [summary param] self in lang:std::_::::duration | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:std::_::::duration | | file://:0:0:0:0 | [summary param] self in lang:std::_::::as_raw_fd | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:std::_::::as_raw_fd | -| file://:0:0:0:0 | [summary param] self in lang:std::_::<{486}::StaticStrPayload as crate::panic::PanicPayload>::as_str | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:std::_::<{486}::StaticStrPayload as crate::panic::PanicPayload>::as_str | -| file://:0:0:0:0 | [summary param] self in lang:std::_::<{486}::StaticStrPayload as crate::panic::PanicPayload>::get | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:std::_::<{486}::StaticStrPayload as crate::panic::PanicPayload>::get | -| file://:0:0:0:0 | [summary param] self in lang:std::_::<{491}::RewrapBox as crate::panic::PanicPayload>::get | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:std::_::<{491}::RewrapBox as crate::panic::PanicPayload>::get | | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:alloc::_::::as_mut_ptr | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference.Reference in lang:alloc::_::::as_mut_ptr | | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:alloc::_::::as_ptr | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference.Reference in lang:alloc::_::::as_ptr | +| file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:alloc::_::::unwrap_or_clone | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference.Reference in lang:alloc::_::::unwrap_or_clone | +| file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:alloc::_::::unwrap_or_clone | &ref | file://:0:0:0:0 | [summary] read: Argument[0].Reference.Reference in lang:alloc::_::::unwrap_or_clone | | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::from | Some | file://:0:0:0:0 | [summary] read: Argument[0].Reference.Field[crate::option::Option::Some(0)] in lang:core::_::::from | | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::index | element | file://:0:0:0:0 | [summary] read: Argument[0].Reference.Element in lang:core::_::::index | | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:core::_::::index_mut | element | file://:0:0:0:0 | [summary] read: Argument[0].Reference.Element in lang:core::_::::index_mut | | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:std::_::::advance_slices | element | file://:0:0:0:0 | [summary] read: Argument[0].Reference.Element in lang:std::_::::advance_slices | | file://:0:0:0:0 | [summary] read: Argument[0].Reference in lang:std::_::::advance_slices | element | file://:0:0:0:0 | [summary] read: Argument[0].Reference.Element in lang:std::_::::advance_slices | -| file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::get_or_init | Ok | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::get_or_init | -| file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::get_or_try_init | Ok | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::get_or_try_init | -| file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::get_or_try_init | Some | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::get_or_try_init | -| file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::try_rfold | Ok | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::try_rfold | Some | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::try_fold | Ok | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:core::_::::try_fold | Some | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:std::_::crate::io::default_read_buf | Ok | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::crate::io::default_read_buf | -| file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue in lang:std::_::crate::io::default_read_buf | Some | file://:0:0:0:0 | [summary] read: Argument[0].ReturnValue.Field[crate::option::Option::Some(0)] in lang:std::_::crate::io::default_read_buf | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::<&mut _ as crate::iter::traits::double_ended::DoubleEndedIteratorRefSpec>::spec_try_rfold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<&mut _ as crate::iter::traits::double_ended::DoubleEndedIteratorRefSpec>::spec_try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::<&mut _ as crate::iter::traits::double_ended::DoubleEndedIteratorRefSpec>::spec_try_rfold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::<&mut _ as crate::iter::traits::double_ended::DoubleEndedIteratorRefSpec>::spec_try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::<&mut _ as crate::iter::traits::iterator::IteratorRefSpec>::spec_try_fold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<&mut _ as crate::iter::traits::iterator::IteratorRefSpec>::spec_try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::<&mut _ as crate::iter::traits::iterator::IteratorRefSpec>::spec_try_fold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::<&mut _ as crate::iter::traits::iterator::IteratorRefSpec>::spec_try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::spec_try_rfold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::spec_try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::spec_try_rfold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::spec_try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_rfold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_rfold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Ok | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:core::_::::try_fold | Some | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::option::Option::Some(0)] in lang:core::_::::try_fold | -| file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue in lang:std::_::crate::io::append_to_string | Err | file://:0:0:0:0 | [summary] read: Argument[1].ReturnValue.Field[crate::result::Result::Err(0)] in lang:std::_::crate::io::append_to_string | | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:alloc::_::::index | element | file://:0:0:0:0 | [summary] read: Argument[self].Field[0].Element in lang:alloc::_::::index | | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:alloc::_::::index_mut | element | file://:0:0:0:0 | [summary] read: Argument[self].Field[0].Element in lang:alloc::_::::index_mut | | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::index | element | file://:0:0:0:0 | [summary] read: Argument[self].Field[0].Element in lang:core::_::::index | | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::index_mut | element | file://:0:0:0:0 | [summary] read: Argument[self].Field[0].Element in lang:core::_::::index_mut | | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::into_inner | Some | file://:0:0:0:0 | [summary] read: Argument[self].Field[0].Field[crate::option::Option::Some(0)] in lang:core::_::::into_inner | -| file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::rfold | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0].Field[0] in lang:core::_::::rfold | -| file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::fold | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[0].Field[0] in lang:core::_::::fold | +| file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::nth | element | file://:0:0:0:0 | [summary] read: Argument[self].Field[0].Element in lang:core::_::::nth | +| file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::nth | element | file://:0:0:0:0 | [summary] read: Argument[self].Field[0].Element in lang:core::_::::nth | +| file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::nth | element | file://:0:0:0:0 | [summary] read: Argument[self].Field[0].Element in lang:core::_::::nth | +| file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:core::_::::nth | element | file://:0:0:0:0 | [summary] read: Argument[self].Field[0].Element in lang:core::_::::nth | | file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:proc_macro::_::::next | element | file://:0:0:0:0 | [summary] read: Argument[self].Field[0].Element in lang:proc_macro::_::::next | -| file://:0:0:0:0 | [summary] read: Argument[self].Field[0] in lang:std::_::<{491}::RewrapBox as crate::panic::PanicPayload>::get | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Field[0].Reference in lang:std::_::<{491}::RewrapBox as crate::panic::PanicPayload>::get | +| file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::clone | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)].Reference in lang:core::_::::clone | +| file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::and_then | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)].Field[0] in lang:core::_::::and_then | +| file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::cloned | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)].Reference in lang:core::_::::cloned | | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::copied | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)].Reference in lang:core::_::::copied | -| file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::map | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)].Field[0] in lang:core::_::::map | | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::transpose | Err | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)].Field[crate::result::Result::Err(0)] in lang:core::_::::transpose | | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::transpose | Ok | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)].Field[crate::result::Result::Ok(0)] in lang:core::_::::transpose | | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::unzip | tuple.0 | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)].Field[0] in lang:core::_::::unzip | | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)] in lang:core::_::::unzip | tuple.1 | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::option::Option::Some(0)].Field[1] in lang:core::_::::unzip | | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Err(0)] in lang:core::_::::unwrap_or_else | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Err(0)].Reference in lang:core::_::::unwrap_or_else | +| file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Ok(0)] in lang:core::_::::cloned | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Ok(0)].Reference in lang:core::_::::cloned | | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Ok(0)] in lang:core::_::::copied | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Ok(0)].Reference in lang:core::_::::copied | | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Ok(0)] in lang:core::_::::transpose | Some | file://:0:0:0:0 | [summary] read: Argument[self].Field[crate::result::Result::Ok(0)].Field[crate::option::Option::Some(0)] in lang:core::_::::transpose | | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::<&&str as crate::string::SpecToString>::spec_to_string | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference.Reference in lang:alloc::_::<&&str as crate::string::SpecToString>::spec_to_string | +| file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::<&str as crate::string::SpecToString>::spec_to_string | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference.Reference in lang:alloc::_::<&str as crate::string::SpecToString>::spec_to_string | | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::::borrow | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference.Reference in lang:alloc::_::::borrow | | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::::borrow | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference.Reference in lang:alloc::_::::borrow | | file://:0:0:0:0 | [summary] read: Argument[self].Reference in lang:alloc::_::::borrow_mut | &ref | file://:0:0:0:0 | [summary] read: Argument[self].Reference.Reference in lang:alloc::_::::borrow_mut | diff --git a/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected b/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected index b5e19855cfa5..df5c5d04a7e0 100644 --- a/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected @@ -2,10 +2,9 @@ models | 1 | Summary: lang:core; ::clone; Argument[self].Field[crate::option::Option::Some(0)]; ReturnValue.Field[crate::option::Option::Some(0)]; value | | 2 | Summary: lang:core; ::unwrap; Argument[self].Field[crate::option::Option::Some(0)]; ReturnValue; value | | 3 | Summary: lang:core; ::zip; Argument[0].Field[crate::option::Option::Some(0)]; ReturnValue.Field[crate::option::Option::Some(0)].Field[1]; value | -| 4 | Summary: lang:core; ::clone; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue.Field[crate::result::Result::Ok(0)]; value | -| 5 | Summary: lang:core; ::unwrap; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value | -| 6 | Summary: lang:core; crate::ptr::read; Argument[0].Reference; ReturnValue; value | -| 7 | Summary: lang:core; crate::ptr::write; Argument[1]; Argument[0].Reference; value | +| 4 | Summary: lang:core; ::unwrap; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value | +| 5 | Summary: lang:core; crate::ptr::read; Argument[0].Reference; ReturnValue; value | +| 6 | Summary: lang:core; crate::ptr::write; Argument[1]; Argument[0].Reference; value | edges | main.rs:12:9:12:9 | a [Some] | main.rs:13:10:13:19 | a.unwrap() | provenance | MaD:2 | | main.rs:12:9:12:9 | a [Some] | main.rs:14:13:14:13 | a [Some] | provenance | | @@ -16,13 +15,12 @@ edges | main.rs:14:9:14:9 | b [Some] | main.rs:15:10:15:19 | b.unwrap() | provenance | MaD:2 | | main.rs:14:13:14:13 | a [Some] | main.rs:14:13:14:21 | a.clone() [Some] | provenance | generated | | main.rs:14:13:14:21 | a.clone() [Some] | main.rs:14:9:14:9 | b [Some] | provenance | | -| main.rs:19:9:19:9 | a [Ok] | main.rs:20:10:20:19 | a.unwrap() | provenance | MaD:5 | +| main.rs:19:9:19:9 | a [Ok] | main.rs:20:10:20:19 | a.unwrap() | provenance | MaD:4 | | main.rs:19:9:19:9 | a [Ok] | main.rs:21:13:21:13 | a [Ok] | provenance | | -| main.rs:19:9:19:9 | a [Ok] | main.rs:21:13:21:21 | a.clone() [Ok] | provenance | MaD:4 | | main.rs:19:9:19:9 | a [Ok] | main.rs:21:13:21:21 | a.clone() [Ok] | provenance | generated | | main.rs:19:31:19:44 | Ok(...) [Ok] | main.rs:19:9:19:9 | a [Ok] | provenance | | | main.rs:19:34:19:43 | source(...) | main.rs:19:31:19:44 | Ok(...) [Ok] | provenance | | -| main.rs:21:9:21:9 | b [Ok] | main.rs:22:10:22:19 | b.unwrap() | provenance | MaD:5 | +| main.rs:21:9:21:9 | b [Ok] | main.rs:22:10:22:19 | b.unwrap() | provenance | MaD:4 | | main.rs:21:13:21:13 | a [Ok] | main.rs:21:13:21:21 | a.clone() [Ok] | provenance | generated | | main.rs:21:13:21:21 | a.clone() [Ok] | main.rs:21:9:21:9 | b [Ok] | provenance | | | main.rs:26:9:26:9 | a | main.rs:27:10:27:10 | a | provenance | | @@ -53,8 +51,8 @@ edges | main.rs:61:18:61:23 | TuplePat [tuple.1] | main.rs:61:22:61:22 | m | provenance | | | main.rs:61:22:61:22 | m | main.rs:63:22:63:22 | m | provenance | | | main.rs:84:29:84:29 | [post] y [&ref] | main.rs:85:33:85:33 | y [&ref] | provenance | | -| main.rs:84:32:84:41 | source(...) | main.rs:84:29:84:29 | [post] y [&ref] | provenance | MaD:7 | -| main.rs:85:33:85:33 | y [&ref] | main.rs:85:18:85:34 | ...::read(...) | provenance | MaD:6 | +| main.rs:84:32:84:41 | source(...) | main.rs:84:29:84:29 | [post] y [&ref] | provenance | MaD:6 | +| main.rs:85:33:85:33 | y [&ref] | main.rs:85:18:85:34 | ...::read(...) | provenance | MaD:5 | nodes | main.rs:12:9:12:9 | a [Some] | semmle.label | a [Some] | | main.rs:12:13:12:28 | Some(...) [Some] | semmle.label | Some(...) [Some] | From 423e2dac9132d3e0572d8fea053dbafbad87bb82 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 1 May 2025 10:54:52 +0200 Subject: [PATCH 203/336] Rust: Strenghten the modeling of the `Clone` trait --- .../codeql/rust/frameworks/stdlib/Clone.qll | 4 +--- .../codeql/rust/internal/TypeInference.qll | 4 ++-- .../dataflow/modeled/inline-flow.expected | 22 ------------------- .../library-tests/dataflow/modeled/main.rs | 4 ++-- .../CaptureSummaryModels.expected | 2 +- .../test/utils-tests/modelgenerator/option.rs | 6 ++--- 6 files changed, 9 insertions(+), 33 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/Clone.qll b/rust/ql/lib/codeql/rust/frameworks/stdlib/Clone.qll index 514c3781355e..8d3c41c47082 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/Clone.qll +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/Clone.qll @@ -18,9 +18,7 @@ final class CloneCallable extends SummarizedCallable::Range { final override predicate propagatesFlow( string input, string output, boolean preservesValue, string model ) { - // The `clone` method takes a `&self` parameter and dereferences it; - // make sure to not clone the reference itself - input = ["Argument[self].Reference", "Argument[self].WithoutReference"] and + input = "Argument[self].Reference" and output = "ReturnValue" and preservesValue = true and model = "generated" diff --git a/rust/ql/lib/codeql/rust/internal/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/TypeInference.qll index 8c741781c207..cb9450a84d77 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeInference.qll @@ -1041,8 +1041,8 @@ private module Debug { private Locatable getRelevantLocatable() { exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and - filepath.matches("%/tauri/src/app/plugin.rs") and - startline = 54 + filepath.matches("%/main.rs") and + startline = 28 ) } diff --git a/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected b/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected index b5e19855cfa5..198f8ab9cd8c 100644 --- a/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected @@ -10,7 +10,6 @@ edges | main.rs:12:9:12:9 | a [Some] | main.rs:13:10:13:19 | a.unwrap() | provenance | MaD:2 | | main.rs:12:9:12:9 | a [Some] | main.rs:14:13:14:13 | a [Some] | provenance | | | main.rs:12:9:12:9 | a [Some] | main.rs:14:13:14:21 | a.clone() [Some] | provenance | MaD:1 | -| main.rs:12:9:12:9 | a [Some] | main.rs:14:13:14:21 | a.clone() [Some] | provenance | generated | | main.rs:12:13:12:28 | Some(...) [Some] | main.rs:12:9:12:9 | a [Some] | provenance | | | main.rs:12:18:12:27 | source(...) | main.rs:12:13:12:28 | Some(...) [Some] | provenance | | | main.rs:14:9:14:9 | b [Some] | main.rs:15:10:15:19 | b.unwrap() | provenance | MaD:2 | @@ -19,29 +18,19 @@ edges | main.rs:19:9:19:9 | a [Ok] | main.rs:20:10:20:19 | a.unwrap() | provenance | MaD:5 | | main.rs:19:9:19:9 | a [Ok] | main.rs:21:13:21:13 | a [Ok] | provenance | | | main.rs:19:9:19:9 | a [Ok] | main.rs:21:13:21:21 | a.clone() [Ok] | provenance | MaD:4 | -| main.rs:19:9:19:9 | a [Ok] | main.rs:21:13:21:21 | a.clone() [Ok] | provenance | generated | | main.rs:19:31:19:44 | Ok(...) [Ok] | main.rs:19:9:19:9 | a [Ok] | provenance | | | main.rs:19:34:19:43 | source(...) | main.rs:19:31:19:44 | Ok(...) [Ok] | provenance | | | main.rs:21:9:21:9 | b [Ok] | main.rs:22:10:22:19 | b.unwrap() | provenance | MaD:5 | | main.rs:21:13:21:13 | a [Ok] | main.rs:21:13:21:21 | a.clone() [Ok] | provenance | generated | | main.rs:21:13:21:21 | a.clone() [Ok] | main.rs:21:9:21:9 | b [Ok] | provenance | | | main.rs:26:9:26:9 | a | main.rs:27:10:27:10 | a | provenance | | -| main.rs:26:9:26:9 | a | main.rs:28:13:28:21 | a.clone() | provenance | generated | | main.rs:26:13:26:22 | source(...) | main.rs:26:9:26:9 | a | provenance | | -| main.rs:28:9:28:9 | b | main.rs:29:10:29:10 | b | provenance | | -| main.rs:28:13:28:21 | a.clone() | main.rs:28:9:28:9 | b | provenance | | | main.rs:41:13:41:13 | w [Wrapper] | main.rs:42:15:42:15 | w [Wrapper] | provenance | | | main.rs:41:17:41:41 | Wrapper {...} [Wrapper] | main.rs:41:13:41:13 | w [Wrapper] | provenance | | | main.rs:41:30:41:39 | source(...) | main.rs:41:17:41:41 | Wrapper {...} [Wrapper] | provenance | | | main.rs:42:15:42:15 | w [Wrapper] | main.rs:43:13:43:28 | Wrapper {...} [Wrapper] | provenance | | -| main.rs:42:15:42:15 | w [Wrapper] | main.rs:45:17:45:25 | w.clone() [Wrapper] | provenance | generated | | main.rs:43:13:43:28 | Wrapper {...} [Wrapper] | main.rs:43:26:43:26 | n | provenance | | | main.rs:43:26:43:26 | n | main.rs:43:38:43:38 | n | provenance | | -| main.rs:45:13:45:13 | u [Wrapper] | main.rs:46:15:46:15 | u [Wrapper] | provenance | | -| main.rs:45:17:45:25 | w.clone() [Wrapper] | main.rs:45:13:45:13 | u [Wrapper] | provenance | | -| main.rs:46:15:46:15 | u [Wrapper] | main.rs:47:13:47:28 | Wrapper {...} [Wrapper] | provenance | | -| main.rs:47:13:47:28 | Wrapper {...} [Wrapper] | main.rs:47:26:47:26 | n | provenance | | -| main.rs:47:26:47:26 | n | main.rs:47:38:47:38 | n | provenance | | | main.rs:58:13:58:13 | b [Some] | main.rs:59:23:59:23 | b [Some] | provenance | | | main.rs:58:17:58:32 | Some(...) [Some] | main.rs:58:13:58:13 | b [Some] | provenance | | | main.rs:58:22:58:31 | source(...) | main.rs:58:17:58:32 | Some(...) [Some] | provenance | | @@ -75,9 +64,6 @@ nodes | main.rs:26:9:26:9 | a | semmle.label | a | | main.rs:26:13:26:22 | source(...) | semmle.label | source(...) | | main.rs:27:10:27:10 | a | semmle.label | a | -| main.rs:28:9:28:9 | b | semmle.label | b | -| main.rs:28:13:28:21 | a.clone() | semmle.label | a.clone() | -| main.rs:29:10:29:10 | b | semmle.label | b | | main.rs:41:13:41:13 | w [Wrapper] | semmle.label | w [Wrapper] | | main.rs:41:17:41:41 | Wrapper {...} [Wrapper] | semmle.label | Wrapper {...} [Wrapper] | | main.rs:41:30:41:39 | source(...) | semmle.label | source(...) | @@ -85,12 +71,6 @@ nodes | main.rs:43:13:43:28 | Wrapper {...} [Wrapper] | semmle.label | Wrapper {...} [Wrapper] | | main.rs:43:26:43:26 | n | semmle.label | n | | main.rs:43:38:43:38 | n | semmle.label | n | -| main.rs:45:13:45:13 | u [Wrapper] | semmle.label | u [Wrapper] | -| main.rs:45:17:45:25 | w.clone() [Wrapper] | semmle.label | w.clone() [Wrapper] | -| main.rs:46:15:46:15 | u [Wrapper] | semmle.label | u [Wrapper] | -| main.rs:47:13:47:28 | Wrapper {...} [Wrapper] | semmle.label | Wrapper {...} [Wrapper] | -| main.rs:47:26:47:26 | n | semmle.label | n | -| main.rs:47:38:47:38 | n | semmle.label | n | | main.rs:58:13:58:13 | b [Some] | semmle.label | b [Some] | | main.rs:58:17:58:32 | Some(...) [Some] | semmle.label | Some(...) [Some] | | main.rs:58:22:58:31 | source(...) | semmle.label | source(...) | @@ -114,8 +94,6 @@ testFailures | main.rs:20:10:20:19 | a.unwrap() | main.rs:19:34:19:43 | source(...) | main.rs:20:10:20:19 | a.unwrap() | $@ | main.rs:19:34:19:43 | source(...) | source(...) | | main.rs:22:10:22:19 | b.unwrap() | main.rs:19:34:19:43 | source(...) | main.rs:22:10:22:19 | b.unwrap() | $@ | main.rs:19:34:19:43 | source(...) | source(...) | | main.rs:27:10:27:10 | a | main.rs:26:13:26:22 | source(...) | main.rs:27:10:27:10 | a | $@ | main.rs:26:13:26:22 | source(...) | source(...) | -| main.rs:29:10:29:10 | b | main.rs:26:13:26:22 | source(...) | main.rs:29:10:29:10 | b | $@ | main.rs:26:13:26:22 | source(...) | source(...) | | main.rs:43:38:43:38 | n | main.rs:41:30:41:39 | source(...) | main.rs:43:38:43:38 | n | $@ | main.rs:41:30:41:39 | source(...) | source(...) | -| main.rs:47:38:47:38 | n | main.rs:41:30:41:39 | source(...) | main.rs:47:38:47:38 | n | $@ | main.rs:41:30:41:39 | source(...) | source(...) | | main.rs:63:22:63:22 | m | main.rs:58:22:58:31 | source(...) | main.rs:63:22:63:22 | m | $@ | main.rs:58:22:58:31 | source(...) | source(...) | | main.rs:85:18:85:34 | ...::read(...) | main.rs:84:32:84:41 | source(...) | main.rs:85:18:85:34 | ...::read(...) | $@ | main.rs:84:32:84:41 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/modeled/main.rs b/rust/ql/test/library-tests/dataflow/modeled/main.rs index cb955ce32bde..648ffd0a307d 100644 --- a/rust/ql/test/library-tests/dataflow/modeled/main.rs +++ b/rust/ql/test/library-tests/dataflow/modeled/main.rs @@ -26,7 +26,7 @@ fn i64_clone() { let a = source(12); sink(a); // $ hasValueFlow=12 let b = a.clone(); - sink(b); // $ hasValueFlow=12 + sink(b); // $ MISSING: hasValueFlow=12 - lack of builtins means that we cannot resolve clone call above, and hence not insert implicit borrow } mod my_clone { @@ -44,7 +44,7 @@ mod my_clone { } let u = w.clone(); match u { - Wrapper { n: n } => sink(n), // $ hasValueFlow=73 + Wrapper { n: n } => sink(n), // $ MISSING: hasValueFlow=73 - lack of expanded derives means that we cannot resolve clone call above, and hence not insert implicit borrow } } } diff --git a/rust/ql/test/utils-tests/modelgenerator/CaptureSummaryModels.expected b/rust/ql/test/utils-tests/modelgenerator/CaptureSummaryModels.expected index e827c7320cc7..b3a3717c9300 100644 --- a/rust/ql/test/utils-tests/modelgenerator/CaptureSummaryModels.expected +++ b/rust/ql/test/utils-tests/modelgenerator/CaptureSummaryModels.expected @@ -1,4 +1,4 @@ unexpectedModel | Unexpected summary found: repo::test;::clone;Argument[self].Field[crate::option::MyOption::MySome(0)].Reference;ReturnValue.Field[crate::option::MyOption::MySome(0)];value;dfc-generated | -| Unexpected summary found: repo::test;::cloned;Argument[self].Field[crate::option::MyOption::MySome(0)].Reference;ReturnValue.Field[crate::option::MyOption::MySome(0)];value;dfc-generated | expectedModel +| Expected summary missing: repo::test;::clone;Argument[self].Reference.Field[crate::option::MyOption::MySome(0)];ReturnValue.Field[crate::option::MyOption::MySome(0)];value;dfc-generated | diff --git a/rust/ql/test/utils-tests/modelgenerator/option.rs b/rust/ql/test/utils-tests/modelgenerator/option.rs index 5e2e2391ba76..19b4a92fa376 100644 --- a/rust/ql/test/utils-tests/modelgenerator/option.rs +++ b/rust/ql/test/utils-tests/modelgenerator/option.rs @@ -414,7 +414,7 @@ impl MyOption<&T> { } } - // summary=repo::test;::cloned;Argument[self].Field[crate::option::MyOption::MySome(0)];ReturnValue.Field[crate::option::MyOption::MySome(0)];value;dfc-generated + // summary=repo::test;::cloned;Argument[self].Field[crate::option::MyOption::MySome(0)].Reference;ReturnValue.Field[crate::option::MyOption::MySome(0)];value;dfc-generated pub fn cloned(self) -> MyOption where T: Clone, @@ -438,7 +438,7 @@ impl MyOption<&mut T> { } } - // summary=repo::test;::cloned;Argument[self].Field[crate::option::MyOption::MySome(0)];ReturnValue.Field[crate::option::MyOption::MySome(0)];value;dfc-generated + // summary=repo::test;::cloned;Argument[self].Field[crate::option::MyOption::MySome(0)].Reference;ReturnValue.Field[crate::option::MyOption::MySome(0)];value;dfc-generated pub fn cloned(self) -> MyOption where T: Clone, @@ -466,7 +466,7 @@ impl Clone for MyOption where T: Clone, { - // summary=repo::test;::clone;Argument[self].Field[crate::option::MyOption::MySome(0)];ReturnValue.Field[crate::option::MyOption::MySome(0)];value;dfc-generated + // summary=repo::test;::clone;Argument[self].Reference.Field[crate::option::MyOption::MySome(0)];ReturnValue.Field[crate::option::MyOption::MySome(0)];value;dfc-generated fn clone(&self) -> Self { match self { MySome(x) => MySome(x.clone()), From 40d176a7703fd01407179668f3921e1702e48da9 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Wed, 30 Apr 2025 13:45:50 +0200 Subject: [PATCH 204/336] Added model for shelljs.env --- javascript/ql/lib/ext/shelljs.model.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 javascript/ql/lib/ext/shelljs.model.yml diff --git a/javascript/ql/lib/ext/shelljs.model.yml b/javascript/ql/lib/ext/shelljs.model.yml new file mode 100644 index 000000000000..8d2c8db645d8 --- /dev/null +++ b/javascript/ql/lib/ext/shelljs.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/javascript-all + extensible: sourceModel + data: + - ["shelljs", "Member[env]", "environment"] From 602500e280797acb207b4d41020fe0b36090d583 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Wed, 30 Apr 2025 13:40:52 +0200 Subject: [PATCH 205/336] Added change note --- javascript/ql/lib/change-notes/2025-04-30-shelljs.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 javascript/ql/lib/change-notes/2025-04-30-shelljs.md diff --git a/javascript/ql/lib/change-notes/2025-04-30-shelljs.md b/javascript/ql/lib/change-notes/2025-04-30-shelljs.md new file mode 100644 index 000000000000..90a5f5a2a308 --- /dev/null +++ b/javascript/ql/lib/change-notes/2025-04-30-shelljs.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Improved modeling of the [`shelljs`](https://www.npmjs.com/package/shelljs) and [`async-shelljs`](https://www.npmjs.com/package/async-shelljs) libraries by adding support for the `which`, `cmd`, `asyncExec` and `env`. From 33d8ffa83e2866eb6c9602cbd570999bf8e83c31 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 1 May 2025 11:11:29 +0200 Subject: [PATCH 206/336] Added test cases for shelljs.env --- .../Security/CWE-078/IndirectCommandInjection/actions.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection/actions.js b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection/actions.js index 021715395217..a92b7713491c 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection/actions.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection/actions.js @@ -12,3 +12,10 @@ function test(e) { test(process.env); // $ Source exec(getInput('data')); // $ Alert + +function test2(e) { + const shelljs = require('shelljs'); + exec('rm -rf ' + shelljs.env['SOME']); // $ MISSING: Alert + exec('rm -rf ' + shelljs.env.SOME); // $ MISSING: Alert + exec('rm -rf ' + shelljs.env); // $ MISSING: Alert +} From d4b5ef6a6659258f2d837cdcc006fd3e60a49562 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 1 May 2025 11:14:15 +0200 Subject: [PATCH 207/336] Refactor process.env handling in CleartextLogging and IndirectCommandInjection modules to use ThreatModelSource --- .../dataflow/CleartextLoggingCustomizations.qll | 2 +- .../IndirectCommandInjectionCustomizations.qll | 4 ++-- .../CWE-295/DisablingCertificateValidation.ql | 2 +- .../IndirectCommandInjection.expected | 12 ++++++++++++ .../CWE-078/IndirectCommandInjection/actions.js | 6 +++--- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll index 5dca4cf1df28..dbb775f99b58 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll @@ -171,7 +171,7 @@ module CleartextLogging { /** An access to the sensitive object `process.env`. */ class ProcessEnvSource extends Source { - ProcessEnvSource() { this = NodeJSLib::process().getAPropertyRead("env") } + ProcessEnvSource() { this.(ThreatModelSource).getThreatModel() = "environment" } override string describe() { result = "process environment" } } diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll index 9dd6ab4b4a91..84c4600fbc03 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll @@ -29,7 +29,7 @@ module IndirectCommandInjection { * A read of `process.env`, considered as a flow source for command injection. */ private class ProcessEnvAsSource extends Source { - ProcessEnvAsSource() { this = NodeJSLib::process().getAPropertyRead("env") } + ProcessEnvAsSource() { this.(ThreatModelSource).getThreatModel() = "environment" } override string describe() { result = "environment variable" } } @@ -37,7 +37,7 @@ module IndirectCommandInjection { /** Gets a data flow node referring to `process.env`. */ private DataFlow::SourceNode envObject(DataFlow::TypeTracker t) { t.start() and - result = NodeJSLib::process().getAPropertyRead("env") + result.(ThreatModelSource).getThreatModel() = "environment" or exists(DataFlow::TypeTracker t2 | result = envObject(t2).track(t2, t)) } diff --git a/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql b/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql index d9f7267d425a..b5e52d7c6c79 100644 --- a/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql +++ b/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql @@ -37,7 +37,7 @@ DataFlow::ObjectLiteralNode tlsOptions() { result.flowsTo(tlsInvocation().getAnA from DataFlow::PropWrite disable where exists(DataFlow::SourceNode env | - env = NodeJSLib::process().getAPropertyRead("env") and + env.(ThreatModelSource).getThreatModel() = "environment" and disable = env.getAPropertyWrite("NODE_TLS_REJECT_UNAUTHORIZED") and disable.getRhs().mayHaveStringValue("0") ) diff --git a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection/IndirectCommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection/IndirectCommandInjection.expected index 7c7321845776..9fc6f6b1bc4e 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection/IndirectCommandInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection/IndirectCommandInjection.expected @@ -2,6 +2,9 @@ | actions.js:4:6:4:29 | process ... _DATA'] | actions.js:4:6:4:16 | process.env | actions.js:4:6:4:29 | process ... _DATA'] | This command depends on an unsanitized $@. | actions.js:4:6:4:16 | process.env | environment variable | | actions.js:8:10:8:23 | e['TEST_DATA'] | actions.js:12:6:12:16 | process.env | actions.js:8:10:8:23 | e['TEST_DATA'] | This command depends on an unsanitized $@. | actions.js:12:6:12:16 | process.env | environment variable | | actions.js:14:6:14:21 | getInput('data') | actions.js:14:6:14:21 | getInput('data') | actions.js:14:6:14:21 | getInput('data') | This command depends on an unsanitized $@. | actions.js:14:6:14:21 | getInput('data') | GitHub Actions user input | +| actions.js:18:10:18:40 | 'rm -rf ... 'SOME'] | actions.js:18:22:18:32 | shelljs.env | actions.js:18:10:18:40 | 'rm -rf ... 'SOME'] | This command depends on an unsanitized $@. | actions.js:18:22:18:32 | shelljs.env | environment variable | +| actions.js:19:10:19:37 | 'rm -rf ... nv.SOME | actions.js:19:22:19:32 | shelljs.env | actions.js:19:10:19:37 | 'rm -rf ... nv.SOME | This command depends on an unsanitized $@. | actions.js:19:22:19:32 | shelljs.env | environment variable | +| actions.js:20:10:20:32 | 'rm -rf ... ljs.env | actions.js:20:22:20:32 | shelljs.env | actions.js:20:10:20:32 | 'rm -rf ... ljs.env | This command depends on an unsanitized $@. | actions.js:20:22:20:32 | shelljs.env | environment variable | | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line argument | | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line argument | | command-line-parameter-command-injection.js:11:14:11:20 | args[0] | command-line-parameter-command-injection.js:10:13:10:24 | process.argv | command-line-parameter-command-injection.js:11:14:11:20 | args[0] | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:10:13:10:24 | process.argv | command-line argument | @@ -44,6 +47,9 @@ edges | actions.js:7:15:7:15 | e | actions.js:8:10:8:10 | e | provenance | | | actions.js:8:10:8:10 | e | actions.js:8:10:8:23 | e['TEST_DATA'] | provenance | | | actions.js:12:6:12:16 | process.env | actions.js:7:15:7:15 | e | provenance | | +| actions.js:18:22:18:32 | shelljs.env | actions.js:18:10:18:40 | 'rm -rf ... 'SOME'] | provenance | | +| actions.js:19:22:19:32 | shelljs.env | actions.js:19:10:19:37 | 'rm -rf ... nv.SOME | provenance | | +| actions.js:20:22:20:32 | shelljs.env | actions.js:20:10:20:32 | 'rm -rf ... ljs.env | provenance | | | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | provenance | | | command-line-parameter-command-injection.js:10:6:10:33 | args | command-line-parameter-command-injection.js:11:14:11:17 | args | provenance | | | command-line-parameter-command-injection.js:10:6:10:33 | args | command-line-parameter-command-injection.js:12:26:12:29 | args | provenance | | @@ -181,6 +187,12 @@ nodes | actions.js:8:10:8:23 | e['TEST_DATA'] | semmle.label | e['TEST_DATA'] | | actions.js:12:6:12:16 | process.env | semmle.label | process.env | | actions.js:14:6:14:21 | getInput('data') | semmle.label | getInput('data') | +| actions.js:18:10:18:40 | 'rm -rf ... 'SOME'] | semmle.label | 'rm -rf ... 'SOME'] | +| actions.js:18:22:18:32 | shelljs.env | semmle.label | shelljs.env | +| actions.js:19:10:19:37 | 'rm -rf ... nv.SOME | semmle.label | 'rm -rf ... nv.SOME | +| actions.js:19:22:19:32 | shelljs.env | semmle.label | shelljs.env | +| actions.js:20:10:20:32 | 'rm -rf ... ljs.env | semmle.label | 'rm -rf ... ljs.env | +| actions.js:20:22:20:32 | shelljs.env | semmle.label | shelljs.env | | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | semmle.label | process.argv | | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | semmle.label | "cmd.sh ... argv[2] | | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | semmle.label | process.argv | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection/actions.js b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection/actions.js index a92b7713491c..8fb6994a597c 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection/actions.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection/actions.js @@ -15,7 +15,7 @@ exec(getInput('data')); // $ Alert function test2(e) { const shelljs = require('shelljs'); - exec('rm -rf ' + shelljs.env['SOME']); // $ MISSING: Alert - exec('rm -rf ' + shelljs.env.SOME); // $ MISSING: Alert - exec('rm -rf ' + shelljs.env); // $ MISSING: Alert + exec('rm -rf ' + shelljs.env['SOME']); // $ Alert + exec('rm -rf ' + shelljs.env.SOME); // $ Alert + exec('rm -rf ' + shelljs.env); // $ Alert } From 68a9dd9f9e72b2feaade18de2dbabc742406bdeb Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 1 May 2025 11:19:41 +0200 Subject: [PATCH 208/336] Address comments --- javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll index 4b53292e1482..dafc38ca8573 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll @@ -169,9 +169,7 @@ module Fastify { override string getRelativePath() { result = this.getArgument(0).getStringValue() } - override Http::RequestMethodName getHttpMethod() { - if this.getMethodName() = "all" then any() else result = this.getMethodName().toUpperCase() - } + override Http::RequestMethodName getHttpMethod() { result = this.getMethodName().toUpperCase() } } private class AddHookRouteSetup extends Routing::RouteSetup::MethodCall instanceof RouteSetup { From 0863c87572a3867de8fa9a571e8ee3574f809ea1 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Thu, 1 May 2025 10:33:24 +0100 Subject: [PATCH 209/336] Add change notes --- .../src/change-notes/2025-05-01-cwe-tag-changed.md | 9 +++++++++ .../src/change-notes/2025-05-01-cwe-tag-changed.md | 12 ++++++++++++ .../src/change-notes/2025-05-01-cwe-tag-changed.md | 14 ++++++++++++++ .../src/change-notes/2025-05-01-cwe-tag-changed.md | 7 +++++++ .../src/change-notes/2025-05-01-cwe-tag-changed.md | 8 ++++++++ .../src/change-notes/2025-05-01-cwe-tag-changed.md | 10 ++++++++++ .../src/change-notes/2025-05-01-cwe-tag-changed.md | 5 +++++ 7 files changed, 65 insertions(+) create mode 100644 cpp/ql/src/change-notes/2025-05-01-cwe-tag-changed.md create mode 100644 csharp/ql/src/change-notes/2025-05-01-cwe-tag-changed.md create mode 100644 go/ql/src/change-notes/2025-05-01-cwe-tag-changed.md create mode 100644 java/ql/src/change-notes/2025-05-01-cwe-tag-changed.md create mode 100644 javascript/ql/src/change-notes/2025-05-01-cwe-tag-changed.md create mode 100644 python/ql/src/change-notes/2025-05-01-cwe-tag-changed.md create mode 100644 ruby/ql/src/change-notes/2025-05-01-cwe-tag-changed.md diff --git a/cpp/ql/src/change-notes/2025-05-01-cwe-tag-changed.md b/cpp/ql/src/change-notes/2025-05-01-cwe-tag-changed.md new file mode 100644 index 000000000000..daefff65c31e --- /dev/null +++ b/cpp/ql/src/change-notes/2025-05-01-cwe-tag-changed.md @@ -0,0 +1,9 @@ +--- +category: queryMetadata +--- +* The tag `external/cwe/cwe-14` has been removed from `cpp/memset-may-be-deleted` and the tag `external/cwe/cwe-014` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cpp/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cpp/count-untrusted-data-external-api-ir` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cpp/untrusted-data-to-external-api-ir` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cpp/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cpp/late-check-of-function-argument` and the tag `external/cwe/cwe-020` has been added. diff --git a/csharp/ql/src/change-notes/2025-05-01-cwe-tag-changed.md b/csharp/ql/src/change-notes/2025-05-01-cwe-tag-changed.md new file mode 100644 index 000000000000..8b84ae3f0774 --- /dev/null +++ b/csharp/ql/src/change-notes/2025-05-01-cwe-tag-changed.md @@ -0,0 +1,12 @@ +--- +category: queryMetadata +--- + +* The tag `external/cwe/cwe-13` has been removed from `cs/password-in-configuration` and the tag `external/cwe/cwe-013` has been added. +* The tag `external/cwe/cwe-11` has been removed from `cs/web/debug-binary` and the tag `external/cwe/cwe-011` has been added. +* The tag `external/cwe/cwe-16` has been removed from `cs/web/large-max-request-length` and the tag `external/cwe/cwe-016` has been added. +* The tag `external/cwe/cwe-16` has been removed from `cs/web/request-validation-disabled` and the tag `external/cwe/cwe-016` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cs/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cs/serialization-check-bypass` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cs/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-12` has been removed from `cs/web/missing-global-error-handler` and the tag `external/cwe/cwe-012` has been added. diff --git a/go/ql/src/change-notes/2025-05-01-cwe-tag-changed.md b/go/ql/src/change-notes/2025-05-01-cwe-tag-changed.md new file mode 100644 index 000000000000..d084aeeaf48a --- /dev/null +++ b/go/ql/src/change-notes/2025-05-01-cwe-tag-changed.md @@ -0,0 +1,14 @@ +--- +category: queryMetadata +--- + +* The tag `external/cwe/cwe-20` has been removed from `go/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `go/incomplete-hostname-regexp` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `go/regex/missing-regexp-anchor` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `go/suspicious-character-in-regex` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `go/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `go/untrusted-data-to-unknown-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-90` has been removed from `go/ldap-injection` and the tag `external/cwe/cwe-090` has been added. +* The tag `external/cwe/cwe-74` has been removed from `go/dsn-injection` and the tag `external/cwe/cwe-074` has been added. +* The tag `external/cwe/cwe-74` has been removed from `go/dsn-injection-local` and the tag `external/cwe/cwe-074` has been added. +* The tag `external/cwe/cwe-79` has been removed from `go/html-template-escaping-passthrough` and the tag `external/cwe/cwe-079` has been added. diff --git a/java/ql/src/change-notes/2025-05-01-cwe-tag-changed.md b/java/ql/src/change-notes/2025-05-01-cwe-tag-changed.md new file mode 100644 index 000000000000..2bbc6a6d7764 --- /dev/null +++ b/java/ql/src/change-notes/2025-05-01-cwe-tag-changed.md @@ -0,0 +1,7 @@ +--- +category: queryMetadata +--- + +* The tag `external/cwe/cwe-20` has been removed from `java/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `java/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-93` has been removed from `java/netty-http-request-or-response-splitting` and the tag `external/cwe/cwe-093` has been added. diff --git a/javascript/ql/src/change-notes/2025-05-01-cwe-tag-changed.md b/javascript/ql/src/change-notes/2025-05-01-cwe-tag-changed.md new file mode 100644 index 000000000000..01e53adf5f5e --- /dev/null +++ b/javascript/ql/src/change-notes/2025-05-01-cwe-tag-changed.md @@ -0,0 +1,8 @@ +--- +category: queryMetadata +--- + +* The tag `external/cwe/cwe-79` has been removed from `js/disabling-electron-websecurity` and the tag `external/cwe/cwe-079` has been added. +* The tag `external/cwe/cwe-20` has been removed from `js/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `js/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `js/untrusted-data-to-external-api-more-sources` and the tag `external/cwe/cwe-020` has been added. diff --git a/python/ql/src/change-notes/2025-05-01-cwe-tag-changed.md b/python/ql/src/change-notes/2025-05-01-cwe-tag-changed.md new file mode 100644 index 000000000000..0267e9a3fbb8 --- /dev/null +++ b/python/ql/src/change-notes/2025-05-01-cwe-tag-changed.md @@ -0,0 +1,10 @@ +--- +category: queryMetadata +--- + +* The tags `security/cwe/cwe-94` and `security/cwe/cwe-95` have been removed from `py/use-of-input` and the tags `external/cwe/cwe-094` and `external/cwe/cwe-095` have been added. +* The tag `external/cwe/cwe-20` has been removed from `py/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `py/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `py/cookie-injection` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `py/incomplete-url-substring-sanitization` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-94` has been removed from `py/js2py-rce` and the tag `external/cwe/cwe-094` has been added. diff --git a/ruby/ql/src/change-notes/2025-05-01-cwe-tag-changed.md b/ruby/ql/src/change-notes/2025-05-01-cwe-tag-changed.md new file mode 100644 index 000000000000..c8fd8d626866 --- /dev/null +++ b/ruby/ql/src/change-notes/2025-05-01-cwe-tag-changed.md @@ -0,0 +1,5 @@ +--- +category: queryMetadata +--- + +* The tag `external/cwe/cwe-94` has been removed from `rb/server-side-template-injection` and the tag `external/cwe/cwe-094` has been added. From 0325f368fe27045757d8bb55e18879a2ac88f379 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 1 May 2025 13:57:14 +0200 Subject: [PATCH 210/336] Added test case for `hdbcli` --- .../frameworks/hdbcli/ConceptsTest.expected | 0 .../test/library-tests/frameworks/hdbcli/ConceptsTest.ql | 2 ++ python/ql/test/library-tests/frameworks/hdbcli/pep249.py | 9 +++++++++ 3 files changed, 11 insertions(+) create mode 100644 python/ql/test/library-tests/frameworks/hdbcli/ConceptsTest.expected create mode 100644 python/ql/test/library-tests/frameworks/hdbcli/ConceptsTest.ql create mode 100644 python/ql/test/library-tests/frameworks/hdbcli/pep249.py diff --git a/python/ql/test/library-tests/frameworks/hdbcli/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/hdbcli/ConceptsTest.expected new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/ql/test/library-tests/frameworks/hdbcli/ConceptsTest.ql b/python/ql/test/library-tests/frameworks/hdbcli/ConceptsTest.ql new file mode 100644 index 000000000000..b557a0bccb69 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/hdbcli/ConceptsTest.ql @@ -0,0 +1,2 @@ +import python +import experimental.meta.ConceptsTest diff --git a/python/ql/test/library-tests/frameworks/hdbcli/pep249.py b/python/ql/test/library-tests/frameworks/hdbcli/pep249.py new file mode 100644 index 000000000000..35c6e6d87e45 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/hdbcli/pep249.py @@ -0,0 +1,9 @@ +from hdbcli import dbapi + +conn = dbapi.connect(address="hostname", port=300, user="username", password="password") +cursor = conn.cursor() + +cursor.execute("some sql", (42,)) # $ MISSING: getSql="some sql" +cursor.executemany("some sql", (42,)) # $ MISSING: getSql="some sql" + +cursor.close() From e1fc0ca051d43b46aef2fd1adeeb3a5b3c25ed33 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 1 May 2025 14:01:33 +0200 Subject: [PATCH 211/336] Added implementation `hdbcli` as part of `PEP249::PEP249ModuleApiNode` --- python/ql/lib/semmle/python/Frameworks.qll | 1 + .../lib/semmle/python/frameworks/Hdbcli.qll | 24 +++++++++++++++++++ .../library-tests/frameworks/hdbcli/pep249.py | 4 ++-- 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 python/ql/lib/semmle/python/frameworks/Hdbcli.qll diff --git a/python/ql/lib/semmle/python/Frameworks.qll b/python/ql/lib/semmle/python/Frameworks.qll index e6af222a615f..955385141f7f 100644 --- a/python/ql/lib/semmle/python/Frameworks.qll +++ b/python/ql/lib/semmle/python/Frameworks.qll @@ -35,6 +35,7 @@ private import semmle.python.frameworks.FlaskAdmin private import semmle.python.frameworks.FlaskSqlAlchemy private import semmle.python.frameworks.Genshi private import semmle.python.frameworks.Gradio +private import semmle.python.frameworks.Hdbcli private import semmle.python.frameworks.Httpx private import semmle.python.frameworks.Idna private import semmle.python.frameworks.Invoke diff --git a/python/ql/lib/semmle/python/frameworks/Hdbcli.qll b/python/ql/lib/semmle/python/frameworks/Hdbcli.qll new file mode 100644 index 000000000000..6b91519ae63b --- /dev/null +++ b/python/ql/lib/semmle/python/frameworks/Hdbcli.qll @@ -0,0 +1,24 @@ +/** + * Provides classes modeling security-relevant aspects of the `hdbcli` PyPI package. + * See https://pypi.org/project/hdbcli/ + */ + +private import python +private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.Concepts +private import semmle.python.ApiGraphs +private import semmle.python.frameworks.PEP249 + +/** + * Provides models for the `hdbcli` PyPI package. + * See https://pypi.org/project/hdbcli/ + */ +private module Hdbcli { + /** + * A model of `hdbcli` as a module that implements PEP 249, providing ways to execute SQL statements + * against a database. + */ + class HdbcliPEP249 extends PEP249::PEP249ModuleApiNode { + HdbcliPEP249() { this = API::moduleImport("hdbcli").getMember("dbapi") } + } +} diff --git a/python/ql/test/library-tests/frameworks/hdbcli/pep249.py b/python/ql/test/library-tests/frameworks/hdbcli/pep249.py index 35c6e6d87e45..713f15cb6d4f 100644 --- a/python/ql/test/library-tests/frameworks/hdbcli/pep249.py +++ b/python/ql/test/library-tests/frameworks/hdbcli/pep249.py @@ -3,7 +3,7 @@ conn = dbapi.connect(address="hostname", port=300, user="username", password="password") cursor = conn.cursor() -cursor.execute("some sql", (42,)) # $ MISSING: getSql="some sql" -cursor.executemany("some sql", (42,)) # $ MISSING: getSql="some sql" +cursor.execute("some sql", (42,)) # $ getSql="some sql" +cursor.executemany("some sql", (42,)) # $ getSql="some sql" cursor.close() From da7c0931b8aead3a235008d0b5ca2ad88b2a941e Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Thu, 1 May 2025 14:08:54 +0200 Subject: [PATCH 212/336] Added `hdbcli` to be part of `supported-framework` as well as change note --- docs/codeql/reusables/supported-frameworks.rst | 1 + python/ql/lib/change-notes/2025-05-01-hdbcli.md | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 python/ql/lib/change-notes/2025-05-01-hdbcli.md diff --git a/docs/codeql/reusables/supported-frameworks.rst b/docs/codeql/reusables/supported-frameworks.rst index 402a3b9ee3d3..07a5e509fecb 100644 --- a/docs/codeql/reusables/supported-frameworks.rst +++ b/docs/codeql/reusables/supported-frameworks.rst @@ -254,6 +254,7 @@ and the CodeQL library pack ``codeql/python-all`` (`changelog Date: Wed, 30 Apr 2025 13:21:56 +0200 Subject: [PATCH 213/336] Rust: extract declarations of builtin types --- rust/BUILD.bazel | 1 + rust/extractor/src/main.rs | 36 +++++++++++++++++++++++---------- rust/tools/builtins/BUILD.bazel | 8 ++++++++ rust/tools/builtins/types.rs | 25 +++++++++++++++++++++++ 4 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 rust/tools/builtins/BUILD.bazel create mode 100644 rust/tools/builtins/types.rs diff --git a/rust/BUILD.bazel b/rust/BUILD.bazel index 9cdc89dd52fd..6536a4b6fd9e 100644 --- a/rust/BUILD.bazel +++ b/rust/BUILD.bazel @@ -36,6 +36,7 @@ pkg_filegroup( srcs = [ ":tools-arch", "//rust/tools", + "//rust/tools/builtins", ], prefix = "tools", ) diff --git a/rust/extractor/src/main.rs b/rust/extractor/src/main.rs index 0ec1769f1d17..b983a3217a3a 100644 --- a/rust/extractor/src/main.rs +++ b/rust/extractor/src/main.rs @@ -17,6 +17,7 @@ use std::{ collections::HashMap, path::{Path, PathBuf}, }; +use std::{env, fs}; use tracing::{error, info, warn}; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; @@ -77,17 +78,19 @@ impl<'a> Extractor<'a> { } let no_location = (LineCol { line: 0, col: 0 }, LineCol { line: 0, col: 0 }); if let Err(reason) = semantics_info { - let message = format!("semantic analyzer unavailable ({reason})"); - let full_message = format!( - "{message}: macro expansion, call graph, and type inference will be skipped." - ); - translator.emit_diagnostic( - trap::DiagnosticSeverity::Warning, - "semantics".to_owned(), - message, - full_message, - no_location, - ); + if !reason.is_empty() { + let message = format!("semantic analyzer unavailable ({reason})"); + let full_message = format!( + "{message}: macro expansion, call graph, and type inference will be skipped." + ); + translator.emit_diagnostic( + trap::DiagnosticSeverity::Warning, + "semantics".to_owned(), + message, + full_message, + no_location, + ); + } } translator.emit_source_file(ast); translator.trap.commit().unwrap_or_else(|err| { @@ -276,5 +279,16 @@ fn main() -> anyhow::Result<()> { } } } + let builtins_dir = env::var("CODEQL_EXTRACTOR_RUST_ROOT") + .map(|path| Path::new(&path).join("tools").join("builtins"))?; + let builtins = fs::read_dir(builtins_dir).context("failed to read builtins directory")?; + for entry in builtins { + let entry = entry.context("failed to read builtins directory")?; + let path = entry.path(); + if path.extension().is_some_and(|ext| ext == "rs") { + extractor.extract_without_semantics(&path, ""); + } + } + extractor.emit_extraction_diagnostics(start, &cfg) } diff --git a/rust/tools/builtins/BUILD.bazel b/rust/tools/builtins/BUILD.bazel new file mode 100644 index 000000000000..2c7da705dd20 --- /dev/null +++ b/rust/tools/builtins/BUILD.bazel @@ -0,0 +1,8 @@ +load("//misc/bazel:pkg.bzl", "codeql_pkg_files") + +codeql_pkg_files( + name = "builtins", + srcs = glob(["*.rs"]), + prefix = "builtins", + visibility = ["//rust:__subpackages__"], +) diff --git a/rust/tools/builtins/types.rs b/rust/tools/builtins/types.rs new file mode 100644 index 000000000000..91989b5262b5 --- /dev/null +++ b/rust/tools/builtins/types.rs @@ -0,0 +1,25 @@ +// The Language Prelude: https://doc.rust-lang.org/reference/names/preludes.html#language-prelude + +// Type namespace +// Boolean type +pub struct bool; +// Textual types +pub struct char; +pub struct str; +// Integer types +pub struct i8; +pub struct i16; +pub struct i32; +pub struct i64; +pub struct i128; +pub struct u8; +pub struct u16; +pub struct u32; +pub struct u64; +pub struct u128; +// Machine-dependent integer types +pub struct usize; +pub struct isize; +// floating-point types +pub struct f32; +pub struct f64; From ca5f8b0c1d1872d6a9b38d91139a1e6b82659385 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 1 May 2025 15:17:07 +0200 Subject: [PATCH 214/336] JS: Move some code into ModelsAsData.qll --- .../frameworks/data/ModelsAsData.qll | 45 ++++++++++++++++++- .../data/internal/ApiGraphModelsSpecific.qll | 45 ------------------- 2 files changed, 44 insertions(+), 46 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll index 856a61276a0a..9f143a9713ad 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll @@ -45,12 +45,55 @@ private class ThreatModelSourceFromDataExtension extends ThreatModelSource::Rang } } +/** + * Holds if `path` is an input or output spec for a summary with the given `base` node. + */ +pragma[nomagic] +private predicate relevantInputOutputPath(API::InvokeNode base, AccessPath inputOrOutput) { + exists(string type, string input, string output, string path | + ModelOutput::resolvedSummaryBase(type, path, base) and + ModelOutput::relevantSummaryModel(type, path, input, output, _, _) and + inputOrOutput = [input, output] + ) +} + +/** + * Gets the API node for the first `n` tokens of the given input/output path, evaluated relative to `baseNode`. + */ +private API::Node getNodeFromInputOutputPath(API::InvokeNode baseNode, AccessPath path, int n) { + relevantInputOutputPath(baseNode, path) and + ( + n = 1 and + result = Shared::getSuccessorFromInvoke(baseNode, path.getToken(0)) + or + result = + Shared::getSuccessorFromNode(getNodeFromInputOutputPath(baseNode, path, n - 1), + path.getToken(n - 1)) + ) +} + +/** + * Gets the API node for the given input/output path, evaluated relative to `baseNode`. + */ +private API::Node getNodeFromInputOutputPath(API::InvokeNode baseNode, AccessPath path) { + result = getNodeFromInputOutputPath(baseNode, path, path.getNumToken()) +} + +private predicate summaryStep(API::Node pred, API::Node succ, string kind) { + exists(string type, string path, API::InvokeNode base, AccessPath input, AccessPath output | + ModelOutput::relevantSummaryModel(type, path, input, output, kind, _) and + ModelOutput::resolvedSummaryBase(type, path, base) and + pred = getNodeFromInputOutputPath(base, input) and + succ = getNodeFromInputOutputPath(base, output) + ) +} + /** * Like `ModelOutput::summaryStep` but with API nodes mapped to data-flow nodes. */ private predicate summaryStepNodes(DataFlow::Node pred, DataFlow::Node succ, string kind) { exists(API::Node predNode, API::Node succNode | - Specific::summaryStep(predNode, succNode, kind) and + summaryStep(predNode, succNode, kind) and pred = predNode.asSink() and succ = succNode.asSource() ) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll index 1f51af3efda0..473dfe46527b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll @@ -272,51 +272,6 @@ predicate invocationMatchesExtraCallSiteFilter(API::InvokeNode invoke, AccessPat ) } -/** - * Holds if `path` is an input or output spec for a summary with the given `base` node. - */ -pragma[nomagic] -private predicate relevantInputOutputPath(API::InvokeNode base, AccessPath inputOrOutput) { - exists(string type, string input, string output, string path | - ModelOutput::relevantSummaryModel(type, path, input, output, _, _) and - ModelOutput::resolvedSummaryBase(type, path, base) and - inputOrOutput = [input, output] - ) -} - -/** - * Gets the API node for the first `n` tokens of the given input/output path, evaluated relative to `baseNode`. - */ -private API::Node getNodeFromInputOutputPath(API::InvokeNode baseNode, AccessPath path, int n) { - relevantInputOutputPath(baseNode, path) and - ( - n = 1 and - result = getSuccessorFromInvoke(baseNode, path.getToken(0)) - or - result = - getSuccessorFromNode(getNodeFromInputOutputPath(baseNode, path, n - 1), path.getToken(n - 1)) - ) -} - -/** - * Gets the API node for the given input/output path, evaluated relative to `baseNode`. - */ -private API::Node getNodeFromInputOutputPath(API::InvokeNode baseNode, AccessPath path) { - result = getNodeFromInputOutputPath(baseNode, path, path.getNumToken()) -} - -/** - * Holds if a CSV summary contributed the step `pred -> succ` of the given `kind`. - */ -predicate summaryStep(API::Node pred, API::Node succ, string kind) { - exists(string type, string path, API::InvokeNode base, AccessPath input, AccessPath output | - ModelOutput::relevantSummaryModel(type, path, input, output, kind, _) and - ModelOutput::resolvedSummaryBase(type, path, base) and - pred = getNodeFromInputOutputPath(base, input) and - succ = getNodeFromInputOutputPath(base, output) - ) -} - class InvokeNode = API::InvokeNode; /** Gets an `InvokeNode` corresponding to an invocation of `node`. */ From 8e8efedb42ddd87de4519b34f47d77b238aa3577 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Wed, 30 Apr 2025 17:10:33 +0200 Subject: [PATCH 215/336] Rust: adjust integration tests and expected output --- .../hello-project/diagnostics.expected | 2 +- .../hello-project/steps.cargo.expected | 2 ++ .../integration-tests/hello-project/steps.ql | 25 ++++++++++++++++++- .../hello-project/steps.rust-project.expected | 2 ++ .../hello-project/summary.expected | 2 +- .../diagnostics.cargo.expected | 2 +- .../diagnostics.rust-project.expected | 2 +- .../hello-workspace/steps.cargo.expected | 2 ++ .../hello-workspace/steps.ql | 25 ++++++++++++++++++- .../steps.rust-project.expected | 2 ++ .../hello-workspace/summary.cargo.expected | 2 +- .../summary.rust-project.expected | 2 +- .../workspace-with-glob/steps.expected | 2 ++ .../workspace-with-glob/steps.ql | 25 ++++++++++++++++++- 14 files changed, 88 insertions(+), 9 deletions(-) diff --git a/rust/ql/integration-tests/hello-project/diagnostics.expected b/rust/ql/integration-tests/hello-project/diagnostics.expected index 146d8514488e..f45877f26d06 100644 --- a/rust/ql/integration-tests/hello-project/diagnostics.expected +++ b/rust/ql/integration-tests/hello-project/diagnostics.expected @@ -30,7 +30,7 @@ "pretty": "__REDACTED__" } }, - "numberOfFiles": 5, + "numberOfFiles": 6, "numberOfManifests": 1 }, "severity": "note", diff --git a/rust/ql/integration-tests/hello-project/steps.cargo.expected b/rust/ql/integration-tests/hello-project/steps.cargo.expected index 4deec0653daf..ca256c4f8569 100644 --- a/rust/ql/integration-tests/hello-project/steps.cargo.expected +++ b/rust/ql/integration-tests/hello-project/steps.cargo.expected @@ -1,4 +1,6 @@ | Cargo.toml:0:0:0:0 | LoadManifest(Cargo.toml) | +| file:///types.rs:0:0:0:0 | Extract(/types.rs) | +| file:///types.rs:0:0:0:0 | Parse(/types.rs) | | file://:0:0:0:0 | CrateGraph | | file://:0:0:0:0 | FindManifests | | src/directory_module/mod.rs:0:0:0:0 | Extract(src/directory_module/mod.rs) | diff --git a/rust/ql/integration-tests/hello-project/steps.ql b/rust/ql/integration-tests/hello-project/steps.ql index 17358a1c1000..fe45fc4b6dc8 100644 --- a/rust/ql/integration-tests/hello-project/steps.ql +++ b/rust/ql/integration-tests/hello-project/steps.ql @@ -1,4 +1,27 @@ import codeql.rust.elements.internal.ExtractorStep -from ExtractorStep step +private class Step instanceof ExtractorStep { + string toString() { + result = super.getAction() + "(" + this.getFilePath() + ")" + or + not super.hasFile() and result = super.getAction() + } + + private string getFilePath() { + exists(File file | file = super.getFile() | + exists(file.getRelativePath()) and result = file.getAbsolutePath() + or + not exists(file.getRelativePath()) and result = "/" + file.getBaseName() + ) + } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(_, startline, startcolumn, endline, endcolumn) and + filepath = this.getFilePath() + } +} + +from Step step select step diff --git a/rust/ql/integration-tests/hello-project/steps.rust-project.expected b/rust/ql/integration-tests/hello-project/steps.rust-project.expected index fa790e6cd7fd..165a770e1cba 100644 --- a/rust/ql/integration-tests/hello-project/steps.rust-project.expected +++ b/rust/ql/integration-tests/hello-project/steps.rust-project.expected @@ -1,3 +1,5 @@ +| file:///types.rs:0:0:0:0 | Extract(/types.rs) | +| file:///types.rs:0:0:0:0 | Parse(/types.rs) | | file://:0:0:0:0 | CrateGraph | | file://:0:0:0:0 | FindManifests | | rust-project.json:0:0:0:0 | LoadManifest(rust-project.json) | diff --git a/rust/ql/integration-tests/hello-project/summary.expected b/rust/ql/integration-tests/hello-project/summary.expected index 1f343b197c0f..15ee83de7adc 100644 --- a/rust/ql/integration-tests/hello-project/summary.expected +++ b/rust/ql/integration-tests/hello-project/summary.expected @@ -9,7 +9,7 @@ | Inconsistencies - Path resolution | 0 | | Inconsistencies - SSA | 0 | | Inconsistencies - data flow | 0 | -| Lines of code extracted | 6 | +| Lines of code extracted | 23 | | Lines of user code extracted | 6 | | Macro calls - resolved | 2 | | Macro calls - total | 2 | diff --git a/rust/ql/integration-tests/hello-workspace/diagnostics.cargo.expected b/rust/ql/integration-tests/hello-workspace/diagnostics.cargo.expected index 9429dada005e..146d8514488e 100644 --- a/rust/ql/integration-tests/hello-workspace/diagnostics.cargo.expected +++ b/rust/ql/integration-tests/hello-workspace/diagnostics.cargo.expected @@ -30,7 +30,7 @@ "pretty": "__REDACTED__" } }, - "numberOfFiles": 4, + "numberOfFiles": 5, "numberOfManifests": 1 }, "severity": "note", diff --git a/rust/ql/integration-tests/hello-workspace/diagnostics.rust-project.expected b/rust/ql/integration-tests/hello-workspace/diagnostics.rust-project.expected index 9429dada005e..146d8514488e 100644 --- a/rust/ql/integration-tests/hello-workspace/diagnostics.rust-project.expected +++ b/rust/ql/integration-tests/hello-workspace/diagnostics.rust-project.expected @@ -30,7 +30,7 @@ "pretty": "__REDACTED__" } }, - "numberOfFiles": 4, + "numberOfFiles": 5, "numberOfManifests": 1 }, "severity": "note", diff --git a/rust/ql/integration-tests/hello-workspace/steps.cargo.expected b/rust/ql/integration-tests/hello-workspace/steps.cargo.expected index 32a3b1110247..03c81ea6fb71 100644 --- a/rust/ql/integration-tests/hello-workspace/steps.cargo.expected +++ b/rust/ql/integration-tests/hello-workspace/steps.cargo.expected @@ -5,6 +5,8 @@ | exe/src/main.rs:0:0:0:0 | Extract(exe/src/main.rs) | | exe/src/main.rs:0:0:0:0 | LoadSource(exe/src/main.rs) | | exe/src/main.rs:0:0:0:0 | Parse(exe/src/main.rs) | +| file:///types.rs:0:0:0:0 | Extract(/types.rs) | +| file:///types.rs:0:0:0:0 | Parse(/types.rs) | | file://:0:0:0:0 | CrateGraph | | file://:0:0:0:0 | FindManifests | | lib/src/a_module/mod.rs:0:0:0:0 | Extract(lib/src/a_module/mod.rs) | diff --git a/rust/ql/integration-tests/hello-workspace/steps.ql b/rust/ql/integration-tests/hello-workspace/steps.ql index 17358a1c1000..fe45fc4b6dc8 100644 --- a/rust/ql/integration-tests/hello-workspace/steps.ql +++ b/rust/ql/integration-tests/hello-workspace/steps.ql @@ -1,4 +1,27 @@ import codeql.rust.elements.internal.ExtractorStep -from ExtractorStep step +private class Step instanceof ExtractorStep { + string toString() { + result = super.getAction() + "(" + this.getFilePath() + ")" + or + not super.hasFile() and result = super.getAction() + } + + private string getFilePath() { + exists(File file | file = super.getFile() | + exists(file.getRelativePath()) and result = file.getAbsolutePath() + or + not exists(file.getRelativePath()) and result = "/" + file.getBaseName() + ) + } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(_, startline, startcolumn, endline, endcolumn) and + filepath = this.getFilePath() + } +} + +from Step step select step diff --git a/rust/ql/integration-tests/hello-workspace/steps.rust-project.expected b/rust/ql/integration-tests/hello-workspace/steps.rust-project.expected index e9a65e0c7be5..0cf90cf71e02 100644 --- a/rust/ql/integration-tests/hello-workspace/steps.rust-project.expected +++ b/rust/ql/integration-tests/hello-workspace/steps.rust-project.expected @@ -4,6 +4,8 @@ | exe/src/main.rs:0:0:0:0 | Extract(exe/src/main.rs) | | exe/src/main.rs:0:0:0:0 | LoadSource(exe/src/main.rs) | | exe/src/main.rs:0:0:0:0 | Parse(exe/src/main.rs) | +| file:///types.rs:0:0:0:0 | Extract(/types.rs) | +| file:///types.rs:0:0:0:0 | Parse(/types.rs) | | file://:0:0:0:0 | CrateGraph | | file://:0:0:0:0 | FindManifests | | lib/src/a_module/mod.rs:0:0:0:0 | Extract(lib/src/a_module/mod.rs) | diff --git a/rust/ql/integration-tests/hello-workspace/summary.cargo.expected b/rust/ql/integration-tests/hello-workspace/summary.cargo.expected index 5912f7d69baf..c845417a6244 100644 --- a/rust/ql/integration-tests/hello-workspace/summary.cargo.expected +++ b/rust/ql/integration-tests/hello-workspace/summary.cargo.expected @@ -9,7 +9,7 @@ | Inconsistencies - Path resolution | 0 | | Inconsistencies - SSA | 0 | | Inconsistencies - data flow | 0 | -| Lines of code extracted | 9 | +| Lines of code extracted | 26 | | Lines of user code extracted | 9 | | Macro calls - resolved | 2 | | Macro calls - total | 2 | diff --git a/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected b/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected index 5912f7d69baf..c845417a6244 100644 --- a/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected +++ b/rust/ql/integration-tests/hello-workspace/summary.rust-project.expected @@ -9,7 +9,7 @@ | Inconsistencies - Path resolution | 0 | | Inconsistencies - SSA | 0 | | Inconsistencies - data flow | 0 | -| Lines of code extracted | 9 | +| Lines of code extracted | 26 | | Lines of user code extracted | 9 | | Macro calls - resolved | 2 | | Macro calls - total | 2 | diff --git a/rust/ql/integration-tests/workspace-with-glob/steps.expected b/rust/ql/integration-tests/workspace-with-glob/steps.expected index 4b0e6ed828b6..0ee55e79623f 100644 --- a/rust/ql/integration-tests/workspace-with-glob/steps.expected +++ b/rust/ql/integration-tests/workspace-with-glob/steps.expected @@ -1,6 +1,8 @@ | Cargo.toml:0:0:0:0 | LoadManifest(Cargo.toml) | | exe/src/main.rs:0:0:0:0 | Extract(exe/src/main.rs) | | exe/src/main.rs:0:0:0:0 | Parse(exe/src/main.rs) | +| file:///types.rs:0:0:0:0 | Extract(/types.rs) | +| file:///types.rs:0:0:0:0 | Parse(/types.rs) | | file://:0:0:0:0 | CrateGraph | | file://:0:0:0:0 | FindManifests | | lib/src/lib.rs:0:0:0:0 | Extract(lib/src/lib.rs) | diff --git a/rust/ql/integration-tests/workspace-with-glob/steps.ql b/rust/ql/integration-tests/workspace-with-glob/steps.ql index 17358a1c1000..fe45fc4b6dc8 100644 --- a/rust/ql/integration-tests/workspace-with-glob/steps.ql +++ b/rust/ql/integration-tests/workspace-with-glob/steps.ql @@ -1,4 +1,27 @@ import codeql.rust.elements.internal.ExtractorStep -from ExtractorStep step +private class Step instanceof ExtractorStep { + string toString() { + result = super.getAction() + "(" + this.getFilePath() + ")" + or + not super.hasFile() and result = super.getAction() + } + + private string getFilePath() { + exists(File file | file = super.getFile() | + exists(file.getRelativePath()) and result = file.getAbsolutePath() + or + not exists(file.getRelativePath()) and result = "/" + file.getBaseName() + ) + } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(_, startline, startcolumn, endline, endcolumn) and + filepath = this.getFilePath() + } +} + +from Step step select step From 0fc1ae272e8d08ab90b9d62b277c9772cc79d76e Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 1 May 2025 15:22:12 +0200 Subject: [PATCH 216/336] DataFlow: expose from FlowSummaries whether a summary is supported --- .../dataflow/internal/FlowSummaryImpl.qll | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll b/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll index 7fa38a327f16..9e6c4ff8b817 100644 --- a/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll @@ -530,6 +530,85 @@ module Make< } } + private predicate isNonLocalSummaryComponent(SummaryComponent c) { + c instanceof TArgumentSummaryComponent or + c instanceof TParameterSummaryComponent or + c instanceof TReturnSummaryComponent + } + + private predicate isLocalSummaryComponent(SummaryComponent c) { + not isNonLocalSummaryComponent(c) + } + + /** + * Holds if `s` is a valid input stack, in the sense that we generate data flow graph + * that faithfully represents this flow, and lambda-tracking can be expected to track + * lambdas to the relevant callbacks in practice. + */ + private predicate isSupportedInputStack(SummaryComponentStack s) { + // Argument[n].* + s.length() = 1 and + s.head() instanceof TArgumentSummaryComponent + or + // Argument[n].ReturnValue.* + s.length() = 2 and + s.head() instanceof TReturnSummaryComponent and + s.tail().head() instanceof TArgumentSummaryComponent + or + // Argument[n].Parameter[n].Content.* + s.length() = 3 and + s.head() instanceof TContentSummaryComponent and + s.tail().head() instanceof TParameterSummaryComponent and + s.drop(2).head() instanceof TArgumentSummaryComponent + or + isSupportedInputStack(s.tail()) and + isLocalSummaryComponent(s.head()) + } + + /** Like `isSupportedInputStack` but for output stacks. */ + private predicate isSupportedOutputStack(SummaryComponentStack s) { + // ReturnValue.* + s.length() = 1 and + s.head() instanceof TReturnSummaryComponent + or + // Argument[n].Content.* + s.length() = 2 and + s.head() instanceof TContentSummaryComponent and + s.tail().head() instanceof TArgumentSummaryComponent + or + // Argument[n].Parameter[n].* + s.length() = 2 and + s.head() instanceof TParameterSummaryComponent and + s.tail().head() instanceof TArgumentSummaryComponent + or + isSupportedOutputStack(s.tail()) and + isLocalSummaryComponent(s.head()) + } + + /** + * Holds if `callable` has an unsupported flow `input -> output`. + * + * `whichOne` indicates if the `input` or `output` contains the unsupported sequence. + */ + predicate unsupportedCallable( + SummarizedCallableImpl callable, SummaryComponentStack input, SummaryComponentStack output, + string whichOne + ) { + callable.propagatesFlow(input, output, _, _) and + ( + not isSupportedInputStack(input) and whichOne = "input" + or + not isSupportedOutputStack(output) and whichOne = "output" + ) + } + + /** + * Holds if `callable` has an unsupported flow. + */ + predicate unsupportedCallable(SummarizedCallableImpl callable) { + unsupportedCallable(callable, _, _, _) + } + private predicate summarySpec(string spec) { exists(SummarizedCallable c | c.propagatesFlow(spec, _, _, _) From a44bdf3be231dcfc083279ca0e49ddbede93debe Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 1 May 2025 15:22:38 +0200 Subject: [PATCH 217/336] JS: Generate summaries from summaryModel, and only generate steps as a fallback --- .../dataflow/internal/FlowSummaryPrivate.qll | 4 ++ .../frameworks/data/ModelsAsData.qll | 40 +++++++++++++++++++ .../TripleDot/underscore.string.js | 8 ++-- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSummaryPrivate.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSummaryPrivate.qll index 0f25c694f61c..31f5f16bbfb1 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSummaryPrivate.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSummaryPrivate.qll @@ -264,3 +264,7 @@ module Stage { cached predicate backref() { optionalStep(_, _, _) } } + +predicate unsupportedCallable = Private::unsupportedCallable/1; + +predicate unsupportedCallable = Private::unsupportedCallable/4; diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll index 9f143a9713ad..0e19e84b666f 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll @@ -19,6 +19,7 @@ private import javascript private import internal.ApiGraphModels as Shared private import internal.ApiGraphModelsSpecific as Specific +private import semmle.javascript.dataflow.internal.FlowSummaryPrivate private import semmle.javascript.endpoints.EndpointNaming as EndpointNaming import Shared::ModelInput as ModelInput import Shared::ModelOutput as ModelOutput @@ -45,12 +46,50 @@ private class ThreatModelSourceFromDataExtension extends ThreatModelSource::Rang } } +private class SummarizedCallableFromModel extends DataFlow::SummarizedCallable { + string type; + string path; + + SummarizedCallableFromModel() { + ModelOutput::relevantSummaryModel(type, path, _, _, _, _) and + this = type + ";" + path + } + + override DataFlow::InvokeNode getACall() { ModelOutput::resolvedSummaryBase(type, path, result) } + + override predicate propagatesFlow( + string input, string output, boolean preservesValue, string model + ) { + exists(string kind | ModelOutput::relevantSummaryModel(type, path, input, output, kind, model) | + kind = "value" and + preservesValue = true + or + kind = "taint" and + preservesValue = false + ) + } + + predicate hasTypeAndPath(string type_, string path_) { type = type_ and path = path_ } + + predicate isUnsupportedByFlowSummaries() { unsupportedCallable(this) } +} + +private predicate shouldInduceStepsFromSummary(string type, string path) { + exists(SummarizedCallableFromModel callable | + callable.isUnsupportedByFlowSummaries() and + callable.hasTypeAndPath(type, path) + ) +} + /** * Holds if `path` is an input or output spec for a summary with the given `base` node. */ pragma[nomagic] private predicate relevantInputOutputPath(API::InvokeNode base, AccessPath inputOrOutput) { exists(string type, string input, string output, string path | + // If the summary for 'callable' could not be handled as a flow summary, we need to evaluate + // its inputs and outputs to a set of nodes, so we can generate steps instead. + shouldInduceStepsFromSummary(type, path) and ModelOutput::resolvedSummaryBase(type, path, base) and ModelOutput::relevantSummaryModel(type, path, input, output, _, _) and inputOrOutput = [input, output] @@ -81,6 +120,7 @@ private API::Node getNodeFromInputOutputPath(API::InvokeNode baseNode, AccessPat private predicate summaryStep(API::Node pred, API::Node succ, string kind) { exists(string type, string path, API::InvokeNode base, AccessPath input, AccessPath output | + shouldInduceStepsFromSummary(type, path) and ModelOutput::relevantSummaryModel(type, path, input, output, kind, _) and ModelOutput::resolvedSummaryBase(type, path, base) and pred = getNodeFromInputOutputPath(base, input) and diff --git a/javascript/ql/test/library-tests/TripleDot/underscore.string.js b/javascript/ql/test/library-tests/TripleDot/underscore.string.js index 07f186343ce2..dd904cd78c3b 100644 --- a/javascript/ql/test/library-tests/TripleDot/underscore.string.js +++ b/javascript/ql/test/library-tests/TripleDot/underscore.string.js @@ -39,7 +39,7 @@ function strToStr() { } function strToArray() { - sink(s.chop(source("s1"), 3)); // $ MISSING: hasTaintFlow=s1 + sink(s.chop(source("s1"), 3)); // $ hasTaintFlow=s1 sink(s.chars(source("s2"))[0]); // $ hasTaintFlow=s2 sink(s.words(source("s3"))[0]); // $ hasTaintFlow=s3 sink(s.lines(source("s7"))[0]); // $ hasTaintFlow=s7 @@ -97,7 +97,7 @@ function multiSource() { function chaining() { sink(s(source("s1")) - .slugify().capitalize().decapitalize().clean().cleanDiacritics() + .slugify().capitalize().decapitalize().clean().cleanDiacritics() .swapCase().escapeHTML().unescapeHTML().wrap().dedent() .reverse().pred().succ().titleize().camelize().classify() .underscored().dasherize().humanize().trim().ltrim().rtrim() @@ -119,8 +119,8 @@ function chaining() { .q(source("s17")).ljust(10, source("s18")) .rjust(10, source("s19"))); // $ hasTaintFlow=s16 hasTaintFlow=s17 hasTaintFlow=s18 hasTaintFlow=s19 - sink(s(source("s20")).tap(function(value) { - return value + source("s21"); + sink(s(source("s20")).tap(function(value) { + return value + source("s21"); }).value()); // $ hasTaintFlow=s20 hasTaintFlow=s21 } From 73fa381dbcc96975611249e09cfeec6435836a2e Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 30 Apr 2025 19:49:47 +0200 Subject: [PATCH 218/336] Rust: Remove visibility check in path resolution --- .../codeql/rust/internal/PathResolution.qll | 93 ++++++------------- .../dataflow/modeled/inline-flow.expected | 15 +++ .../library-tests/dataflow/modeled/main.rs | 2 +- .../PathResolutionConsistency.expected | 41 ++++++++ 4 files changed, 87 insertions(+), 64 deletions(-) create mode 100644 rust/ql/test/query-tests/security/CWE-022/CONSISTENCY/PathResolutionConsistency.expected diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index 5bc45afecf17..d1878ce3daea 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -87,11 +87,6 @@ abstract class ItemNode extends Locatable { /** Gets the `i`th type parameter of this item, if any. */ abstract TypeParam getTypeParam(int i); - /** Holds if this item is declared as `pub`. */ - bindingset[this] - pragma[inline_late] - predicate isPublic() { exists(this.getVisibility()) } - /** Gets an element that has this item as immediately enclosing item. */ pragma[nomagic] Element getADescendant() { @@ -207,6 +202,11 @@ abstract class ItemNode extends Locatable { result.(CrateItemNode).isPotentialDollarCrateTarget() } + pragma[nomagic] + private predicate hasSourceFunction(string name) { + this.getASuccessorFull(name).(Function).fromSource() + } + /** Gets a successor named `name` of this item, if any. */ pragma[nomagic] ItemNode getASuccessor(string name) { @@ -219,7 +219,7 @@ abstract class ItemNode extends Locatable { or not result instanceof Function or - not this.getASuccessorFull(name).(Function).fromSource() + not this.hasSourceFunction(name) ) } @@ -266,8 +266,6 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile { override Visibility getVisibility() { none() } - override predicate isPublic() { any() } - override TypeParam getTypeParam(int i) { none() } } @@ -330,8 +328,6 @@ class CrateItemNode extends ItemNode instanceof Crate { override Visibility getVisibility() { none() } - override predicate isPublic() { any() } - override TypeParam getTypeParam(int i) { none() } } @@ -436,7 +432,7 @@ abstract class ImplOrTraitItemNode extends ItemNode { pragma[nomagic] private TypeParamItemNode resolveTypeParamPathTypeRepr(PathTypeRepr ptr) { - result = resolvePath(ptr.getPath()) + result = resolvePathFull(ptr.getPath()) } class ImplItemNode extends ImplOrTraitItemNode instanceof Impl { @@ -444,9 +440,9 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl { Path getTraitPath() { result = super.getTrait().(PathTypeRepr).getPath() } - ItemNode resolveSelfTy() { result = resolvePath(this.getSelfPath()) } + ItemNode resolveSelfTy() { result = resolvePathFull(this.getSelfPath()) } - TraitItemNode resolveTraitTy() { result = resolvePath(this.getTraitPath()) } + TraitItemNode resolveTraitTy() { result = resolvePathFull(this.getTraitPath()) } pragma[nomagic] private TypeRepr getASelfTyArg() { @@ -560,7 +556,7 @@ class TraitItemNode extends ImplOrTraitItemNode instanceof Trait { } pragma[nomagic] - ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) } + ItemNode resolveABound() { result = resolvePathFull(this.getABoundPath()) } override AssocItemNode getAnAssocItem() { result = super.getAssocItemList().getAnAssocItem() } @@ -634,7 +630,7 @@ class TypeParamItemNode extends ItemNode instanceof TypeParam { } pragma[nomagic] - ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) } + ItemNode resolveABound() { result = resolvePathFull(this.getABoundPath()) } /** * Holds if this type parameter has a trait bound. Examples: @@ -897,12 +893,6 @@ class RelevantPath extends Path { this.getQualifier().(RelevantPath).isCratePath("$crate", _) and this.getText() = name } - - // TODO: Remove once the crate graph extractor generates publicly visible paths - predicate requiresExtractorWorkaround() { - not this.fromSource() and - this = any(RelevantPath p).getQualifier() - } } private predicate isModule(ItemNode m) { m instanceof Module } @@ -1056,8 +1046,14 @@ private predicate pathUsesNamespace(Path p, Namespace n) { ) } +/** + * Gets the item that `path` resolves to, if any. + * + * Whenever `path` can resolve to both a function in source code and in library + * code, both are included + */ pragma[nomagic] -private ItemNode resolvePath1(RelevantPath path) { +private ItemNode resolvePathFull(RelevantPath path) { exists(Namespace ns | result = resolvePath0(path, ns) | pathUsesNamespace(path, ns) or @@ -1067,58 +1063,29 @@ private ItemNode resolvePath1(RelevantPath path) { } pragma[nomagic] -private ItemNode resolvePathPrivate( - RelevantPath path, ModuleLikeNode itemParent, ModuleLikeNode pathParent -) { - not path.requiresExtractorWorkaround() and - result = resolvePath1(path) and - itemParent = result.getImmediateParentModule() and - not result.isPublic() and - ( - pathParent.getADescendant() = path - or - pathParent = any(ItemNode mid | path = mid.getADescendant()).getImmediateParentModule() - ) -} - -pragma[nomagic] -private predicate isItemParent(ModuleLikeNode itemParent) { - exists(resolvePathPrivate(_, itemParent, _)) -} - -/** - * Gets a module that has access to private items defined inside `itemParent`. - * - * According to [The Rust Reference][1] this is either `itemParent` itself or any - * descendant of `itemParent`. - * - * [1]: https://doc.rust-lang.org/reference/visibility-and-privacy.html#r-vis.access - */ -pragma[nomagic] -private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) { - isItemParent(itemParent) and - result.getImmediateParentModule*() = itemParent +private predicate resolvesSourceFunction(RelevantPath path) { + resolvePathFull(path).(Function).fromSource() } /** Gets the item that `path` resolves to, if any. */ cached ItemNode resolvePath(RelevantPath path) { - result = resolvePath1(path) and + result = resolvePathFull(path) and ( - result.isPublic() + // when a function exists in both source code and in library code, it is because + // we also extracted the source code as library code, and hence we only want + // the function from source code + result.fromSource() or - path.requiresExtractorWorkaround() - ) - or - exists(ModuleLikeNode itemParent, ModuleLikeNode pathParent | - result = resolvePathPrivate(path, itemParent, pathParent) and - pathParent = getAPrivateVisibleModule(itemParent) + not result instanceof Function + or + not resolvesSourceFunction(path) ) } pragma[nomagic] private ItemNode resolvePathQualifier(RelevantPath path, string name) { - result = resolvePath(path.getQualifier()) and + result = resolvePathFull(path.getQualifier()) and name = path.getText() } @@ -1164,7 +1131,7 @@ private ItemNode resolveUseTreeListItemQualifier( pragma[nomagic] private ItemNode resolveUseTreeListItem(Use use, UseTree tree) { tree = use.getUseTree() and - result = resolvePath(tree.getPath()) + result = resolvePathFull(tree.getPath()) or result = resolveUseTreeListItem(use, tree, tree.getPath()) } diff --git a/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected b/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected index 198f8ab9cd8c..9ff1be3b3c50 100644 --- a/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/modeled/inline-flow.expected @@ -29,8 +29,15 @@ edges | main.rs:41:17:41:41 | Wrapper {...} [Wrapper] | main.rs:41:13:41:13 | w [Wrapper] | provenance | | | main.rs:41:30:41:39 | source(...) | main.rs:41:17:41:41 | Wrapper {...} [Wrapper] | provenance | | | main.rs:42:15:42:15 | w [Wrapper] | main.rs:43:13:43:28 | Wrapper {...} [Wrapper] | provenance | | +| main.rs:42:15:42:15 | w [Wrapper] | main.rs:45:17:45:17 | w [Wrapper] | provenance | | | main.rs:43:13:43:28 | Wrapper {...} [Wrapper] | main.rs:43:26:43:26 | n | provenance | | | main.rs:43:26:43:26 | n | main.rs:43:38:43:38 | n | provenance | | +| main.rs:45:13:45:13 | u [Wrapper] | main.rs:46:15:46:15 | u [Wrapper] | provenance | | +| main.rs:45:17:45:17 | w [Wrapper] | main.rs:45:17:45:25 | w.clone() [Wrapper] | provenance | generated | +| main.rs:45:17:45:25 | w.clone() [Wrapper] | main.rs:45:13:45:13 | u [Wrapper] | provenance | | +| main.rs:46:15:46:15 | u [Wrapper] | main.rs:47:13:47:28 | Wrapper {...} [Wrapper] | provenance | | +| main.rs:47:13:47:28 | Wrapper {...} [Wrapper] | main.rs:47:26:47:26 | n | provenance | | +| main.rs:47:26:47:26 | n | main.rs:47:38:47:38 | n | provenance | | | main.rs:58:13:58:13 | b [Some] | main.rs:59:23:59:23 | b [Some] | provenance | | | main.rs:58:17:58:32 | Some(...) [Some] | main.rs:58:13:58:13 | b [Some] | provenance | | | main.rs:58:22:58:31 | source(...) | main.rs:58:17:58:32 | Some(...) [Some] | provenance | | @@ -71,6 +78,13 @@ nodes | main.rs:43:13:43:28 | Wrapper {...} [Wrapper] | semmle.label | Wrapper {...} [Wrapper] | | main.rs:43:26:43:26 | n | semmle.label | n | | main.rs:43:38:43:38 | n | semmle.label | n | +| main.rs:45:13:45:13 | u [Wrapper] | semmle.label | u [Wrapper] | +| main.rs:45:17:45:17 | w [Wrapper] | semmle.label | w [Wrapper] | +| main.rs:45:17:45:25 | w.clone() [Wrapper] | semmle.label | w.clone() [Wrapper] | +| main.rs:46:15:46:15 | u [Wrapper] | semmle.label | u [Wrapper] | +| main.rs:47:13:47:28 | Wrapper {...} [Wrapper] | semmle.label | Wrapper {...} [Wrapper] | +| main.rs:47:26:47:26 | n | semmle.label | n | +| main.rs:47:38:47:38 | n | semmle.label | n | | main.rs:58:13:58:13 | b [Some] | semmle.label | b [Some] | | main.rs:58:17:58:32 | Some(...) [Some] | semmle.label | Some(...) [Some] | | main.rs:58:22:58:31 | source(...) | semmle.label | source(...) | @@ -95,5 +109,6 @@ testFailures | main.rs:22:10:22:19 | b.unwrap() | main.rs:19:34:19:43 | source(...) | main.rs:22:10:22:19 | b.unwrap() | $@ | main.rs:19:34:19:43 | source(...) | source(...) | | main.rs:27:10:27:10 | a | main.rs:26:13:26:22 | source(...) | main.rs:27:10:27:10 | a | $@ | main.rs:26:13:26:22 | source(...) | source(...) | | main.rs:43:38:43:38 | n | main.rs:41:30:41:39 | source(...) | main.rs:43:38:43:38 | n | $@ | main.rs:41:30:41:39 | source(...) | source(...) | +| main.rs:47:38:47:38 | n | main.rs:41:30:41:39 | source(...) | main.rs:47:38:47:38 | n | $@ | main.rs:41:30:41:39 | source(...) | source(...) | | main.rs:63:22:63:22 | m | main.rs:58:22:58:31 | source(...) | main.rs:63:22:63:22 | m | $@ | main.rs:58:22:58:31 | source(...) | source(...) | | main.rs:85:18:85:34 | ...::read(...) | main.rs:84:32:84:41 | source(...) | main.rs:85:18:85:34 | ...::read(...) | $@ | main.rs:84:32:84:41 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/modeled/main.rs b/rust/ql/test/library-tests/dataflow/modeled/main.rs index 648ffd0a307d..3ce3e0ecae04 100644 --- a/rust/ql/test/library-tests/dataflow/modeled/main.rs +++ b/rust/ql/test/library-tests/dataflow/modeled/main.rs @@ -44,7 +44,7 @@ mod my_clone { } let u = w.clone(); match u { - Wrapper { n: n } => sink(n), // $ MISSING: hasValueFlow=73 - lack of expanded derives means that we cannot resolve clone call above, and hence not insert implicit borrow + Wrapper { n: n } => sink(n), // $ hasValueFlow=73 } } } diff --git a/rust/ql/test/query-tests/security/CWE-022/CONSISTENCY/PathResolutionConsistency.expected b/rust/ql/test/query-tests/security/CWE-022/CONSISTENCY/PathResolutionConsistency.expected new file mode 100644 index 000000000000..03a2899da095 --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-022/CONSISTENCY/PathResolutionConsistency.expected @@ -0,0 +1,41 @@ +multiplePathResolutions +| src/main.rs:8:21:8:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:8:21:8:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:8:21:8:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:8:21:8:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:8:21:8:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:19:21:19:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:19:21:19:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:19:21:19:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:19:21:19:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:19:21:19:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:25:23:25:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:25:23:25:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:25:23:25:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:25:23:25:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:25:23:25:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:26:38:26:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:26:38:26:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:26:38:26:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:26:38:26:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:26:38:26:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:39:23:39:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:39:23:39:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:39:23:39:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:39:23:39:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:39:23:39:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:40:38:40:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:40:38:40:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:40:38:40:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:40:38:40:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:40:38:40:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:52:23:52:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:52:23:52:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:52:23:52:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:52:23:52:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:52:23:52:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:53:38:53:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:53:38:53:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:53:38:53:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:53:38:53:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:53:38:53:50 | ...::from | file://:0:0:0:0 | fn from | From bd3155ef0c698de8e35dcb6cdb8f545981d81f10 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 1 May 2025 16:42:13 +0100 Subject: [PATCH 219/336] Rust: Promote rust/uncontrolled-allocation-size to warning. --- .../src/queries/security/CWE-770/UncontrolledAllocationSize.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql index c41257743152..3d25ede3187d 100644 --- a/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql +++ b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql @@ -4,7 +4,7 @@ * arbitrary amounts of memory being allocated, leading to a crash or a * denial-of-service (DoS) attack. * @kind path-problem - * @problem.severity recommendation + * @problem.severity warning * @security-severity 7.5 * @precision high * @id rust/uncontrolled-allocation-size From c9ce6c0fb608501043e8130932cec64797c445cb Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 1 May 2025 16:42:41 +0100 Subject: [PATCH 220/336] Rust: Demote rust/cleartext-logging to warning. --- rust/ql/src/queries/security/CWE-312/CleartextLogging.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql b/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql index 75bd47e76dc9..c2a1dcc747f5 100644 --- a/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql +++ b/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql @@ -3,7 +3,7 @@ * @description Logging sensitive information in plaintext can * expose it to an attacker. * @kind path-problem - * @problem.severity error + * @problem.severity warning * @security-severity 7.5 * @precision high * @id rust/cleartext-logging From 93f8cea8845783adbac926b459989ba93107537d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 9 Apr 2025 15:44:54 +0100 Subject: [PATCH 221/336] Rust: Add + clean up some QLDoc. --- .../rust/elements/AssignmentOperation.qll | 18 ++++++++++++------ .../codeql/rust/elements/LogicalOperation.qll | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/AssignmentOperation.qll b/rust/ql/lib/codeql/rust/elements/AssignmentOperation.qll index 368e5738c191..a3ca1722b577 100644 --- a/rust/ql/lib/codeql/rust/elements/AssignmentOperation.qll +++ b/rust/ql/lib/codeql/rust/elements/AssignmentOperation.qll @@ -1,16 +1,23 @@ -/** Provides classes for assignment operations. */ +/** + * Provides classes for assignment operations. + */ private import rust private import codeql.rust.elements.internal.BinaryExprImpl -/** An assignment operation. */ +/** + * An assignment operation, for example: + * ```rust + * x = y; + * x += y; + * ``` + */ abstract private class AssignmentOperationImpl extends Impl::BinaryExpr { } final class AssignmentOperation = AssignmentOperationImpl; /** - * An assignment expression, for example - * + * An assignment expression, for example: * ```rust * x = y; * ``` @@ -22,8 +29,7 @@ final class AssignmentExpr extends AssignmentOperationImpl { } /** - * A compound assignment expression, for example - * + * A compound assignment expression, for example: * ```rust * x += y; * ``` diff --git a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll index fdbfb5d4613a..ab9aa6ef0fd4 100644 --- a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll +++ b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll @@ -2,30 +2,48 @@ private import codeql.rust.elements.Expr private import codeql.rust.elements.BinaryExpr private import codeql.rust.elements.PrefixExpr +/** + * A logical operation, such as `&&`, `||` or `!`. + */ abstract private class LogicalOperationImpl extends Expr { abstract Expr getAnOperand(); } final class LogicalOperation = LogicalOperationImpl; +/** + * A binary logical operation, such as `&&` or `||`. + */ abstract private class BinaryLogicalOperationImpl extends BinaryExpr, LogicalOperationImpl { override Expr getAnOperand() { result = [this.getLhs(), this.getRhs()] } } final class BinaryLogicalOperation = BinaryLogicalOperationImpl; +/** + * The logical and operation, `&&`. + */ final class LogicalAndExpr extends BinaryLogicalOperationImpl, BinaryExpr { LogicalAndExpr() { this.getOperatorName() = "&&" } } +/** + * The logical or operation, `||`. + */ final class LogicalOrExpr extends BinaryLogicalOperationImpl { LogicalOrExpr() { this.getOperatorName() = "||" } } +/** + * A unary logical operation, such as `!`. + */ abstract private class UnaryLogicalOperationImpl extends PrefixExpr, LogicalOperationImpl { } final class UnaryLogicalOperation = UnaryLogicalOperationImpl; +/** + * A logical not operation, `!`. + */ final class LogicalNotExpr extends UnaryLogicalOperationImpl { LogicalNotExpr() { this.getOperatorName() = "!" } From 778f46d5be80ff1657da988c5a041fb5b74e06c3 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Thu, 1 May 2025 22:21:48 +0200 Subject: [PATCH 222/336] Rust: adjust unit tests and expected output --- rust/ql/test/TestUtils.qll | 6 +++++- rust/ql/test/query-tests/diagnostics/LinesOfCode.expected | 2 +- .../query-tests/diagnostics/SummaryStatsReduced.expected | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/rust/ql/test/TestUtils.qll b/rust/ql/test/TestUtils.qll index ce494ff5a608..dc75d109a339 100644 --- a/rust/ql/test/TestUtils.qll +++ b/rust/ql/test/TestUtils.qll @@ -1,6 +1,6 @@ private import rust -predicate toBeTested(Element e) { not e instanceof CrateElement } +predicate toBeTested(Element e) { not e instanceof CrateElement and not e instanceof Builtin } class CrateElement extends Element { CrateElement() { @@ -9,3 +9,7 @@ class CrateElement extends Element { any(Crate c).getModule() = this.(AstNode).getParentNode*() } } + +class Builtin extends AstNode { + Builtin() { this.getFile().getAbsolutePath().matches("%/builtins/%.rs") } +} diff --git a/rust/ql/test/query-tests/diagnostics/LinesOfCode.expected b/rust/ql/test/query-tests/diagnostics/LinesOfCode.expected index 5fa7b20e01bb..76e48043d0d4 100644 --- a/rust/ql/test/query-tests/diagnostics/LinesOfCode.expected +++ b/rust/ql/test/query-tests/diagnostics/LinesOfCode.expected @@ -1 +1 @@ -| 60 | +| 77 | diff --git a/rust/ql/test/query-tests/diagnostics/SummaryStatsReduced.expected b/rust/ql/test/query-tests/diagnostics/SummaryStatsReduced.expected index ed21d9772fce..793ed90a482a 100644 --- a/rust/ql/test/query-tests/diagnostics/SummaryStatsReduced.expected +++ b/rust/ql/test/query-tests/diagnostics/SummaryStatsReduced.expected @@ -9,7 +9,7 @@ | Inconsistencies - Path resolution | 0 | | Inconsistencies - SSA | 0 | | Inconsistencies - data flow | 0 | -| Lines of code extracted | 60 | +| Lines of code extracted | 77 | | Lines of user code extracted | 60 | | Macro calls - resolved | 8 | | Macro calls - total | 9 | From 16fc8c3d9e46143d2872dcb91b7aa0bd01f5bbef Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 2 May 2025 11:09:19 +0200 Subject: [PATCH 223/336] JS: Benign test updates --- .../library-tests/frameworks/data/test.expected | 17 +++++++++++++++++ .../CWE-079/ReflectedXss/ReflectedXss.expected | 6 +++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/javascript/ql/test/library-tests/frameworks/data/test.expected b/javascript/ql/test/library-tests/frameworks/data/test.expected index 0bc1b6b6ee07..875b0189d619 100644 --- a/javascript/ql/test/library-tests/frameworks/data/test.expected +++ b/javascript/ql/test/library-tests/frameworks/data/test.expected @@ -1,4 +1,21 @@ legacyDataFlowDifference +| test.js:5:30:5:37 | source() | test.js:5:8:5:38 | testlib ... urce()) | only flow with NEW data flow library | +| test.js:6:22:6:29 | source() | test.js:6:8:6:30 | preserv ... urce()) | only flow with NEW data flow library | +| test.js:7:41:7:48 | source() | test.js:7:8:7:49 | require ... urce()) | only flow with NEW data flow library | +| test.js:11:38:11:45 | source() | test.js:11:8:11:55 | testlib ... , 1, 1) | only flow with NEW data flow library | +| test.js:13:44:13:51 | source() | test.js:13:8:13:55 | testlib ... e(), 1) | only flow with NEW data flow library | +| test.js:17:47:17:54 | source() | test.js:17:8:17:61 | testlib ... , 1, 1) | only flow with NEW data flow library | +| test.js:18:50:18:57 | source() | test.js:18:8:18:61 | testlib ... e(), 1) | only flow with NEW data flow library | +| test.js:19:53:19:60 | source() | test.js:19:8:19:61 | testlib ... urce()) | only flow with NEW data flow library | +| test.js:21:34:21:41 | source() | test.js:21:8:21:51 | testlib ... , 1, 1) | only flow with NEW data flow library | +| test.js:22:37:22:44 | source() | test.js:22:8:22:51 | testlib ... , 1, 1) | only flow with NEW data flow library | +| test.js:23:40:23:47 | source() | test.js:23:8:23:51 | testlib ... e(), 1) | only flow with NEW data flow library | +| test.js:24:43:24:50 | source() | test.js:24:8:24:51 | testlib ... urce()) | only flow with NEW data flow library | +| test.js:31:29:31:36 | source() | test.js:32:10:32:10 | y | only flow with NEW data flow library | +| test.js:37:29:37:36 | source() | test.js:38:10:38:10 | y | only flow with NEW data flow library | +| test.js:43:29:43:36 | source() | test.js:44:10:44:10 | y | only flow with NEW data flow library | +| test.js:47:33:47:40 | source() | test.js:49:10:49:13 | this | only flow with NEW data flow library | +| test.js:102:16:102:34 | testlib.getSource() | test.js:104:8:104:24 | source.continue() | only flow with NEW data flow library | consistencyIssue taintFlow | guardedRouteHandler.js:6:10:6:28 | req.injectedReqData | guardedRouteHandler.js:6:10:6:28 | req.injectedReqData | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected index 5681ae99aa85..09874ecef104 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected @@ -78,7 +78,9 @@ edges | ReflectedXss.js:22:19:22:26 | req.body | ReflectedXss.js:22:12:22:27 | marked(req.body) | provenance | | | ReflectedXss.js:29:7:32:4 | mytable | ReflectedXss.js:33:12:33:18 | mytable | provenance | | | ReflectedXss.js:29:17:32:4 | table([ ... ce\\n ]) | ReflectedXss.js:29:7:32:4 | mytable | provenance | | -| ReflectedXss.js:31:14:31:21 | req.body | ReflectedXss.js:29:17:32:4 | table([ ... ce\\n ]) | provenance | | +| ReflectedXss.js:29:23:32:3 | [\\n [ ... rce\\n ] [1, 1] | ReflectedXss.js:29:17:32:4 | table([ ... ce\\n ]) | provenance | | +| ReflectedXss.js:31:5:31:22 | ['body', req.body] [1] | ReflectedXss.js:29:23:32:3 | [\\n [ ... rce\\n ] [1, 1] | provenance | | +| ReflectedXss.js:31:14:31:21 | req.body | ReflectedXss.js:31:5:31:22 | ['body', req.body] [1] | provenance | | | ReflectedXss.js:41:31:41:38 | req.body | ReflectedXss.js:41:12:41:39 | convert ... q.body) | provenance | | | ReflectedXss.js:63:14:63:21 | req.body | ReflectedXss.js:63:39:63:42 | file | provenance | | | ReflectedXss.js:63:39:63:42 | file | ReflectedXss.js:64:16:64:19 | file | provenance | | @@ -253,6 +255,8 @@ nodes | ReflectedXss.js:28:12:28:19 | req.body | semmle.label | req.body | | ReflectedXss.js:29:7:32:4 | mytable | semmle.label | mytable | | ReflectedXss.js:29:17:32:4 | table([ ... ce\\n ]) | semmle.label | table([ ... ce\\n ]) | +| ReflectedXss.js:29:23:32:3 | [\\n [ ... rce\\n ] [1, 1] | semmle.label | [\\n [ ... rce\\n ] [1, 1] | +| ReflectedXss.js:31:5:31:22 | ['body', req.body] [1] | semmle.label | ['body', req.body] [1] | | ReflectedXss.js:31:14:31:21 | req.body | semmle.label | req.body | | ReflectedXss.js:33:12:33:18 | mytable | semmle.label | mytable | | ReflectedXss.js:40:12:40:19 | req.body | semmle.label | req.body | From f64e86fe2e661d88b892c483e7d8fe7015d39c9b Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 9 Apr 2025 20:55:34 +0100 Subject: [PATCH 224/336] Rust: Add a library test for Operations. --- .../operations/Operations.expected | 0 .../library-tests/operations/Operations.ql | 30 ++++++++++ rust/ql/test/library-tests/operations/test.rs | 57 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 rust/ql/test/library-tests/operations/Operations.expected create mode 100644 rust/ql/test/library-tests/operations/Operations.ql create mode 100644 rust/ql/test/library-tests/operations/test.rs diff --git a/rust/ql/test/library-tests/operations/Operations.expected b/rust/ql/test/library-tests/operations/Operations.expected new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/rust/ql/test/library-tests/operations/Operations.ql b/rust/ql/test/library-tests/operations/Operations.ql new file mode 100644 index 000000000000..7605aa9e7196 --- /dev/null +++ b/rust/ql/test/library-tests/operations/Operations.ql @@ -0,0 +1,30 @@ +import rust +import utils.test.InlineExpectationsTest + +string describe(Expr op) { + op instanceof PrefixExpr and result = "PrefixExpr" + or + op instanceof BinaryExpr and result = "BinaryExpr" + or + op instanceof AssignmentOperation and result = "AssignmentOperation" + or + op instanceof LogicalOperation and result = "LogicalOperation" + or + op instanceof RefExpr and result = "RefExpr" +} + +module OperationsTest implements TestSig { + string getARelevantTag() { result = describe(_) } + + predicate hasActualResult(Location location, string element, string tag, string value) { + exists(Expr op | + location = op.getLocation() and + location.getFile().getBaseName() != "" and + element = op.toString() and + tag = describe(op) and + value = "" + ) + } +} + +import MakeTest diff --git a/rust/ql/test/library-tests/operations/test.rs b/rust/ql/test/library-tests/operations/test.rs new file mode 100644 index 000000000000..84152bd70723 --- /dev/null +++ b/rust/ql/test/library-tests/operations/test.rs @@ -0,0 +1,57 @@ + +// --- tests --- + +fn test_operations( + y: i32, a: bool, b: bool, + ptr: &i32, res: Result) -> Result<(), ()> +{ + let mut x: i32; + + // simple assignment + x = y; // $ AssignmentOperation BinaryExpr + + // comparison operations + x == y; // $ BinaryExpr + x != y; // $ BinaryExpr + x < y; // $ BinaryExpr + x <= y; // $ BinaryExpr + x > y; // $ BinaryExpr + x >= y; // $ BinaryExpr + + // arithmetic operations + x + y; // $ BinaryExpr + x - y; // $ BinaryExpr + x * y; // $ BinaryExpr + x / y; // $ BinaryExpr + x % y; // $ BinaryExpr + x += y; // $ AssignmentOperation BinaryExpr + x -= y; // $ AssignmentOperation BinaryExpr + x *= y; // $ AssignmentOperation BinaryExpr + x /= y; // $ AssignmentOperation BinaryExpr + x %= y; // $ AssignmentOperation BinaryExpr + -x; // $ PrefixExpr + + // logical operations + a && b; // $ BinaryExpr LogicalOperation + a || b; // $ BinaryExpr LogicalOperation + !a; // $ PrefixExpr LogicalOperation + + // bitwise operations + x & y; // $ BinaryExpr + x | y; // $ BinaryExpr + x ^ y; // $ BinaryExpr + x << y; // $ BinaryExpr + x >> y; // $ BinaryExpr + x &= y; // $ AssignmentOperation BinaryExpr + x |= y; // $ AssignmentOperation BinaryExpr + x ^= y; // $ AssignmentOperation BinaryExpr + x <<= y; // $ AssignmentOperation BinaryExpr + x >>= y; // $ AssignmentOperation BinaryExpr + + // miscellaneous expressions that might be operations + *ptr; // $ PrefixExpr + &x; // $ RefExpr + res?; + + return Ok(()); +} From f3e0cfd947ab686185be16c5b029326c2ba8f665 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 2 May 2025 12:41:29 +0200 Subject: [PATCH 225/336] Apply suggestions from code review Co-authored-by: Erik Krogh Kristensen --- javascript/ql/lib/semmle/javascript/TSConfig.qll | 2 +- .../ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/TSConfig.qll b/javascript/ql/lib/semmle/javascript/TSConfig.qll index b38fa1d1dc92..c10177e5fe24 100644 --- a/javascript/ql/lib/semmle/javascript/TSConfig.qll +++ b/javascript/ql/lib/semmle/javascript/TSConfig.qll @@ -141,7 +141,7 @@ class TSConfig extends JsonObject { } /** - * Holds if this has an exact path mapping from `pattern` to `newPath`. + * Holds if this has an exact path mapping (i.e. no wildcards) from `pattern` to `newPath`. * * For example, `"paths": { "@": "./src/index.ts" }` maps the `@` path to `./src/index.ts`. * diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll index 4e2a51aaf7d4..5f4a6eb930ea 100644 --- a/javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll @@ -2,7 +2,7 @@ private import javascript private import semmle.javascript.internal.paths.JSPaths /** - * Extension of `PackageJson` with some internal path-resolution predicates. + * A `package.json` file. The class is an extension of the `PackageJson` class with some internal path-resolution predicates. */ class PackageJsonEx extends PackageJson { private JsonValue getAPartOfExportsSection(string pattern) { From c6d95ceeb011f3ba0b0cd6ec9ee5e3e0cc14f212 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Fri, 2 May 2025 13:21:10 +0200 Subject: [PATCH 226/336] Shared: Remove the language-specific model generator scripts --- .github/workflows/mad_modelDiff.yml | 2 +- .../utils/modelgenerator/GenerateFlowModel.py | 15 ----- .../2025-05-02-mad-generator-renamed.md | 8 +++ .../utils/modelgenerator/GenerateFlowModel.py | 15 ----- .../2025-05-02-mad-generator-renamed.md | 8 +++ .../utils/modelgenerator/GenerateFlowModel.py | 15 ----- .../utils/modelgenerator/RegenerateModels.py | 4 +- ...generate_flow_model.py => generate_mad.py} | 59 +++++++++++-------- .../utils/modelgenerator/GenerateFlowModel.py | 15 ----- 9 files changed, 54 insertions(+), 87 deletions(-) delete mode 100644 cpp/ql/src/utils/modelgenerator/GenerateFlowModel.py create mode 100644 csharp/ql/src/change-notes/2025-05-02-mad-generator-renamed.md delete mode 100755 csharp/ql/src/utils/modelgenerator/GenerateFlowModel.py create mode 100644 java/ql/src/change-notes/2025-05-02-mad-generator-renamed.md delete mode 100755 java/ql/src/utils/modelgenerator/GenerateFlowModel.py rename misc/scripts/models-as-data/{generate_flow_model.py => generate_mad.py} (86%) delete mode 100644 rust/ql/src/utils/modelgenerator/GenerateFlowModel.py diff --git a/.github/workflows/mad_modelDiff.yml b/.github/workflows/mad_modelDiff.yml index 3d98e74f0fbb..b0e4a20f2b84 100644 --- a/.github/workflows/mad_modelDiff.yml +++ b/.github/workflows/mad_modelDiff.yml @@ -68,7 +68,7 @@ jobs: DATABASE=$2 cd codeql-$QL_VARIANT SHORTNAME=`basename $DATABASE` - python java/ql/src/utils/modelgenerator/GenerateFlowModel.py --with-summaries --with-sinks $DATABASE $SHORTNAME/$QL_VARIANT + python misc/scripts/models-as-data/generate_mad.py --language java --with-summaries --with-sinks $DATABASE $SHORTNAME/$QL_VARIANT mkdir -p $MODELS/$SHORTNAME mv java/ql/lib/ext/generated/$SHORTNAME/$QL_VARIANT $MODELS/$SHORTNAME cd .. diff --git a/cpp/ql/src/utils/modelgenerator/GenerateFlowModel.py b/cpp/ql/src/utils/modelgenerator/GenerateFlowModel.py deleted file mode 100644 index 38bbaad118bd..000000000000 --- a/cpp/ql/src/utils/modelgenerator/GenerateFlowModel.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/python3 - -import sys -import os.path -import subprocess - -# Add Model as Data script directory to sys.path. -gitroot = subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).decode("utf-8").strip() -madpath = os.path.join(gitroot, "misc/scripts/models-as-data/") -sys.path.append(madpath) - -import generate_flow_model as model - -language = "cpp" -model.Generator.make(language).run() diff --git a/csharp/ql/src/change-notes/2025-05-02-mad-generator-renamed.md b/csharp/ql/src/change-notes/2025-05-02-mad-generator-renamed.md new file mode 100644 index 000000000000..824b37180a18 --- /dev/null +++ b/csharp/ql/src/change-notes/2025-05-02-mad-generator-renamed.md @@ -0,0 +1,8 @@ +--- +category: minorAnalysis +--- +* Changes to the MaD model generation infrastructure: + * The `csharp/ql/src/utils/modelgenerator/GenerateFlowModel.py` script has + been removed. The `/misc/scripts/models-as-data/generate_mad.py` script now + supports being called directly and should be used instead. The script + requires a `--language` argument but otherwise functions identically. diff --git a/csharp/ql/src/utils/modelgenerator/GenerateFlowModel.py b/csharp/ql/src/utils/modelgenerator/GenerateFlowModel.py deleted file mode 100755 index ebc7ea1be789..000000000000 --- a/csharp/ql/src/utils/modelgenerator/GenerateFlowModel.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/python3 - -import sys -import os.path -import subprocess - -# Add Model as Data script directory to sys.path. -gitroot = subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).decode("utf-8").strip() -madpath = os.path.join(gitroot, "misc/scripts/models-as-data/") -sys.path.append(madpath) - -import generate_flow_model as model - -language = "csharp" -model.Generator.make(language).run() \ No newline at end of file diff --git a/java/ql/src/change-notes/2025-05-02-mad-generator-renamed.md b/java/ql/src/change-notes/2025-05-02-mad-generator-renamed.md new file mode 100644 index 000000000000..0a2d9e797fc5 --- /dev/null +++ b/java/ql/src/change-notes/2025-05-02-mad-generator-renamed.md @@ -0,0 +1,8 @@ +--- +category: minorAnalysis +--- +* Changes to the MaD model generation infrastructure: + * The `java/ql/src/utils/modelgenerator/GenerateFlowModel.py` script has + been removed. The `/misc/scripts/models-as-data/generate_mad.py` script now + supports being called directly and should be used instead. The script + requires a `--language` argument but otherwise functions identically. diff --git a/java/ql/src/utils/modelgenerator/GenerateFlowModel.py b/java/ql/src/utils/modelgenerator/GenerateFlowModel.py deleted file mode 100755 index 44b40a4d34a4..000000000000 --- a/java/ql/src/utils/modelgenerator/GenerateFlowModel.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/python3 - -import sys -import os.path -import subprocess - -# Add Model as Data script directory to sys.path. -gitroot = subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).decode("utf-8").strip() -madpath = os.path.join(gitroot, "misc/scripts/models-as-data/") -sys.path.append(madpath) - -import generate_flow_model as model - -language = "java" -model.Generator.make(language).run() \ No newline at end of file diff --git a/java/ql/src/utils/modelgenerator/RegenerateModels.py b/java/ql/src/utils/modelgenerator/RegenerateModels.py index 1f7df71776b1..0c38f41c0694 100755 --- a/java/ql/src/utils/modelgenerator/RegenerateModels.py +++ b/java/ql/src/utils/modelgenerator/RegenerateModels.py @@ -35,8 +35,8 @@ def regenerateModel(lgtmSlug, extractedDb): sys.exit(1) modelFile = lgtmSlugToModelFile[lgtmSlug] codeQlRoot = findGitRoot() - subprocess.check_call([codeQlRoot + "/java/ql/src/utils/modelgenerator/GenerateFlowModel.py", - "--with-summaries", "--with-sinks", "--with-neutrals", + subprocess.check_call([codeQlRoot + "/misc/scripts/models-as-data/generate_mad.py", + "--language", "java", "--with-summaries", "--with-sinks", "--with-neutrals", extractedDb, modelFile]) print("Regenerated " + modelFile) shutil.rmtree(tmpDir) diff --git a/misc/scripts/models-as-data/generate_flow_model.py b/misc/scripts/models-as-data/generate_mad.py similarity index 86% rename from misc/scripts/models-as-data/generate_flow_model.py rename to misc/scripts/models-as-data/generate_mad.py index 1d108015fa0b..60674ed54eda 100755 --- a/misc/scripts/models-as-data/generate_flow_model.py +++ b/misc/scripts/models-as-data/generate_mad.py @@ -1,10 +1,8 @@ #!/usr/bin/python3 import helpers -import json import os import os.path -import shlex import subprocess import sys import tempfile @@ -27,24 +25,13 @@ def parseData(data): return rows -class Generator: - def __init__ (self, language): - self.language = language - self.generateSinks = False - self.generateSources = False - self.generateSummaries = False - self.generateNeutrals = False - self.generateTypeBasedSummaries = False - self.dryRun = False - self.dirname = "modelgenerator" - - def printHelp(self): - print(f"""Usage: -python3 GenerateFlowModel.py [DIR] [--with-sinks] [--with-sources] [--with-summaries] [--with-neutrals] [--with-typebased-summaries] [--dry-run] +def printHelp(): + print(f"""Usage: +python3 generate_mad.py [DIR] --language LANGUAGE [--with-sinks] [--with-sources] [--with-summaries] [--with-neutrals] [--with-typebased-summaries] [--dry-run] This generates summary, source, sink and neutral models for the code in the database. -The files will be placed in `{self.language}/ql/lib/ext/generated/DIR` +The files will be placed in `LANGUAGE/ql/lib/ext/generated/DIR` Which models are generated is controlled by the flags: --with-sinks @@ -57,14 +44,25 @@ def printHelp(self): --dry-run: Only run the queries, but don't write to file. Example invocations: -$ python3 GenerateFlowModel.py /tmp/dbs/my_library_db -$ python3 GenerateFlowModel.py /tmp/dbs/my_library_db --with-sinks -$ python3 GenerateFlowModel.py /tmp/dbs/my_library_db --with-sinks my_directory +$ python3 generate_mad.py /tmp/dbs/my_library_db +$ python3 generate_mad.py /tmp/dbs/my_library_db --with-sinks +$ python3 generate_mad.py /tmp/dbs/my_library_db --with-sinks my_directory Requirements: `codeql` should appear on your path. """) +class Generator: + def __init__(self, language): + self.language = language + self.generateSinks = False + self.generateSources = False + self.generateSummaries = False + self.generateNeutrals = False + self.generateTypeBasedSummaries = False + self.dryRun = False + self.dirname = "modelgenerator" + def setenvironment(self, database, folder): self.codeQlRoot = subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).decode("utf-8").strip() @@ -76,12 +74,22 @@ def setenvironment(self, database, folder): @staticmethod - def make(language): - generator = Generator(language) + def make(): + '''Create a generator instance based on command line arguments.''' if any(s == "--help" for s in sys.argv): - generator.printHelp() + printHelp() + sys.exit(0) + + if "--language" in sys.argv: + language = sys.argv[sys.argv.index("--language") + 1] + sys.argv.remove("--language") + sys.argv.remove(language) + else: + print("Error: Language not specified. Use --language .") sys.exit(0) + generator = Generator(language=language) + if "--with-sinks" in sys.argv: sys.argv.remove("--with-sinks") generator.generateSinks = True @@ -115,7 +123,7 @@ def make(language): n = len(sys.argv) if n < 2: - generator.printHelp() + printHelp() sys.exit(1) elif n == 2: generator.setenvironment(sys.argv[1], "") @@ -204,3 +212,6 @@ def run(self): if self.generateTypeBasedSummaries: self.save(typeBasedContent, ".typebased.model.yml") + +if __name__ == '__main__': + Generator.make().run() \ No newline at end of file diff --git a/rust/ql/src/utils/modelgenerator/GenerateFlowModel.py b/rust/ql/src/utils/modelgenerator/GenerateFlowModel.py deleted file mode 100644 index 008b82501ff9..000000000000 --- a/rust/ql/src/utils/modelgenerator/GenerateFlowModel.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/python3 - -import sys -import os.path -import subprocess - -# Add Model as Data script directory to sys.path. -gitroot = subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).decode("utf-8").strip() -madpath = os.path.join(gitroot, "misc/scripts/models-as-data/") -sys.path.append(madpath) - -import generate_flow_model as model - -language = "rust" -model.Generator.make(language).run() From 5c9218fe5a392ceacebdb4a71733e51dd99ce2a1 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 2 May 2025 13:03:29 +0200 Subject: [PATCH 227/336] JS: Add comment about 'path' heuristic --- .../lib/semmle/javascript/internal/paths/PathConcatenation.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll index 448c7e55e016..ad5552ce78c3 100644 --- a/javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll @@ -25,6 +25,7 @@ private class TemplateConcatenation extends PathConcatenation, TemplateLiteral { private class JoinCallConcatenation extends PathConcatenation, CallExpr { JoinCallConcatenation() { + // Heuristic recognition of path.join and path.resolve since we can't rely on SourceNode at this stage. this.getReceiver().(VarAccess).getName() = "path" and this.getCalleeName() = ["join", "resolve"] } From 1f308ee47ab015800f64500c8edae6b6a22f9114 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 2 May 2025 13:05:37 +0200 Subject: [PATCH 228/336] JS: Explain use of monotonicAggregates --- .../ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll index 05b8a6207171..63ffd9554773 100644 --- a/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll @@ -65,6 +65,7 @@ module ResolveExpr { or exists(PathConcatenation join | node = TValueNode(join) and + // Note: 'monotonicAggregates' above lets us use recursion in the last clause of this aggregate result = strictconcat(int n, EarlyStageNode child, string sep | child = TValueNode(join.getOperand(n)) and sep = join.getSeparator() From 871e93d9fe2309d757bc6d19484fb491c9b31b64 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Fri, 2 May 2025 13:39:46 +0200 Subject: [PATCH 229/336] Update javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll Co-authored-by: Asger F --- javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll index ae0ba17941c2..fc0e366df4b8 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll @@ -163,10 +163,7 @@ module ShellJS { if name = "cmd" then result = this.getArgument(_) and - not ( - result = this.getLastArgument() and - exists(this.getOptionsArg()) - ) + not result = this.getOptionsArg() else // For exec/asyncExec: only first argument is command result = this.getArgument(0) From 97d2ed8b3ba6c6a75f36abb2a4fd8cd3e33f6a5b Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Wed, 30 Apr 2025 12:16:04 +0200 Subject: [PATCH 230/336] Swift: Support `UnsafeCastExpr` --- swift/extractor/infra/SwiftTagTraits.h | 2 +- swift/ql/.generated.list | 14 ++++++---- swift/ql/.gitattributes | 4 +++ swift/ql/lib/codeql/swift/elements.qll | 1 + .../swift/elements/expr/UnsafeCastExpr.qll | 12 +++++++++ .../internal/UnsafeCastExprConstructor.qll | 14 ++++++++++ .../expr/internal/UnsafeCastExprImpl.qll | 19 ++++++++++++++ .../codeql/swift/generated/ParentChild.qll | 19 ++++++++++++++ swift/ql/lib/codeql/swift/generated/Raw.qll | 8 ++++++ swift/ql/lib/codeql/swift/generated/Synth.qll | 22 +++++++++++++++- .../swift/generated/SynthConstructors.qll | 1 + .../swift/generated/expr/UnsafeCastExpr.qll | 26 +++++++++++++++++++ swift/ql/lib/swift.dbscheme | 5 ++++ .../ImplicitConversionExpr.expected | 2 ++ .../ImplicitConversionExpr_getType.expected | 2 ++ .../implicit_conversions.swift | 11 ++++++++ swift/schema.py | 6 +++++ 17 files changed, 161 insertions(+), 7 deletions(-) create mode 100644 swift/ql/lib/codeql/swift/elements/expr/UnsafeCastExpr.qll create mode 100644 swift/ql/lib/codeql/swift/elements/expr/internal/UnsafeCastExprConstructor.qll create mode 100644 swift/ql/lib/codeql/swift/elements/expr/internal/UnsafeCastExprImpl.qll create mode 100644 swift/ql/lib/codeql/swift/generated/expr/UnsafeCastExpr.qll diff --git a/swift/extractor/infra/SwiftTagTraits.h b/swift/extractor/infra/SwiftTagTraits.h index b95cec8d7d97..3bc1c511fa1a 100644 --- a/swift/extractor/infra/SwiftTagTraits.h +++ b/swift/extractor/infra/SwiftTagTraits.h @@ -177,7 +177,7 @@ MAP(swift::Expr, ExprTag) MAP(swift::ABISafeConversionExpr, AbiSafeConversionExprTag) // different acronym convention MAP(swift::ActorIsolationErasureExpr, ActorIsolationErasureExprTag) MAP(swift::UnreachableExpr, UnreachableExprTag) - MAP(swift::UnsafeCastExpr, void) // TODO swift 6.1 + MAP(swift::UnsafeCastExpr, UnsafeCastExprTag) MAP(swift::ExplicitCastExpr, ExplicitCastExprTag) MAP(swift::CheckedCastExpr, CheckedCastExprTag) MAP(swift::ForcedCheckedCastExpr, ForcedCheckedCastExprTag) diff --git a/swift/ql/.generated.list b/swift/ql/.generated.list index 04ed47ffe922..11c2d5d450d2 100644 --- a/swift/ql/.generated.list +++ b/swift/ql/.generated.list @@ -240,6 +240,7 @@ lib/codeql/swift/elements/expr/UnresolvedMemberExpr.qll 14bc154493999d866a3265d6 lib/codeql/swift/elements/expr/UnresolvedPatternExpr.qll f27ef68f5bbb2d957513efdd43fb9c77987d4f7850b050d40faf5e0ab23cf9cd d9bad310caf43eb82ca294fcb43f1aaa4046ddc8ff9d6c46f65c9a6f798d30af lib/codeql/swift/elements/expr/UnresolvedSpecializeExpr.qll 9e1b27d90419e757480d0ae369bec1f159de3c28ddf760cdf24dd30b0ec6fcf9 1aeab5e10b1c3f081c5c3ca5bd807bfc38726a7b21b7201e0a9f997572935c73 lib/codeql/swift/elements/expr/UnresolvedTypeConversionExpr.qll e259a187d70ea6b6007ebdd3659aa7e1947b2dc606642ccda27309ff74ffc3db c6a85856f82e74ed5597e381a5e4c27927eb4f01c7b588b1f4277dfb0e977521 +lib/codeql/swift/elements/expr/UnsafeCastExpr.qll 09c18a43f66432340b3212cb1933e096faf3825fa0a9abb30f7be11f170b6f97 93f35d500d67b71ed52d508ca9f7236c671f5b68a0ce6a0ee6a1a03d2b5db290 lib/codeql/swift/elements/expr/VarargExpansionExpr.qll c7d7574caaac88fd73e69e82a84ca924e078eece0fd85a476b4a831e23b425f9 27213c88f864b7f8fd73edf8951e04a5ae7a57140a387df7c03dc1544ced723b lib/codeql/swift/elements/expr/internal/AbiSafeConversionExprConstructor.qll de9d2daf68b754e783374d017116606c8cd0710dbf8989d3606939e977dc672c 63c5ddb9da56da2c9637d7a0a6d9d069f745b4c095b07c9494a0b3a7e11be95b lib/codeql/swift/elements/expr/internal/AbiSafeConversionExprImpl.qll 6b2c51a5a5dd17044c6f5510048a9a2187aac9d35a70541faa9400406e35bc1e 448c23eec2ef44bd90e6c1636e3e881ca3447198eb68b8261412f42c4995b766 @@ -425,6 +426,8 @@ lib/codeql/swift/elements/expr/internal/UnresolvedSpecializeExprConstructor.qll lib/codeql/swift/elements/expr/internal/UnresolvedSpecializeExprImpl.qll b1dc437410aa4a509ffc92cc0f63509e7bf698a52d79fc44a06230f185f22a97 a994738135b4118fadeb1a00c976772f777e7eeb4ecc0ab55e00676e0e1d507d lib/codeql/swift/elements/expr/internal/UnresolvedTypeConversionExprConstructor.qll 2d5a737ac25f4657d7fbc3be8ae927a44c01262e56fe49c161e73a7c015072b2 db3f463afb834181d618e8cc3773f0b174f17a0b29674cc8b1c3f5845c1317f9 lib/codeql/swift/elements/expr/internal/UnresolvedTypeConversionExprImpl.qll 3511bf1bea3e3cee95c0793e40000493537076d76f235bfe91866e1e0caf97ab b97de4c795e873acee89d9b87d8c58b14e05f0c09e3a0385a479638adcf32966 +lib/codeql/swift/elements/expr/internal/UnsafeCastExprConstructor.qll f8771eb8f677003fc62a2f78dcdffc46ee5510001428dde58a7e9d82746b6f97 f20eb160de27d9413a3b5d7ace406fe5f6912ad5720db85d8a12c48c71e42b35 +lib/codeql/swift/elements/expr/internal/UnsafeCastExprImpl.qll 787104ce97d702c0c3efa81a0f8416584f35c454d3b2ffe7bd0917861589612b 50496a0f3f3a9e3d5a2e6cbcd5eb16b634cf3fd5e0878bdf017678243dbfd8a0 lib/codeql/swift/elements/expr/internal/VarargExpansionExprConstructor.qll 917701083da11fce895c53d5f3e0a52b8e3142e9aacdf1d8536a4216ef377b16 b72ca103ced9cbb45f2ef9387387b8aaf3134e358ae5a03fa3ea242896954c81 lib/codeql/swift/elements/internal/AvailabilityInfoConstructor.qll 89c731f266122a3434b88dfd573d68c50b5c4fa5e13c2443c54f78e682190d1e 86beb6f684e08b6f557b7d67bc164113e9f5270c09bbe95fbd81c558d77f7f84 lib/codeql/swift/elements/internal/AvailabilitySpecImpl.qll 9ac9285e731938747c574c3f270aaead323656162bd34a6630c1babfaaf25a6a 900b2e638639f427506b2d0eb2806b6ee119ea63ea4ce44758e0c36f2ce915ac @@ -704,7 +707,7 @@ lib/codeql/swift/elements/type/internal/UnresolvedTypeImpl.qll ee1499dd568753898 lib/codeql/swift/elements/type/internal/VariadicSequenceTypeConstructor.qll fc74a5a2a2effa28ef24509b20ee4373d97cf6e8c71840121bb031c6adedf584 c9b2effc1d01c13c5e6a74a111122fa79a2f6554dda3cb016d68ba397e566ec4 lib/codeql/swift/elements/type/internal/WeakStorageTypeConstructor.qll 5fdce3716aba6318522174a2c455a63480970222ae81c732fb19c6dd3ae2d271 60ea79d6943e129deba0deccb566cf9d73f78398b0f7f0212674d91287d6b2ae lib/codeql/swift/elements/type/internal/WeakStorageTypeImpl.qll 74f79b458f3204ec2519bd654de21bc4fb6b76816bd8ca01990fe897563a1383 34e1810f74cecda5b580ed050438ae1d914b97a36b8f4e2de1c25254c0cac633 -lib/codeql/swift/elements.qll 9648ab501b413dc327513d9ed1d6e620a9eab6096e1130dc7e78cd6a2b6b549b 9648ab501b413dc327513d9ed1d6e620a9eab6096e1130dc7e78cd6a2b6b549b +lib/codeql/swift/elements.qll 24dc5e00db9aa90fbabc9d2b20b7e3ed9e1cdbc826dbda89f332a83b19054f53 24dc5e00db9aa90fbabc9d2b20b7e3ed9e1cdbc826dbda89f332a83b19054f53 lib/codeql/swift/generated/AstNode.qll 6fb80e9b230a1e3ae8193af40744f253d5cc81dc4239156924e5ab606c491efc e5c28418e9a38bde08f323a3986a199620189fc4a8a4dc8f670610a5d3d65b99 lib/codeql/swift/generated/AvailabilityInfo.qll e3a5274c43e72ff124b6988fd8be0c83a41b89337e11104150dd0ca7f51d8a11 889563791ca8d9758dbbccf64a0731c4bdbf721cad32bc6cd723f1072b6aa1de lib/codeql/swift/generated/AvailabilitySpec.qll bc64d5c690c4d18800f0a48cc76a6a9ee4f832041343666da2d8df2aae04ed7e d03bf874293ac0ab09c025f75c0f392473d47bebe3223143adcc13882a366119 @@ -721,12 +724,12 @@ lib/codeql/swift/generated/Locatable.qll 1d37fa20de71c0b9986bfd7a7c0cb82ab7bf3fd lib/codeql/swift/generated/Location.qll 5e20316c3e480ddfe632b7e88e016c19f10a67df1f6ae9c8f128755a6907d6f5 5a0af2d070bcb2ed53d6d0282bf9c60dc64c2dce89c21fdd485e9c7893c1c8fa lib/codeql/swift/generated/MacroRole.qll facf907e75490d69cd401c491215e4719324d751f40ea46c86ccf24cf3663c1f 969d8d4b44e3f1a9c193a152a4d83a303e56d2dbb871fc920c47a33f699cf018 lib/codeql/swift/generated/OtherAvailabilitySpec.qll d9feaa2a71acff3184ca389045b0a49d09156210df0e034923d715b432ad594b 046737621a8bcf69bf805afb0cff476bd15259f12f0d77fce3206dd01b31518f -lib/codeql/swift/generated/ParentChild.qll 7c9537f74a4c5a02622ce28c3de4b0ce02a7027d2e9aea9a860ece6a1e2ec340 49c1993b2a96df66903bffde78d63d8f4c68b2d604c419b20d88b63406366156 +lib/codeql/swift/generated/ParentChild.qll df9d71a00c137e89dd6a0caab75fea672fdf769ca60975d455aea85f2cb0e911 2a3495960938e3512cc10031b4c70b102c5ef8478528216fa27545b5ad37b9d7 lib/codeql/swift/generated/PlatformVersionAvailabilitySpec.qll dc17b49a90a18a8f7607adf2433bc8f0c194fa3e803aa3822f809d4d4fbd6793 be48ea9f8ae17354c8508aaed24337a9e57ce01f288fece3dcecd99776cabcec lib/codeql/swift/generated/PureSynthConstructors.qll bc31a6c4d142fa3fbdcae69d5ba6f1cec00eb9ad92b46c8d7b91ebfa7ef6c1f4 bc31a6c4d142fa3fbdcae69d5ba6f1cec00eb9ad92b46c8d7b91ebfa7ef6c1f4 -lib/codeql/swift/generated/Raw.qll 6012194c54f8992401dffc0916b5790cdf581f18ac7b884379362dc807a52706 f9538fdfb326b715fdbc47e9e8b310df684d5a34519f751a65b3a4a75e430ce9 -lib/codeql/swift/generated/Synth.qll a14dddab40979df82d30b2d73407fe0058a803ed6e1a882cd9a6ae5ffd240526 0879d2476a42123b46eee216d4ea03523e0c04fe0b68d9a68e0046253edb1bc9 -lib/codeql/swift/generated/SynthConstructors.qll f64121911e082aa15478eb8779025cee96e97503724c02aff31741e65a894a4b f64121911e082aa15478eb8779025cee96e97503724c02aff31741e65a894a4b +lib/codeql/swift/generated/Raw.qll 105d8abf7a4e7ffa9a421e17ca8eccf348a7fcfcc77b3a92e7e49750f0020284 271868257e2f48b743fc473ef3817611c3b112542a04f6e993fc4dfe34055b07 +lib/codeql/swift/generated/Synth.qll b1ef500787c05001ff7ddd6bdb3a5812ddc0ffa815906ae2e1c3f3a2416034ea 70f264bff132ece154200e81144f52377a7c65bd200c6aefd17d283bb29b9868 +lib/codeql/swift/generated/SynthConstructors.qll 2b242b849125bae5a0d19f19265882151a19120d43cc5b51398a5d5b520facaa 2b242b849125bae5a0d19f19265882151a19120d43cc5b51398a5d5b520facaa lib/codeql/swift/generated/UnknownFile.qll 247ddf2ebb49ce5ed4bf7bf91a969ddff37de6c78d43d8affccaf7eb586e06f2 452b29f0465ef45e978ef8b647b75e5a2a1e53f2a568fc003bc8f52f73b3fa4d lib/codeql/swift/generated/UnknownLocation.qll d871000b4f53ffca4f67ea23ca5626e5dcce125d62a4d4b9969e08cc974af6fc b05971d7774e60790362fb810fb7086314f40a2de747b8cb1bc823ec6494a4dd lib/codeql/swift/generated/UnspecifiedElement.qll d9ad4ba1ffff90cc465e8ba0dea8c4e8ba67dce5529b53b63ab6dc8e13c85e67 025218e1fee8ee382b63ad38009dfec73dc604d2ba80b9ad956c7c96eeed7022 @@ -906,6 +909,7 @@ lib/codeql/swift/generated/expr/UnresolvedMemberExpr.qll 64a64c105b9b8b7bc0e1619 lib/codeql/swift/generated/expr/UnresolvedPatternExpr.qll f197e1f19aa3b7641df8e9a7fcfe9f474282aadcb31172db8d76d2eb2449f7e1 5490ad6989b86f4f62657553e67d468bcbf60c1091bdac7fe0948bf6a22731fb lib/codeql/swift/generated/expr/UnresolvedSpecializeExpr.qll 5b6d9a88439442624051af347514b0a9fd5e932a440979778cf4072f71317770 a8f10642376f9ffa7f7cc73ca81e1a1f5905778a2752f20360f8a84f333dbfdd lib/codeql/swift/generated/expr/UnresolvedTypeConversionExpr.qll f30db08dbb5fce2bf6149238f608c62b51079c3694ed80d15ddcbecb2af75346 71b60e93c67f7b66468400ce9cc8714c9ead1bacaa7ce27e9df94542b41318f9 +lib/codeql/swift/generated/expr/UnsafeCastExpr.qll ec430464e1b6253dfcf0d17c08a01efae318b3f0c8beb7c977209504ccc2cc4f 48d5a80c96dfa71e091be2ce13ab7123997a37f8bcbaa6bde070493286f6b7f0 lib/codeql/swift/generated/expr/VarargExpansionExpr.qll 3f382a545ef79ef5cd7eadf397f01524769d5fa0ee6410f1d92ff6b9985a99ff ffe8d0caec0226a13599de646f9e0c5f0e1af3c2b7ed480b327f2d51850e9e32 lib/codeql/swift/generated/pattern/AnyPattern.qll af808c11b81a388f7d35bd98b6abf0fef45a1e1ec850cad16abb754c97c4da82 5c6cb800d4f026792a49fb84a3404f0797e599425bc54f474e3df6a948c18cfe lib/codeql/swift/generated/pattern/BindingPattern.qll ec7a78c6f2c2e56494d87c8865da2028cc65875edc516fdbdbde8f2fc80a28e7 df9988a745548d8920a78c0aca6692b24e6dad19251420208d050ee4eb39eee3 diff --git a/swift/ql/.gitattributes b/swift/ql/.gitattributes index 32c1865ff305..22fb1d0111bd 100644 --- a/swift/ql/.gitattributes +++ b/swift/ql/.gitattributes @@ -242,6 +242,7 @@ /lib/codeql/swift/elements/expr/UnresolvedPatternExpr.qll linguist-generated /lib/codeql/swift/elements/expr/UnresolvedSpecializeExpr.qll linguist-generated /lib/codeql/swift/elements/expr/UnresolvedTypeConversionExpr.qll linguist-generated +/lib/codeql/swift/elements/expr/UnsafeCastExpr.qll linguist-generated /lib/codeql/swift/elements/expr/VarargExpansionExpr.qll linguist-generated /lib/codeql/swift/elements/expr/internal/AbiSafeConversionExprConstructor.qll linguist-generated /lib/codeql/swift/elements/expr/internal/AbiSafeConversionExprImpl.qll linguist-generated @@ -427,6 +428,8 @@ /lib/codeql/swift/elements/expr/internal/UnresolvedSpecializeExprImpl.qll linguist-generated /lib/codeql/swift/elements/expr/internal/UnresolvedTypeConversionExprConstructor.qll linguist-generated /lib/codeql/swift/elements/expr/internal/UnresolvedTypeConversionExprImpl.qll linguist-generated +/lib/codeql/swift/elements/expr/internal/UnsafeCastExprConstructor.qll linguist-generated +/lib/codeql/swift/elements/expr/internal/UnsafeCastExprImpl.qll linguist-generated /lib/codeql/swift/elements/expr/internal/VarargExpansionExprConstructor.qll linguist-generated /lib/codeql/swift/elements/internal/AvailabilityInfoConstructor.qll linguist-generated /lib/codeql/swift/elements/internal/AvailabilitySpecImpl.qll linguist-generated @@ -908,6 +911,7 @@ /lib/codeql/swift/generated/expr/UnresolvedPatternExpr.qll linguist-generated /lib/codeql/swift/generated/expr/UnresolvedSpecializeExpr.qll linguist-generated /lib/codeql/swift/generated/expr/UnresolvedTypeConversionExpr.qll linguist-generated +/lib/codeql/swift/generated/expr/UnsafeCastExpr.qll linguist-generated /lib/codeql/swift/generated/expr/VarargExpansionExpr.qll linguist-generated /lib/codeql/swift/generated/pattern/AnyPattern.qll linguist-generated /lib/codeql/swift/generated/pattern/BindingPattern.qll linguist-generated diff --git a/swift/ql/lib/codeql/swift/elements.qll b/swift/ql/lib/codeql/swift/elements.qll index 53d630d9f197..a8d352e0ead3 100644 --- a/swift/ql/lib/codeql/swift/elements.qll +++ b/swift/ql/lib/codeql/swift/elements.qll @@ -195,6 +195,7 @@ import codeql.swift.elements.expr.UnresolvedMemberExpr import codeql.swift.elements.expr.UnresolvedPatternExpr import codeql.swift.elements.expr.UnresolvedSpecializeExpr import codeql.swift.elements.expr.UnresolvedTypeConversionExpr +import codeql.swift.elements.expr.UnsafeCastExpr import codeql.swift.elements.expr.VarargExpansionExpr import codeql.swift.elements.pattern.AnyPattern import codeql.swift.elements.pattern.BindingPattern diff --git a/swift/ql/lib/codeql/swift/elements/expr/UnsafeCastExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/UnsafeCastExpr.qll new file mode 100644 index 000000000000..162e5d085896 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/expr/UnsafeCastExpr.qll @@ -0,0 +1,12 @@ +// generated by codegen/codegen.py, do not edit +/** + * This module provides the public class `UnsafeCastExpr`. + */ + +private import internal.UnsafeCastExprImpl +import codeql.swift.elements.expr.ImplicitConversionExpr + +/** + * A conversion that performs an unsafe bitcast. + */ +final class UnsafeCastExpr = Impl::UnsafeCastExpr; diff --git a/swift/ql/lib/codeql/swift/elements/expr/internal/UnsafeCastExprConstructor.qll b/swift/ql/lib/codeql/swift/elements/expr/internal/UnsafeCastExprConstructor.qll new file mode 100644 index 000000000000..892f3400380f --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/expr/internal/UnsafeCastExprConstructor.qll @@ -0,0 +1,14 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +/** + * This module defines the hook used internally to tweak the characteristic predicate of + * `UnsafeCastExpr` synthesized instances. + * INTERNAL: Do not use. + */ + +private import codeql.swift.generated.Raw + +/** + * The characteristic predicate of `UnsafeCastExpr` synthesized instances. + * INTERNAL: Do not use. + */ +predicate constructUnsafeCastExpr(Raw::UnsafeCastExpr id) { any() } diff --git a/swift/ql/lib/codeql/swift/elements/expr/internal/UnsafeCastExprImpl.qll b/swift/ql/lib/codeql/swift/elements/expr/internal/UnsafeCastExprImpl.qll new file mode 100644 index 000000000000..89a010f57529 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/expr/internal/UnsafeCastExprImpl.qll @@ -0,0 +1,19 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +/** + * This module provides a hand-modifiable wrapper around the generated class `UnsafeCastExpr`. + * + * INTERNAL: Do not use. + */ + +private import codeql.swift.generated.expr.UnsafeCastExpr + +/** + * INTERNAL: This module contains the customizable definition of `UnsafeCastExpr` and should not + * be referenced directly. + */ +module Impl { + /** + * A conversion that performs an unsafe bitcast. + */ + class UnsafeCastExpr extends Generated::UnsafeCastExpr { } +} diff --git a/swift/ql/lib/codeql/swift/generated/ParentChild.qll b/swift/ql/lib/codeql/swift/generated/ParentChild.qll index 2925620f24f0..30801ade8d57 100644 --- a/swift/ql/lib/codeql/swift/generated/ParentChild.qll +++ b/swift/ql/lib/codeql/swift/generated/ParentChild.qll @@ -3169,6 +3169,23 @@ private module Impl { ) } + private Element getImmediateChildOfUnsafeCastExpr( + UnsafeCastExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + private Element getImmediateChildOfBooleanLiteralExpr( BooleanLiteralExpr e, int index, string partialPredicateCall ) { @@ -5493,6 +5510,8 @@ private module Impl { or result = getImmediateChildOfUnresolvedTypeConversionExpr(e, index, partialAccessor) or + result = getImmediateChildOfUnsafeCastExpr(e, index, partialAccessor) + or result = getImmediateChildOfBooleanLiteralExpr(e, index, partialAccessor) or result = getImmediateChildOfConditionalCheckedCastExpr(e, index, partialAccessor) diff --git a/swift/ql/lib/codeql/swift/generated/Raw.qll b/swift/ql/lib/codeql/swift/generated/Raw.qll index c59c831a1ee2..0ebc95d2084c 100644 --- a/swift/ql/lib/codeql/swift/generated/Raw.qll +++ b/swift/ql/lib/codeql/swift/generated/Raw.qll @@ -2488,6 +2488,14 @@ module Raw { override string toString() { result = "UnresolvedTypeConversionExpr" } } + /** + * INTERNAL: Do not use. + * A conversion that performs an unsafe bitcast. + */ + class UnsafeCastExpr extends @unsafe_cast_expr, ImplicitConversionExpr { + override string toString() { result = "UnsafeCastExpr" } + } + /** * INTERNAL: Do not use. */ diff --git a/swift/ql/lib/codeql/swift/generated/Synth.qll b/swift/ql/lib/codeql/swift/generated/Synth.qll index ce6eca080afb..83a94b965053 100644 --- a/swift/ql/lib/codeql/swift/generated/Synth.qll +++ b/swift/ql/lib/codeql/swift/generated/Synth.qll @@ -716,6 +716,10 @@ module Synth { TUnresolvedTypeConversionExpr(Raw::UnresolvedTypeConversionExpr id) { constructUnresolvedTypeConversionExpr(id) } or + /** + * INTERNAL: Do not use. + */ + TUnsafeCastExpr(Raw::UnsafeCastExpr id) { constructUnsafeCastExpr(id) } or /** * INTERNAL: Do not use. */ @@ -1288,7 +1292,7 @@ module Synth { TLinearToDifferentiableFunctionExpr or TLoadExpr or TMetatypeConversionExpr or TPointerToPointerExpr or TProtocolMetatypeToObjectExpr or TStringToPointerExpr or TUnderlyingToOpaqueExpr or TUnevaluatedInstanceExpr or TUnreachableExpr or - TUnresolvedTypeConversionExpr; + TUnresolvedTypeConversionExpr or TUnsafeCastExpr; /** * INTERNAL: Do not use. @@ -2561,6 +2565,12 @@ module Synth { result = TUnresolvedTypeConversionExpr(e) } + /** + * INTERNAL: Do not use. + * Converts a raw element to a synthesized `TUnsafeCastExpr`, if possible. + */ + TUnsafeCastExpr convertUnsafeCastExprFromRaw(Raw::Element e) { result = TUnsafeCastExpr(e) } + /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TVarargExpansionExpr`, if possible. @@ -3765,6 +3775,8 @@ module Synth { result = convertUnreachableExprFromRaw(e) or result = convertUnresolvedTypeConversionExprFromRaw(e) + or + result = convertUnsafeCastExprFromRaw(e) } /** @@ -5269,6 +5281,12 @@ module Synth { e = TUnresolvedTypeConversionExpr(result) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TUnsafeCastExpr` to a raw DB element, if possible. + */ + Raw::Element convertUnsafeCastExprToRaw(TUnsafeCastExpr e) { e = TUnsafeCastExpr(result) } + /** * INTERNAL: Do not use. * Converts a synthesized `TVarargExpansionExpr` to a raw DB element, if possible. @@ -6473,6 +6491,8 @@ module Synth { result = convertUnreachableExprToRaw(e) or result = convertUnresolvedTypeConversionExprToRaw(e) + or + result = convertUnsafeCastExprToRaw(e) } /** diff --git a/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll b/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll index 1da3dcbc0134..474420586cac 100644 --- a/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll +++ b/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll @@ -162,6 +162,7 @@ import codeql.swift.elements.expr.internal.UnresolvedMemberExprConstructor import codeql.swift.elements.expr.internal.UnresolvedPatternExprConstructor import codeql.swift.elements.expr.internal.UnresolvedSpecializeExprConstructor import codeql.swift.elements.expr.internal.UnresolvedTypeConversionExprConstructor +import codeql.swift.elements.expr.internal.UnsafeCastExprConstructor import codeql.swift.elements.expr.internal.VarargExpansionExprConstructor import codeql.swift.elements.pattern.internal.AnyPatternConstructor import codeql.swift.elements.pattern.internal.BindingPatternConstructor diff --git a/swift/ql/lib/codeql/swift/generated/expr/UnsafeCastExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/UnsafeCastExpr.qll new file mode 100644 index 000000000000..d21ba383f141 --- /dev/null +++ b/swift/ql/lib/codeql/swift/generated/expr/UnsafeCastExpr.qll @@ -0,0 +1,26 @@ +// generated by codegen/codegen.py, do not edit +/** + * This module provides the generated definition of `UnsafeCastExpr`. + * INTERNAL: Do not import directly. + */ + +private import codeql.swift.generated.Synth +private import codeql.swift.generated.Raw +import codeql.swift.elements.expr.internal.ImplicitConversionExprImpl::Impl as ImplicitConversionExprImpl + +/** + * INTERNAL: This module contains the fully generated definition of `UnsafeCastExpr` and should not + * be referenced directly. + */ +module Generated { + /** + * A conversion that performs an unsafe bitcast. + * INTERNAL: Do not reference the `Generated::UnsafeCastExpr` class directly. + * Use the subclass `UnsafeCastExpr`, where the following predicates are available. + */ + class UnsafeCastExpr extends Synth::TUnsafeCastExpr, + ImplicitConversionExprImpl::ImplicitConversionExpr + { + override string getAPrimaryQlClass() { result = "UnsafeCastExpr" } + } +} diff --git a/swift/ql/lib/swift.dbscheme b/swift/ql/lib/swift.dbscheme index 4dd3d5ca8a89..3d88fb615e8a 100644 --- a/swift/ql/lib/swift.dbscheme +++ b/swift/ql/lib/swift.dbscheme @@ -1067,6 +1067,7 @@ if_exprs( //dir=expr | @unevaluated_instance_expr | @unreachable_expr | @unresolved_type_conversion_expr +| @unsafe_cast_expr ; #keyset[id] @@ -1656,6 +1657,10 @@ unresolved_type_conversion_exprs( //dir=expr unique int id: @unresolved_type_conversion_expr ); +unsafe_cast_exprs( //dir=expr + unique int id: @unsafe_cast_expr +); + boolean_literal_exprs( //dir=expr unique int id: @boolean_literal_expr, boolean value: boolean ref diff --git a/swift/ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/ImplicitConversionExpr.expected b/swift/ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/ImplicitConversionExpr.expected index 9baeaf412413..ac122e39f9f7 100644 --- a/swift/ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/ImplicitConversionExpr.expected +++ b/swift/ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/ImplicitConversionExpr.expected @@ -3,3 +3,5 @@ | implicit_conversions.swift:5:25:5:25 | (any Equatable) ... | ErasureExpr | hasType: | yes | getSubExpr: | implicit_conversions.swift:5:25:5:25 | 42 | | implicit_conversions.swift:12:3:12:5 | (@lvalue (() -> Void)?) ... | AbiSafeConversionExpr | hasType: | yes | getSubExpr: | implicit_conversions.swift:12:3:12:5 | .b | | implicit_conversions.swift:12:9:12:10 | ((() -> Void)?) ... | InjectIntoOptionalExpr | hasType: | yes | getSubExpr: | implicit_conversions.swift:12:9:12:10 | { ... } | +| implicit_conversions.swift:24:3:24:5 | (Array) ... | UnsafeCastExpr | hasType: | yes | getSubExpr: | implicit_conversions.swift:24:3:24:5 | ([any Sendable]) ... | +| implicit_conversions.swift:24:3:24:5 | ([any Sendable]) ... | LoadExpr | hasType: | yes | getSubExpr: | implicit_conversions.swift:24:3:24:5 | .a | diff --git a/swift/ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/ImplicitConversionExpr_getType.expected b/swift/ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/ImplicitConversionExpr_getType.expected index e57454212dfb..8254ef3cc8a7 100644 --- a/swift/ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/ImplicitConversionExpr_getType.expected +++ b/swift/ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/ImplicitConversionExpr_getType.expected @@ -3,3 +3,5 @@ | implicit_conversions.swift:5:25:5:25 | (any Equatable) ... | any Equatable | | implicit_conversions.swift:12:3:12:5 | (@lvalue (() -> Void)?) ... | @lvalue (() -> Void)? | | implicit_conversions.swift:12:9:12:10 | ((() -> Void)?) ... | (() -> Void)? | +| implicit_conversions.swift:24:3:24:5 | (Array) ... | Array | +| implicit_conversions.swift:24:3:24:5 | ([any Sendable]) ... | [any Sendable] | diff --git a/swift/ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/implicit_conversions.swift b/swift/ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/implicit_conversions.swift index 6bd2b4b3fb1e..24f0a6cff19c 100644 --- a/swift/ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/implicit_conversions.swift +++ b/swift/ql/test/extractor-tests/generated/expr/ImplicitConversionExpr/implicit_conversions.swift @@ -12,3 +12,14 @@ func g(_ a: A) { a.b = {} } +class B { + @preconcurrency var a: [any Sendable] = [] +} + +extension Array where Element == Any { + func h() {} +} + +func i(b: B) { + b.a.h() +} diff --git a/swift/schema.py b/swift/schema.py index 78750ae2baac..4e11bc7a33d1 100644 --- a/swift/schema.py +++ b/swift/schema.py @@ -1463,3 +1463,9 @@ class UnreachableExpr(ImplicitConversionExpr): """ A conversion from the uninhabited type to any other type. It's never evaluated. """ + + +class UnsafeCastExpr(ImplicitConversionExpr): + """ + A conversion that performs an unsafe bitcast. + """ From c74fca929a277c4097e6daf9575ef59294b319d4 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 1 May 2025 15:49:56 +0200 Subject: [PATCH 231/336] Swift: Support `TypeValueExpr` and `IntegerType` --- swift/extractor/infra/SwiftTagTraits.h | 4 +- swift/extractor/mangler/SwiftMangler.cpp | 3 ++ .../extractor/translators/ExprTranslator.cpp | 6 +++ swift/extractor/translators/ExprTranslator.h | 1 + .../extractor/translators/TypeTranslator.cpp | 6 +++ swift/extractor/translators/TypeTranslator.h | 1 + swift/ql/.generated.list | 21 ++++++-- swift/ql/.gitattributes | 11 ++++ swift/ql/lib/codeql/swift/elements.qll | 2 + .../swift/elements/expr/TypeValueExpr.qll | 10 ++++ .../internal/TypeValueExprConstructor.qll | 14 +++++ .../expr/internal/TypeValueExprImpl.qll | 16 ++++++ .../swift/elements/type/IntegerType.qll | 9 ++++ .../type/internal/IntegerTypeConstructor.qll | 14 +++++ .../type/internal/IntegerTypeImpl.qll | 16 ++++++ .../codeql/swift/generated/ParentChild.qll | 37 +++++++++++++ swift/ql/lib/codeql/swift/generated/Raw.qll | 24 +++++++++ swift/ql/lib/codeql/swift/generated/Synth.qll | 52 ++++++++++++++++--- .../swift/generated/SynthConstructors.qll | 2 + .../swift/generated/expr/TypeValueExpr.qll | 34 ++++++++++++ .../swift/generated/type/IntegerType.qll | 30 +++++++++++ swift/ql/lib/swift.dbscheme | 12 +++++ swift/ql/test/TestUtils.qll | 2 + .../expr/TypeValueExpr/TypeValueExpr.expected | 2 + .../expr/TypeValueExpr/TypeValueExpr.ql | 11 ++++ .../TypeValueExpr_getType.expected | 2 + .../TypeValueExpr/TypeValueExpr_getType.ql | 7 +++ .../expr/TypeValueExpr/type_value_exprs.swift | 8 +++ .../type/IntegerType/IntegerType.expected | 2 + .../generated/type/IntegerType/IntegerType.ql | 12 +++++ .../type/IntegerType/integer_type.swift | 9 ++++ swift/schema.py | 6 +++ 32 files changed, 373 insertions(+), 13 deletions(-) create mode 100644 swift/ql/lib/codeql/swift/elements/expr/TypeValueExpr.qll create mode 100644 swift/ql/lib/codeql/swift/elements/expr/internal/TypeValueExprConstructor.qll create mode 100644 swift/ql/lib/codeql/swift/elements/expr/internal/TypeValueExprImpl.qll create mode 100644 swift/ql/lib/codeql/swift/elements/type/IntegerType.qll create mode 100644 swift/ql/lib/codeql/swift/elements/type/internal/IntegerTypeConstructor.qll create mode 100644 swift/ql/lib/codeql/swift/elements/type/internal/IntegerTypeImpl.qll create mode 100644 swift/ql/lib/codeql/swift/generated/expr/TypeValueExpr.qll create mode 100644 swift/ql/lib/codeql/swift/generated/type/IntegerType.qll create mode 100644 swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr.expected create mode 100644 swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr.ql create mode 100644 swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr_getType.expected create mode 100644 swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr_getType.ql create mode 100644 swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/type_value_exprs.swift create mode 100644 swift/ql/test/extractor-tests/generated/type/IntegerType/IntegerType.expected create mode 100644 swift/ql/test/extractor-tests/generated/type/IntegerType/IntegerType.ql create mode 100644 swift/ql/test/extractor-tests/generated/type/IntegerType/integer_type.swift diff --git a/swift/extractor/infra/SwiftTagTraits.h b/swift/extractor/infra/SwiftTagTraits.h index 3bc1c511fa1a..285f48cc940e 100644 --- a/swift/extractor/infra/SwiftTagTraits.h +++ b/swift/extractor/infra/SwiftTagTraits.h @@ -205,7 +205,7 @@ MAP(swift::Expr, ExprTag) MAP(swift::SingleValueStmtExpr, SingleValueStmtExprTag) MAP(swift::ExtractFunctionIsolationExpr, ExtractFunctionIsolationExprTag) MAP(swift::CurrentContextIsolationExpr, CurrentContextIsolationExprTag) - MAP(swift::TypeValueExpr, void) // TODO swift 6.1 + MAP(swift::TypeValueExpr, TypeValueExprTag) MAP(swift::Decl, DeclTag) MAP(swift::ValueDecl, ValueDeclTag) MAP(swift::TypeDecl, TypeDeclTag) @@ -339,7 +339,7 @@ MAP(swift::TypeBase, TypeTag) MAP(swift::PackElementType, PackElementTypeTag) MAP(swift::TypeVariableType, void) // created during type checking and only used for constraint checking MAP(swift::ErrorUnionType, void) // created during type checking and only used for constraint checking - MAP(swift::IntegerType, void) // TODO swift 6.1 + MAP(swift::IntegerType, IntegerTypeTag) MAP(swift::SugarType, SugarTypeTag) MAP(swift::TypeAliasType, TypeAliasTypeTag) MAP(swift::SyntaxSugarType, SyntaxSugarTypeTag) diff --git a/swift/extractor/mangler/SwiftMangler.cpp b/swift/extractor/mangler/SwiftMangler.cpp index 6357a58beca6..7e1f1f0bfe87 100644 --- a/swift/extractor/mangler/SwiftMangler.cpp +++ b/swift/extractor/mangler/SwiftMangler.cpp @@ -285,6 +285,9 @@ SwiftMangledName SwiftMangler::visitGenericTypeParamType(const swift::GenericTyp if (type->isParameterPack()) { ret << "each_"; } + if (type->isValue()) { + ret << "val_"; + } if (auto decl = type->getDecl()) { ret << fetch(decl); } else { diff --git a/swift/extractor/translators/ExprTranslator.cpp b/swift/extractor/translators/ExprTranslator.cpp index 0f7d5d0c9155..30cca659a8c9 100644 --- a/swift/extractor/translators/ExprTranslator.cpp +++ b/swift/extractor/translators/ExprTranslator.cpp @@ -689,4 +689,10 @@ codeql::CurrentContextIsolationExpr ExprTranslator::translateCurrentContextIsola return entry; } +codeql::TypeValueExpr ExprTranslator::translateTypeValueExpr(const swift::TypeValueExpr& expr) { + auto entry = createExprEntry(expr); + entry.type_repr = dispatcher.fetchLabel(expr.getParamTypeRepr()); + return entry; +} + } // namespace codeql diff --git a/swift/extractor/translators/ExprTranslator.h b/swift/extractor/translators/ExprTranslator.h index ff3db137b3bc..525f1fda6c17 100644 --- a/swift/extractor/translators/ExprTranslator.h +++ b/swift/extractor/translators/ExprTranslator.h @@ -129,6 +129,7 @@ class ExprTranslator : public AstTranslatorBase { const swift::ExtractFunctionIsolationExpr& expr); codeql::CurrentContextIsolationExpr translateCurrentContextIsolationExpr( const swift::CurrentContextIsolationExpr& expr); + codeql::TypeValueExpr translateTypeValueExpr(const swift::TypeValueExpr& expr); private: void fillClosureExpr(const swift::AbstractClosureExpr& expr, codeql::ClosureExpr& entry); diff --git a/swift/extractor/translators/TypeTranslator.cpp b/swift/extractor/translators/TypeTranslator.cpp index 3404bb7d95ab..cd4714498276 100644 --- a/swift/extractor/translators/TypeTranslator.cpp +++ b/swift/extractor/translators/TypeTranslator.cpp @@ -297,4 +297,10 @@ codeql::PackExpansionType TypeTranslator::translatePackExpansionType( return entry; } +codeql::IntegerType TypeTranslator::translateIntegerType(const swift::IntegerType& type) { + auto entry = createTypeEntry(type); + entry.value = type.getDigitsText(); + return entry; +} + } // namespace codeql diff --git a/swift/extractor/translators/TypeTranslator.h b/swift/extractor/translators/TypeTranslator.h index 02eb24632f46..404f7214beae 100644 --- a/swift/extractor/translators/TypeTranslator.h +++ b/swift/extractor/translators/TypeTranslator.h @@ -82,6 +82,7 @@ class TypeTranslator : public TypeTranslatorBase { codeql::PackType translatePackType(const swift::PackType& type); codeql::PackElementType translatePackElementType(const swift::PackElementType& type); codeql::PackExpansionType translatePackExpansionType(const swift::PackExpansionType& type); + codeql::IntegerType translateIntegerType(const swift::IntegerType& type); private: void fillType(const swift::TypeBase& type, codeql::Type& entry); diff --git a/swift/ql/.generated.list b/swift/ql/.generated.list index 11c2d5d450d2..fcec2a9fbe21 100644 --- a/swift/ql/.generated.list +++ b/swift/ql/.generated.list @@ -230,6 +230,7 @@ lib/codeql/swift/elements/expr/TryExpr.qll 524d52e85f893ed735463f2ac8ebff1c37ce1 lib/codeql/swift/elements/expr/TupleElementExpr.qll 32bd4e870958e0fe8a06626618379d5d081e6b6d1d2da35954ff8c6e1cac5891 1036d0a774f16dfdfe223181bf86a7fb3e5a65495f13a584af4419c769b5ca93 lib/codeql/swift/elements/expr/TupleExpr.qll 11efe0f2737b561a392bbd684c7c1cc2e29bed3273597e64933608d8a4e3a736 f02537adb1271e4b84c44eb001ccb7b7c70f13fc13908354fd4361ed3720d06b lib/codeql/swift/elements/expr/TypeExpr.qll c3f7272b77aadd8a4a0e5c7e3876bba6bba45343415c8ce96de26e1e898d11c0 91cd440b768e4d9aa60a165ddb62ecdcad85eb4a676ab0d60ca8777e753bffc7 +lib/codeql/swift/elements/expr/TypeValueExpr.qll 8a8d061b091594b758fb7d0b708337b639b7d76b1f63bd860e3e4466f268ba3f 7722a6668b3e382e32ef0cc5bbb8c79c7de9a618c8822957e5f48b45770d0af3 lib/codeql/swift/elements/expr/UnderlyingToOpaqueExpr.qll f319daff97d13a5cacf2efcd1f2b77e58ec9b9a30413ddb30cc0333197cbef9f 9c6a97a66a452a6167b26f48b0f31a42e2c528fcd30e76c9f4dd146f6609b5d3 lib/codeql/swift/elements/expr/UnevaluatedInstanceExpr.qll 7eca15f753e81d99a275ca1d29986d5209d8ffea4034746945227fedc1b74c38 714c9a7a09f525187f53a4c9599a141a32ec6071c405c2a425dc2cfb6f2457e6 lib/codeql/swift/elements/expr/UnreachableExpr.qll 930822d66d99422603725161f55fec7b861ef33aa8fe57afbdbea2a68a764fcb e8005f5ac66a97e614f3792e8053b0fb6d6bb1f99bc1d0f7d0d0b41e703efe9c @@ -408,6 +409,8 @@ lib/codeql/swift/elements/expr/internal/TryExprConstructor.qll 594b8505862487212 lib/codeql/swift/elements/expr/internal/TupleElementExprConstructor.qll e9d0f5b77adcdfad3e4f3aad8674dd86b86d81bc4aca534a6a30172364d5ce81 ccac3b0ae4ebc028a9cb58f6f71a07330fb235180109c1f72ddbb10992af976c lib/codeql/swift/elements/expr/internal/TupleExprConstructor.qll 14c402dd2c9dc350270d406c8d71b4a46080fd321a60b49e7eb73f46dc371d07 165527b92b2302e098002cf888254a8f4af208cd3aa8f441c740b59ac50ddc15 lib/codeql/swift/elements/expr/internal/TypeExprConstructor.qll 8e23bd56763001fa82b9642c36c54785fd0a544c8eb9175fd12fd5b8053a039c 3388ed62f69e5d45a5d6753400cae3532b1da915186b9bf5d0d29c9cb0e71e8c +lib/codeql/swift/elements/expr/internal/TypeValueExprConstructor.qll dd3b0f5a05a758fce4cdbd4665077b18afd1a76079b5c99ca8be18b1dc2fcced b8b3a648919cbc98b6ad8d973a4e5745cc03026dafeeba2614e6995630e18d6a +lib/codeql/swift/elements/expr/internal/TypeValueExprImpl.qll fe6ba98379db2f664ea34457f8b808881eaf2639b659f1accf52ca2642e5ec02 86df96c256cc924e108241fffe4bd152c61171bc012b13f10d6bbd308df12446 lib/codeql/swift/elements/expr/internal/UnderlyingToOpaqueExprConstructor.qll 8b763964bdda1af1971fa737980780d7a1b57afe37cafc6edc594bedd767725f 0485956adfc2e9a31aeeef1c8ed1d53781967445e3ea0f76c843fd48e33f021a lib/codeql/swift/elements/expr/internal/UnderlyingToOpaqueExprImpl.qll cf2637b44a96fce2d8e618469692305181490a28f3b2698b6f9db2d58e7c474d 9b062defb7c19e217bea6e5bd65ccf28e1ff25fb1e784405eb92406806a3349c lib/codeql/swift/elements/expr/internal/UnevaluatedInstanceExprConstructor.qll 4560f4737cb47512b8348fd2a37599227df4a05bfad84873f6666d121a524e0a b49bfdfa550330bab087c5a6b7a3885fd22360e557adf984ce7a35534d882510 @@ -557,6 +560,7 @@ lib/codeql/swift/elements/type/FunctionType.qll 1a64eb24e8baa74ef2a8e4451f97442a lib/codeql/swift/elements/type/GenericFunctionType.qll 8df1db2785c4e6b88f9af13eb7ba473f91459f57d19c4d706847ac6e3a02d64a 186efec4c23c372f9d9f7038d4b5a36f9c3184564e5b6899d2e467864977dd89 lib/codeql/swift/elements/type/GenericTypeParamType.qll d75c865295501f7efe27399ce93b30f6a4a217ed207e7227a5d9870cf536ad5f 1a764963700b872c8ea7afd586abbc0dadda68366555baefa6737d87b701a73f lib/codeql/swift/elements/type/InOutType.qll 3ff69b884d2604f66290b188892f1d9d4321bf77a20bcda2ce5cb69e565b0cfb 3cd2b06bc606d84b1d73b8fcd2aea4d49aed0c8b98902b44dd6f19d298db7f9d +lib/codeql/swift/elements/type/IntegerType.qll 118acea4a849506aeddd5df92e9f134bf611f8c08cb44e18dc56259df1c98e5f 6801c067c63e310f28fed70a7c1ed87d08be6b7070a7ec677517a93b6eab0c3f lib/codeql/swift/elements/type/LValueType.qll e1e53b1467f7b4ff77a812ae9cd8ce151cfc21443a4da14319aee390c081775c 42f5a39fb2c1e5dad3fef6db56430c6063cb04b1ba9c1f2b9c68356aef6aef1c lib/codeql/swift/elements/type/LocalArchetypeType.qll 449ff6d721a70a0f8f7a8e1604471513af1523bad6efcc49820154e4d42a426b 1121b807f15d442b708bb614b684ad3d0581c787bae4a16999b8dd7da5103ab6 lib/codeql/swift/elements/type/MetatypeType.qll 9a0b15d97d67edfd68221903c65d1537ffd9270630b751528e3c97c504ab9472 aeb2263f4d49f71f529b467f4505605f42be5f48ae52c44b9041eea69fb4e3eb @@ -655,6 +659,8 @@ lib/codeql/swift/elements/type/internal/GenericTypeParamTypeConstructor.qll b126 lib/codeql/swift/elements/type/internal/GenericTypeParamTypeImpl.qll efca259897a044fc967341a9fdb39497fc5e9bcb0b4ba33fa76cb926b98b3eb7 aaa621c691813a2f70f4071e3592d7760cef319904209770442ca0d0583f65a1 lib/codeql/swift/elements/type/internal/InOutTypeConstructor.qll 40550fd07551bc7c1692e08f1cb0692defca613c3c6403719efc5998eb1f1bfd 775f16224a455e336da239a179f84581b345803b9576aca119aeb3eef583d739 lib/codeql/swift/elements/type/internal/InOutTypeImpl.qll 28fc2931a424f551107b0ee49663d5d5307146c725353c5e484f0dd289f93dc0 ff12e91e30ee53bb8acdcf9e31261b6b1b0ae966babb4eacacb344c22aa1cb6e +lib/codeql/swift/elements/type/internal/IntegerTypeConstructor.qll 39e33225066f7162309f888723f81893703ee0daba68f192e3277f922060160b 08903e4d0bc8889761d016d6b6c4b7f1bd061a08c97e2a151b59cc0400ea2199 +lib/codeql/swift/elements/type/internal/IntegerTypeImpl.qll ba8e6e972dcea4dbe937083c819c5fd9eb49ba4b6176e040ce65d36a95fe31bd 88064b52d9430b67edd62ed37426f5adc8f6d80722370340d147b0a4ca90f70c lib/codeql/swift/elements/type/internal/LValueTypeConstructor.qll e3ab6ebb6191a2553bd4a483067acf7131862bc7235af2da74c35e2250300da8 cfa65d0f22416408ee1e5e5af440166fe5f5b39ae9bf1b9ae92bd9f9f2954b76 lib/codeql/swift/elements/type/internal/LocalArchetypeTypeImpl.qll 8170baafe8e2845a3f7f11894244c6b1cfbeadf7d3c86de676fe17deec68494c e72508db440afe58c2da26529c362f1f7eeb6f360424f62c7f6cd841c4a6f3bd lib/codeql/swift/elements/type/internal/MetatypeTypeConstructor.qll 7011a1307524477b7e3b43e2efb2ebcbdc7fec258455c95d3c2525cb8857bf3c b56938e2d9cd814b2fa3de569f091f42e716b399e73e024e405eb211f65a944c @@ -707,7 +713,7 @@ lib/codeql/swift/elements/type/internal/UnresolvedTypeImpl.qll ee1499dd568753898 lib/codeql/swift/elements/type/internal/VariadicSequenceTypeConstructor.qll fc74a5a2a2effa28ef24509b20ee4373d97cf6e8c71840121bb031c6adedf584 c9b2effc1d01c13c5e6a74a111122fa79a2f6554dda3cb016d68ba397e566ec4 lib/codeql/swift/elements/type/internal/WeakStorageTypeConstructor.qll 5fdce3716aba6318522174a2c455a63480970222ae81c732fb19c6dd3ae2d271 60ea79d6943e129deba0deccb566cf9d73f78398b0f7f0212674d91287d6b2ae lib/codeql/swift/elements/type/internal/WeakStorageTypeImpl.qll 74f79b458f3204ec2519bd654de21bc4fb6b76816bd8ca01990fe897563a1383 34e1810f74cecda5b580ed050438ae1d914b97a36b8f4e2de1c25254c0cac633 -lib/codeql/swift/elements.qll 24dc5e00db9aa90fbabc9d2b20b7e3ed9e1cdbc826dbda89f332a83b19054f53 24dc5e00db9aa90fbabc9d2b20b7e3ed9e1cdbc826dbda89f332a83b19054f53 +lib/codeql/swift/elements.qll 67832d269392e0c8226bd03918be9b3e4cf11213e54dd3acfe153dd8f8cd33c7 67832d269392e0c8226bd03918be9b3e4cf11213e54dd3acfe153dd8f8cd33c7 lib/codeql/swift/generated/AstNode.qll 6fb80e9b230a1e3ae8193af40744f253d5cc81dc4239156924e5ab606c491efc e5c28418e9a38bde08f323a3986a199620189fc4a8a4dc8f670610a5d3d65b99 lib/codeql/swift/generated/AvailabilityInfo.qll e3a5274c43e72ff124b6988fd8be0c83a41b89337e11104150dd0ca7f51d8a11 889563791ca8d9758dbbccf64a0731c4bdbf721cad32bc6cd723f1072b6aa1de lib/codeql/swift/generated/AvailabilitySpec.qll bc64d5c690c4d18800f0a48cc76a6a9ee4f832041343666da2d8df2aae04ed7e d03bf874293ac0ab09c025f75c0f392473d47bebe3223143adcc13882a366119 @@ -724,12 +730,12 @@ lib/codeql/swift/generated/Locatable.qll 1d37fa20de71c0b9986bfd7a7c0cb82ab7bf3fd lib/codeql/swift/generated/Location.qll 5e20316c3e480ddfe632b7e88e016c19f10a67df1f6ae9c8f128755a6907d6f5 5a0af2d070bcb2ed53d6d0282bf9c60dc64c2dce89c21fdd485e9c7893c1c8fa lib/codeql/swift/generated/MacroRole.qll facf907e75490d69cd401c491215e4719324d751f40ea46c86ccf24cf3663c1f 969d8d4b44e3f1a9c193a152a4d83a303e56d2dbb871fc920c47a33f699cf018 lib/codeql/swift/generated/OtherAvailabilitySpec.qll d9feaa2a71acff3184ca389045b0a49d09156210df0e034923d715b432ad594b 046737621a8bcf69bf805afb0cff476bd15259f12f0d77fce3206dd01b31518f -lib/codeql/swift/generated/ParentChild.qll df9d71a00c137e89dd6a0caab75fea672fdf769ca60975d455aea85f2cb0e911 2a3495960938e3512cc10031b4c70b102c5ef8478528216fa27545b5ad37b9d7 +lib/codeql/swift/generated/ParentChild.qll 3b7e2e04c92f395f446fbf2dcf62f97a1b066523a5feb90c1cede9a1e644d4e4 58b8a96626a061b11ea0783b0356467358ef80bc9148666f78d6b64a0457a899 lib/codeql/swift/generated/PlatformVersionAvailabilitySpec.qll dc17b49a90a18a8f7607adf2433bc8f0c194fa3e803aa3822f809d4d4fbd6793 be48ea9f8ae17354c8508aaed24337a9e57ce01f288fece3dcecd99776cabcec lib/codeql/swift/generated/PureSynthConstructors.qll bc31a6c4d142fa3fbdcae69d5ba6f1cec00eb9ad92b46c8d7b91ebfa7ef6c1f4 bc31a6c4d142fa3fbdcae69d5ba6f1cec00eb9ad92b46c8d7b91ebfa7ef6c1f4 -lib/codeql/swift/generated/Raw.qll 105d8abf7a4e7ffa9a421e17ca8eccf348a7fcfcc77b3a92e7e49750f0020284 271868257e2f48b743fc473ef3817611c3b112542a04f6e993fc4dfe34055b07 -lib/codeql/swift/generated/Synth.qll b1ef500787c05001ff7ddd6bdb3a5812ddc0ffa815906ae2e1c3f3a2416034ea 70f264bff132ece154200e81144f52377a7c65bd200c6aefd17d283bb29b9868 -lib/codeql/swift/generated/SynthConstructors.qll 2b242b849125bae5a0d19f19265882151a19120d43cc5b51398a5d5b520facaa 2b242b849125bae5a0d19f19265882151a19120d43cc5b51398a5d5b520facaa +lib/codeql/swift/generated/Raw.qll ca16e576312f595283994e8b02a32693826712c76c471f7969271dc09361d13e 3d86c741064a075810e1e92d2c3bdc2a77755b9142904dee95709117af3c29a1 +lib/codeql/swift/generated/Synth.qll a8462dd9e84e0059f6ca4d9c9f42ac75d0d3fd7b65702e1409c583a89665f18c 051e02492cba3ddda863cd80507a49884d73d57c834f00f6d3547e2143c48dbe +lib/codeql/swift/generated/SynthConstructors.qll 9dc761332663708d16ee6303930557858ea56049ce2dbac4b14f995e6c02977d 9dc761332663708d16ee6303930557858ea56049ce2dbac4b14f995e6c02977d lib/codeql/swift/generated/UnknownFile.qll 247ddf2ebb49ce5ed4bf7bf91a969ddff37de6c78d43d8affccaf7eb586e06f2 452b29f0465ef45e978ef8b647b75e5a2a1e53f2a568fc003bc8f52f73b3fa4d lib/codeql/swift/generated/UnknownLocation.qll d871000b4f53ffca4f67ea23ca5626e5dcce125d62a4d4b9969e08cc974af6fc b05971d7774e60790362fb810fb7086314f40a2de747b8cb1bc823ec6494a4dd lib/codeql/swift/generated/UnspecifiedElement.qll d9ad4ba1ffff90cc465e8ba0dea8c4e8ba67dce5529b53b63ab6dc8e13c85e67 025218e1fee8ee382b63ad38009dfec73dc604d2ba80b9ad956c7c96eeed7022 @@ -899,6 +905,7 @@ lib/codeql/swift/generated/expr/TryExpr.qll 92b670b206df8b75d703c35dec2594802334 lib/codeql/swift/generated/expr/TupleElementExpr.qll 1528226a5615b821fa40127b425a7ffe2004d58b7511ba4e7313449c37e3d552 dcb5bef0a132257c6ca67d2d459ee1e420e0fa36fd8da56aac07af7c27b95a6e lib/codeql/swift/generated/expr/TupleExpr.qll 860dde65c440ffa74648c663126194182c430c1520d5ce1a6766b81edf16dfd8 669091d441977fb730d3dcbfc6018e5fc013b6c2d27a0877c244431a6ffbb7a8 lib/codeql/swift/generated/expr/TypeExpr.qll 1f38f463b11b9f10878dab7266f05f455a0802e6d7464d81d4c05855d41adc64 b3c3f6b61b466be86a8cc0cea18d85b7a23b1f8dcf876ef2a050ef69778df32b +lib/codeql/swift/generated/expr/TypeValueExpr.qll 7c3ed4ddda248999ebe88c436a1967978efdbde7a4f0b73c1b74d350d59b4d26 e631045cc6943f59ba8732a77fa1ff23f2eddc767722be83160f31a9a65e26bd lib/codeql/swift/generated/expr/UnderlyingToOpaqueExpr.qll 3d68175d73056e6f5afea5040ad2f9a8447adf078c490bb06769008857ee2ca7 f0ec8f0bf7271289b8be32038e60c2b1053d6563354c8bced53a42fef6292152 lib/codeql/swift/generated/expr/UnevaluatedInstanceExpr.qll bac438970bc12eef2ace318b97d37ef58ab7a9c2c43c3f4515780f65cdc5de70 11810cdd753c744f3ee274fce889d272c3c94b6087c124cdd09e99188eb3f926 lib/codeql/swift/generated/expr/UnreachableExpr.qll ab17ea1f01eb1b22b1012b57582b170936244c98f42374e0e21b9d468db9249c 93a2a3685a9f8d4eab06cf700bc6465915e29b49249a14fe6aa68d1af96c86ca @@ -986,6 +993,7 @@ lib/codeql/swift/generated/type/FunctionType.qll 739192b77787905a66d9c9970dc077c lib/codeql/swift/generated/type/GenericFunctionType.qll 50743701a62cad6f2cbe8b331a45bd3b18f3154b860720355b831735fd2208b4 481b28aee3e473a74a66628acd2050cfee9807ebad8c8a0646783e3942b89297 lib/codeql/swift/generated/type/GenericTypeParamType.qll f266dffcd2f87f8411b796b97faa671a7bb5e6dd0aa67d3bfc9bbc06a47f1a3b 0e1625a7d2447faf75ec4c716ed1d5219b82ba8720450bc77d279e9854599758 lib/codeql/swift/generated/type/InOutType.qll 809a3bb1c5eec066416c2fce85df9116e7402a368c7e955abe6a01c7673cbdf4 7c614fa92e624890f3a83e7a7f3464f8a94f45b60beeb77f9295850567522ba7 +lib/codeql/swift/generated/type/IntegerType.qll f2040268ae94c41f27a659c09c55360b20000d40440cb9513409a95379b3b37f 4397d31da9bad9e5167d6dc6cb7f26071bb80e00538bd8f55e7fc53e45e8bd32 lib/codeql/swift/generated/type/LValueType.qll 4a6422f21bd21b841d841cad9f7c01ce7eeb9ba6b5d1fa004fa44dc008eaa432 8914e356e0475f0f3b81c681295fa7a833fae2e24c491d8d6e552ad897be4184 lib/codeql/swift/generated/type/LocalArchetypeType.qll de4f291bab61ccb699609f39682cbe29936da3c8be51e9a5620b0bce384bc852 152a74964a40daa7419de15d646ee8b62d137a8a5d7c5d0b002d81d1fdf12c47 lib/codeql/swift/generated/type/MetatypeType.qll bef10ef14aa44b8ef86e5dfe38061df202b9a8d3fb27d671c4b71b51dbe48d1d fd43f29906ef16b3488a74d33fe76ec34e4b8afe6fdfd88036ee1e8305036ca7 @@ -1232,6 +1240,8 @@ test/extractor-tests/generated/expr/TryExpr/MISSING_SOURCE.txt 35fb32ea5393152eb test/extractor-tests/generated/expr/TupleElementExpr/MISSING_SOURCE.txt 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d test/extractor-tests/generated/expr/TupleExpr/MISSING_SOURCE.txt 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d test/extractor-tests/generated/expr/TypeExpr/MISSING_SOURCE.txt 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d +test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr.ql 93ebaff4938dd18f3626533cbf23094c4d7eac7ce84325b743f78dd36d8831e5 c3bc6b6f7a18ca5a32084207fac2468f6306b81cd6a7af1ecf117b1a37147266 +test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr_getType.ql da07880497965cf7f7e28fb3c3a8e8223368685fdacb62d7e562757f01fd521c 9be644216f6adf12adf102ecfac5b3820c2fe7916a86586744ae71d1c11d9704 test/extractor-tests/generated/expr/VarargExpansionExpr/MISSING_SOURCE.txt 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d test/extractor-tests/generated/pattern/AnyPattern/MISSING_SOURCE.txt 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d test/extractor-tests/generated/pattern/BindingPattern/MISSING_SOURCE.txt 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d @@ -1295,6 +1305,7 @@ test/extractor-tests/generated/type/FunctionType/MISSING_SOURCE.txt 35fb32ea5393 test/extractor-tests/generated/type/GenericFunctionType/MISSING_SOURCE.txt 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d test/extractor-tests/generated/type/GenericTypeParamType/MISSING_SOURCE.txt 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d test/extractor-tests/generated/type/InOutType/InOutType.ql a3591003defc284ba9c1c8492ccea5f46ff1de2d86a2240da3a501598d236f8e 4915db95b101c199dcf194e8b974a3c7c94f8ac1d4d9dbf6144822beb4ec0b66 +test/extractor-tests/generated/type/IntegerType/IntegerType.ql 7c911b67a801d8a4f0fe695c66318f6a08278b632adacb58bb10578474a43d49 9590080054ad1280eecb97d2f5265de8c2d2eeca03af24654cac5e2818240e85 test/extractor-tests/generated/type/LValueType/MISSING_SOURCE.txt 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d test/extractor-tests/generated/type/MetatypeType/MISSING_SOURCE.txt 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d 35fb32ea5393152eb7a875b20b4e3e4b8c7a997a8959c32417140d57a16a052d test/extractor-tests/generated/type/ModuleType/ModuleType.ql a65f7a166068b3bc622864b4b7464a25e41cd8a02f2bdce214ae59475acb9893 89a165e1c0f5b1de549d6c73e893cbc520832d534f801ba5d9144ac2ae3a9b8a diff --git a/swift/ql/.gitattributes b/swift/ql/.gitattributes index 22fb1d0111bd..2d8114e910cb 100644 --- a/swift/ql/.gitattributes +++ b/swift/ql/.gitattributes @@ -232,6 +232,7 @@ /lib/codeql/swift/elements/expr/TupleElementExpr.qll linguist-generated /lib/codeql/swift/elements/expr/TupleExpr.qll linguist-generated /lib/codeql/swift/elements/expr/TypeExpr.qll linguist-generated +/lib/codeql/swift/elements/expr/TypeValueExpr.qll linguist-generated /lib/codeql/swift/elements/expr/UnderlyingToOpaqueExpr.qll linguist-generated /lib/codeql/swift/elements/expr/UnevaluatedInstanceExpr.qll linguist-generated /lib/codeql/swift/elements/expr/UnreachableExpr.qll linguist-generated @@ -410,6 +411,8 @@ /lib/codeql/swift/elements/expr/internal/TupleElementExprConstructor.qll linguist-generated /lib/codeql/swift/elements/expr/internal/TupleExprConstructor.qll linguist-generated /lib/codeql/swift/elements/expr/internal/TypeExprConstructor.qll linguist-generated +/lib/codeql/swift/elements/expr/internal/TypeValueExprConstructor.qll linguist-generated +/lib/codeql/swift/elements/expr/internal/TypeValueExprImpl.qll linguist-generated /lib/codeql/swift/elements/expr/internal/UnderlyingToOpaqueExprConstructor.qll linguist-generated /lib/codeql/swift/elements/expr/internal/UnderlyingToOpaqueExprImpl.qll linguist-generated /lib/codeql/swift/elements/expr/internal/UnevaluatedInstanceExprConstructor.qll linguist-generated @@ -559,6 +562,7 @@ /lib/codeql/swift/elements/type/GenericFunctionType.qll linguist-generated /lib/codeql/swift/elements/type/GenericTypeParamType.qll linguist-generated /lib/codeql/swift/elements/type/InOutType.qll linguist-generated +/lib/codeql/swift/elements/type/IntegerType.qll linguist-generated /lib/codeql/swift/elements/type/LValueType.qll linguist-generated /lib/codeql/swift/elements/type/LocalArchetypeType.qll linguist-generated /lib/codeql/swift/elements/type/MetatypeType.qll linguist-generated @@ -657,6 +661,8 @@ /lib/codeql/swift/elements/type/internal/GenericTypeParamTypeImpl.qll linguist-generated /lib/codeql/swift/elements/type/internal/InOutTypeConstructor.qll linguist-generated /lib/codeql/swift/elements/type/internal/InOutTypeImpl.qll linguist-generated +/lib/codeql/swift/elements/type/internal/IntegerTypeConstructor.qll linguist-generated +/lib/codeql/swift/elements/type/internal/IntegerTypeImpl.qll linguist-generated /lib/codeql/swift/elements/type/internal/LValueTypeConstructor.qll linguist-generated /lib/codeql/swift/elements/type/internal/LocalArchetypeTypeImpl.qll linguist-generated /lib/codeql/swift/elements/type/internal/MetatypeTypeConstructor.qll linguist-generated @@ -901,6 +907,7 @@ /lib/codeql/swift/generated/expr/TupleElementExpr.qll linguist-generated /lib/codeql/swift/generated/expr/TupleExpr.qll linguist-generated /lib/codeql/swift/generated/expr/TypeExpr.qll linguist-generated +/lib/codeql/swift/generated/expr/TypeValueExpr.qll linguist-generated /lib/codeql/swift/generated/expr/UnderlyingToOpaqueExpr.qll linguist-generated /lib/codeql/swift/generated/expr/UnevaluatedInstanceExpr.qll linguist-generated /lib/codeql/swift/generated/expr/UnreachableExpr.qll linguist-generated @@ -988,6 +995,7 @@ /lib/codeql/swift/generated/type/GenericFunctionType.qll linguist-generated /lib/codeql/swift/generated/type/GenericTypeParamType.qll linguist-generated /lib/codeql/swift/generated/type/InOutType.qll linguist-generated +/lib/codeql/swift/generated/type/IntegerType.qll linguist-generated /lib/codeql/swift/generated/type/LValueType.qll linguist-generated /lib/codeql/swift/generated/type/LocalArchetypeType.qll linguist-generated /lib/codeql/swift/generated/type/MetatypeType.qll linguist-generated @@ -1234,6 +1242,8 @@ /test/extractor-tests/generated/expr/TupleElementExpr/MISSING_SOURCE.txt linguist-generated /test/extractor-tests/generated/expr/TupleExpr/MISSING_SOURCE.txt linguist-generated /test/extractor-tests/generated/expr/TypeExpr/MISSING_SOURCE.txt linguist-generated +/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr.ql linguist-generated +/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr_getType.ql linguist-generated /test/extractor-tests/generated/expr/VarargExpansionExpr/MISSING_SOURCE.txt linguist-generated /test/extractor-tests/generated/pattern/AnyPattern/MISSING_SOURCE.txt linguist-generated /test/extractor-tests/generated/pattern/BindingPattern/MISSING_SOURCE.txt linguist-generated @@ -1297,6 +1307,7 @@ /test/extractor-tests/generated/type/GenericFunctionType/MISSING_SOURCE.txt linguist-generated /test/extractor-tests/generated/type/GenericTypeParamType/MISSING_SOURCE.txt linguist-generated /test/extractor-tests/generated/type/InOutType/InOutType.ql linguist-generated +/test/extractor-tests/generated/type/IntegerType/IntegerType.ql linguist-generated /test/extractor-tests/generated/type/LValueType/MISSING_SOURCE.txt linguist-generated /test/extractor-tests/generated/type/MetatypeType/MISSING_SOURCE.txt linguist-generated /test/extractor-tests/generated/type/ModuleType/ModuleType.ql linguist-generated diff --git a/swift/ql/lib/codeql/swift/elements.qll b/swift/ql/lib/codeql/swift/elements.qll index a8d352e0ead3..f840aa9df513 100644 --- a/swift/ql/lib/codeql/swift/elements.qll +++ b/swift/ql/lib/codeql/swift/elements.qll @@ -185,6 +185,7 @@ import codeql.swift.elements.expr.TryExpr import codeql.swift.elements.expr.TupleElementExpr import codeql.swift.elements.expr.TupleExpr import codeql.swift.elements.expr.TypeExpr +import codeql.swift.elements.expr.TypeValueExpr import codeql.swift.elements.expr.UnderlyingToOpaqueExpr import codeql.swift.elements.expr.UnevaluatedInstanceExpr import codeql.swift.elements.expr.UnreachableExpr @@ -272,6 +273,7 @@ import codeql.swift.elements.type.FunctionType import codeql.swift.elements.type.GenericFunctionType import codeql.swift.elements.type.GenericTypeParamType import codeql.swift.elements.type.InOutType +import codeql.swift.elements.type.IntegerType import codeql.swift.elements.type.LValueType import codeql.swift.elements.type.LocalArchetypeType import codeql.swift.elements.type.MetatypeType diff --git a/swift/ql/lib/codeql/swift/elements/expr/TypeValueExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/TypeValueExpr.qll new file mode 100644 index 000000000000..7f48b7a80b55 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/expr/TypeValueExpr.qll @@ -0,0 +1,10 @@ +// generated by codegen/codegen.py, do not edit +/** + * This module provides the public class `TypeValueExpr`. + */ + +private import internal.TypeValueExprImpl +import codeql.swift.elements.expr.Expr +import codeql.swift.elements.type.TypeRepr + +final class TypeValueExpr = Impl::TypeValueExpr; diff --git a/swift/ql/lib/codeql/swift/elements/expr/internal/TypeValueExprConstructor.qll b/swift/ql/lib/codeql/swift/elements/expr/internal/TypeValueExprConstructor.qll new file mode 100644 index 000000000000..de997a791b45 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/expr/internal/TypeValueExprConstructor.qll @@ -0,0 +1,14 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +/** + * This module defines the hook used internally to tweak the characteristic predicate of + * `TypeValueExpr` synthesized instances. + * INTERNAL: Do not use. + */ + +private import codeql.swift.generated.Raw + +/** + * The characteristic predicate of `TypeValueExpr` synthesized instances. + * INTERNAL: Do not use. + */ +predicate constructTypeValueExpr(Raw::TypeValueExpr id) { any() } diff --git a/swift/ql/lib/codeql/swift/elements/expr/internal/TypeValueExprImpl.qll b/swift/ql/lib/codeql/swift/elements/expr/internal/TypeValueExprImpl.qll new file mode 100644 index 000000000000..4fd16c6693fa --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/expr/internal/TypeValueExprImpl.qll @@ -0,0 +1,16 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +/** + * This module provides a hand-modifiable wrapper around the generated class `TypeValueExpr`. + * + * INTERNAL: Do not use. + */ + +private import codeql.swift.generated.expr.TypeValueExpr + +/** + * INTERNAL: This module contains the customizable definition of `TypeValueExpr` and should not + * be referenced directly. + */ +module Impl { + class TypeValueExpr extends Generated::TypeValueExpr { } +} diff --git a/swift/ql/lib/codeql/swift/elements/type/IntegerType.qll b/swift/ql/lib/codeql/swift/elements/type/IntegerType.qll new file mode 100644 index 000000000000..8d1df2b47699 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/type/IntegerType.qll @@ -0,0 +1,9 @@ +// generated by codegen/codegen.py, do not edit +/** + * This module provides the public class `IntegerType`. + */ + +private import internal.IntegerTypeImpl +import codeql.swift.elements.type.Type + +final class IntegerType = Impl::IntegerType; diff --git a/swift/ql/lib/codeql/swift/elements/type/internal/IntegerTypeConstructor.qll b/swift/ql/lib/codeql/swift/elements/type/internal/IntegerTypeConstructor.qll new file mode 100644 index 000000000000..b9190352b5da --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/type/internal/IntegerTypeConstructor.qll @@ -0,0 +1,14 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +/** + * This module defines the hook used internally to tweak the characteristic predicate of + * `IntegerType` synthesized instances. + * INTERNAL: Do not use. + */ + +private import codeql.swift.generated.Raw + +/** + * The characteristic predicate of `IntegerType` synthesized instances. + * INTERNAL: Do not use. + */ +predicate constructIntegerType(Raw::IntegerType id) { any() } diff --git a/swift/ql/lib/codeql/swift/elements/type/internal/IntegerTypeImpl.qll b/swift/ql/lib/codeql/swift/elements/type/internal/IntegerTypeImpl.qll new file mode 100644 index 000000000000..9eeb9798fc64 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/type/internal/IntegerTypeImpl.qll @@ -0,0 +1,16 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +/** + * This module provides a hand-modifiable wrapper around the generated class `IntegerType`. + * + * INTERNAL: Do not use. + */ + +private import codeql.swift.generated.type.IntegerType + +/** + * INTERNAL: This module contains the customizable definition of `IntegerType` and should not + * be referenced directly. + */ +module Impl { + class IntegerType extends Generated::IntegerType { } +} diff --git a/swift/ql/lib/codeql/swift/generated/ParentChild.qll b/swift/ql/lib/codeql/swift/generated/ParentChild.qll index 30801ade8d57..8ab3348f470b 100644 --- a/swift/ql/lib/codeql/swift/generated/ParentChild.qll +++ b/swift/ql/lib/codeql/swift/generated/ParentChild.qll @@ -2009,6 +2009,24 @@ private module Impl { ) } + private Element getImmediateChildOfTypeValueExpr( + TypeValueExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nTypeRepr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nTypeRepr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getTypeRepr() and partialPredicateCall = "TypeRepr()" + ) + ) + } + private Element getImmediateChildOfUnresolvedDeclRefExpr( UnresolvedDeclRefExpr e, int index, string partialPredicateCall ) { @@ -4277,6 +4295,21 @@ private module Impl { ) } + private Element getImmediateChildOfIntegerType( + IntegerType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + private Element getImmediateChildOfLValueType(LValueType e, int index, string partialPredicateCall) { exists(int b, int bType, int n | b = 0 and @@ -5382,6 +5415,8 @@ private module Impl { or result = getImmediateChildOfTypeExpr(e, index, partialAccessor) or + result = getImmediateChildOfTypeValueExpr(e, index, partialAccessor) + or result = getImmediateChildOfUnresolvedDeclRefExpr(e, index, partialAccessor) or result = getImmediateChildOfUnresolvedDotExpr(e, index, partialAccessor) @@ -5618,6 +5653,8 @@ private module Impl { or result = getImmediateChildOfInOutType(e, index, partialAccessor) or + result = getImmediateChildOfIntegerType(e, index, partialAccessor) + or result = getImmediateChildOfLValueType(e, index, partialAccessor) or result = getImmediateChildOfModuleType(e, index, partialAccessor) diff --git a/swift/ql/lib/codeql/swift/generated/Raw.qll b/swift/ql/lib/codeql/swift/generated/Raw.qll index 0ebc95d2084c..88ba766fc866 100644 --- a/swift/ql/lib/codeql/swift/generated/Raw.qll +++ b/swift/ql/lib/codeql/swift/generated/Raw.qll @@ -1853,6 +1853,18 @@ module Raw { TypeRepr getTypeRepr() { type_expr_type_reprs(this, result) } } + /** + * INTERNAL: Do not use. + */ + class TypeValueExpr extends @type_value_expr, Expr { + override string toString() { result = "TypeValueExpr" } + + /** + * Gets the type representation of this type value expression. + */ + TypeRepr getTypeRepr() { type_value_exprs(this, result) } + } + /** * INTERNAL: Do not use. */ @@ -3323,6 +3335,18 @@ module Raw { Type getObjectType() { in_out_types(this, result) } } + /** + * INTERNAL: Do not use. + */ + class IntegerType extends @integer_type, Type { + override string toString() { result = "IntegerType" } + + /** + * Gets the value of this integer type. + */ + string getValue() { integer_types(this, result) } + } + /** * INTERNAL: Do not use. */ diff --git a/swift/ql/lib/codeql/swift/generated/Synth.qll b/swift/ql/lib/codeql/swift/generated/Synth.qll index 83a94b965053..7eecd52e6266 100644 --- a/swift/ql/lib/codeql/swift/generated/Synth.qll +++ b/swift/ql/lib/codeql/swift/generated/Synth.qll @@ -668,6 +668,10 @@ module Synth { * INTERNAL: Do not use. */ TTypeExpr(Raw::TypeExpr id) { constructTypeExpr(id) } or + /** + * INTERNAL: Do not use. + */ + TTypeValueExpr(Raw::TypeValueExpr id) { constructTypeValueExpr(id) } or /** * INTERNAL: Do not use. */ @@ -994,6 +998,10 @@ module Synth { * INTERNAL: Do not use. */ TInOutType(Raw::InOutType id) { constructInOutType(id) } or + /** + * INTERNAL: Do not use. + */ + TIntegerType(Raw::IntegerType id) { constructIntegerType(id) } or /** * INTERNAL: Do not use. */ @@ -1266,9 +1274,9 @@ module Synth { TOptionalEvaluationExpr or TOtherInitializerRefExpr or TOverloadedDeclRefExpr or TPackElementExpr or TPackExpansionExpr or TPropertyWrapperValuePlaceholderExpr or TRebindSelfInInitializerExpr or TSequenceExpr or TSingleValueStmtExpr or TSuperRefExpr or - TTapExpr or TTupleElementExpr or TTupleExpr or TTypeExpr or TUnresolvedDeclRefExpr or - TUnresolvedDotExpr or TUnresolvedMemberExpr or TUnresolvedPatternExpr or - TUnresolvedSpecializeExpr or TVarargExpansionExpr; + TTapExpr or TTupleElementExpr or TTupleExpr or TTypeExpr or TTypeValueExpr or + TUnresolvedDeclRefExpr or TUnresolvedDotExpr or TUnresolvedMemberExpr or + TUnresolvedPatternExpr or TUnresolvedSpecializeExpr or TVarargExpansionExpr; /** * INTERNAL: Do not use. @@ -1426,9 +1434,9 @@ module Synth { class TType = TAnyFunctionType or TAnyGenericType or TAnyMetatypeType or TBuiltinType or TDependentMemberType or TDynamicSelfType or TErrorType or TExistentialType or TInOutType or - TLValueType or TModuleType or TPackElementType or TPackExpansionType or TPackType or - TParameterizedProtocolType or TProtocolCompositionType or TReferenceStorageType or - TSubstitutableType or TSugarType or TTupleType or TUnresolvedType; + TIntegerType or TLValueType or TModuleType or TPackElementType or TPackExpansionType or + TPackType or TParameterizedProtocolType or TProtocolCompositionType or + TReferenceStorageType or TSubstitutableType or TSugarType or TTupleType or TUnresolvedType; /** * INTERNAL: Do not use. @@ -2487,6 +2495,12 @@ module Synth { */ TTypeExpr convertTypeExprFromRaw(Raw::Element e) { result = TTypeExpr(e) } + /** + * INTERNAL: Do not use. + * Converts a raw element to a synthesized `TTypeValueExpr`, if possible. + */ + TTypeValueExpr convertTypeValueExprFromRaw(Raw::Element e) { result = TTypeValueExpr(e) } + /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TUnderlyingToOpaqueExpr`, if possible. @@ -3003,6 +3017,12 @@ module Synth { */ TInOutType convertInOutTypeFromRaw(Raw::Element e) { result = TInOutType(e) } + /** + * INTERNAL: Do not use. + * Converts a raw element to a synthesized `TIntegerType`, if possible. + */ + TIntegerType convertIntegerTypeFromRaw(Raw::Element e) { result = TIntegerType(e) } + /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TLValueType`, if possible. @@ -3674,6 +3694,8 @@ module Synth { or result = convertTypeExprFromRaw(e) or + result = convertTypeValueExprFromRaw(e) + or result = convertUnresolvedDeclRefExprFromRaw(e) or result = convertUnresolvedDotExprFromRaw(e) @@ -4116,6 +4138,8 @@ module Synth { or result = convertInOutTypeFromRaw(e) or + result = convertIntegerTypeFromRaw(e) + or result = convertLValueTypeFromRaw(e) or result = convertModuleTypeFromRaw(e) @@ -5203,6 +5227,12 @@ module Synth { */ Raw::Element convertTypeExprToRaw(TTypeExpr e) { e = TTypeExpr(result) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TTypeValueExpr` to a raw DB element, if possible. + */ + Raw::Element convertTypeValueExprToRaw(TTypeValueExpr e) { e = TTypeValueExpr(result) } + /** * INTERNAL: Do not use. * Converts a synthesized `TUnderlyingToOpaqueExpr` to a raw DB element, if possible. @@ -5719,6 +5749,12 @@ module Synth { */ Raw::Element convertInOutTypeToRaw(TInOutType e) { e = TInOutType(result) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TIntegerType` to a raw DB element, if possible. + */ + Raw::Element convertIntegerTypeToRaw(TIntegerType e) { e = TIntegerType(result) } + /** * INTERNAL: Do not use. * Converts a synthesized `TLValueType` to a raw DB element, if possible. @@ -6390,6 +6426,8 @@ module Synth { or result = convertTypeExprToRaw(e) or + result = convertTypeValueExprToRaw(e) + or result = convertUnresolvedDeclRefExprToRaw(e) or result = convertUnresolvedDotExprToRaw(e) @@ -6832,6 +6870,8 @@ module Synth { or result = convertInOutTypeToRaw(e) or + result = convertIntegerTypeToRaw(e) + or result = convertLValueTypeToRaw(e) or result = convertModuleTypeToRaw(e) diff --git a/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll b/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll index 474420586cac..a9225a1b0ce4 100644 --- a/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll +++ b/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll @@ -152,6 +152,7 @@ import codeql.swift.elements.expr.internal.TryExprConstructor import codeql.swift.elements.expr.internal.TupleElementExprConstructor import codeql.swift.elements.expr.internal.TupleExprConstructor import codeql.swift.elements.expr.internal.TypeExprConstructor +import codeql.swift.elements.expr.internal.TypeValueExprConstructor import codeql.swift.elements.expr.internal.UnderlyingToOpaqueExprConstructor import codeql.swift.elements.expr.internal.UnevaluatedInstanceExprConstructor import codeql.swift.elements.expr.internal.UnreachableExprConstructor @@ -228,6 +229,7 @@ import codeql.swift.elements.type.internal.FunctionTypeConstructor import codeql.swift.elements.type.internal.GenericFunctionTypeConstructor import codeql.swift.elements.type.internal.GenericTypeParamTypeConstructor import codeql.swift.elements.type.internal.InOutTypeConstructor +import codeql.swift.elements.type.internal.IntegerTypeConstructor import codeql.swift.elements.type.internal.LValueTypeConstructor import codeql.swift.elements.type.internal.MetatypeTypeConstructor import codeql.swift.elements.type.internal.ModuleTypeConstructor diff --git a/swift/ql/lib/codeql/swift/generated/expr/TypeValueExpr.qll b/swift/ql/lib/codeql/swift/generated/expr/TypeValueExpr.qll new file mode 100644 index 000000000000..602b0db23757 --- /dev/null +++ b/swift/ql/lib/codeql/swift/generated/expr/TypeValueExpr.qll @@ -0,0 +1,34 @@ +// generated by codegen/codegen.py, do not edit +/** + * This module provides the generated definition of `TypeValueExpr`. + * INTERNAL: Do not import directly. + */ + +private import codeql.swift.generated.Synth +private import codeql.swift.generated.Raw +import codeql.swift.elements.expr.internal.ExprImpl::Impl as ExprImpl +import codeql.swift.elements.type.TypeRepr + +/** + * INTERNAL: This module contains the fully generated definition of `TypeValueExpr` and should not + * be referenced directly. + */ +module Generated { + /** + * INTERNAL: Do not reference the `Generated::TypeValueExpr` class directly. + * Use the subclass `TypeValueExpr`, where the following predicates are available. + */ + class TypeValueExpr extends Synth::TTypeValueExpr, ExprImpl::Expr { + override string getAPrimaryQlClass() { result = "TypeValueExpr" } + + /** + * Gets the type representation of this type value expression. + */ + TypeRepr getTypeRepr() { + result = + Synth::convertTypeReprFromRaw(Synth::convertTypeValueExprToRaw(this) + .(Raw::TypeValueExpr) + .getTypeRepr()) + } + } +} diff --git a/swift/ql/lib/codeql/swift/generated/type/IntegerType.qll b/swift/ql/lib/codeql/swift/generated/type/IntegerType.qll new file mode 100644 index 000000000000..655d4b1fc197 --- /dev/null +++ b/swift/ql/lib/codeql/swift/generated/type/IntegerType.qll @@ -0,0 +1,30 @@ +// generated by codegen/codegen.py, do not edit +/** + * This module provides the generated definition of `IntegerType`. + * INTERNAL: Do not import directly. + */ + +private import codeql.swift.generated.Synth +private import codeql.swift.generated.Raw +import codeql.swift.elements.type.internal.TypeImpl::Impl as TypeImpl + +/** + * INTERNAL: This module contains the fully generated definition of `IntegerType` and should not + * be referenced directly. + */ +module Generated { + /** + * INTERNAL: Do not reference the `Generated::IntegerType` class directly. + * Use the subclass `IntegerType`, where the following predicates are available. + */ + class IntegerType extends Synth::TIntegerType, TypeImpl::Type { + override string getAPrimaryQlClass() { result = "IntegerType" } + + /** + * Gets the value of this integer type. + */ + string getValue() { + result = Synth::convertIntegerTypeToRaw(this).(Raw::IntegerType).getValue() + } + } +} diff --git a/swift/ql/lib/swift.dbscheme b/swift/ql/lib/swift.dbscheme index 3d88fb615e8a..4295ec72e82d 100644 --- a/swift/ql/lib/swift.dbscheme +++ b/swift/ql/lib/swift.dbscheme @@ -819,6 +819,7 @@ arguments( //dir=expr | @tuple_element_expr | @tuple_expr | @type_expr +| @type_value_expr | @unresolved_decl_ref_expr | @unresolved_dot_expr | @unresolved_member_expr @@ -1281,6 +1282,11 @@ type_expr_type_reprs( //dir=expr int type_repr: @type_repr_or_none ref ); +type_value_exprs( //dir=expr + unique int id: @type_value_expr, + int type_repr: @type_repr_or_none ref +); + unresolved_decl_ref_exprs( //dir=expr unique int id: @unresolved_decl_ref_expr ); @@ -2132,6 +2138,7 @@ while_stmts( //dir=stmt | @error_type | @existential_type | @in_out_type +| @integer_type | @l_value_type | @module_type | @pack_element_type @@ -2247,6 +2254,11 @@ in_out_types( //dir=type int object_type: @type_or_none ref ); +integer_types( //dir=type + unique int id: @integer_type, + string value: string ref +); + l_value_types( //dir=type unique int id: @l_value_type, int object_type: @type_or_none ref diff --git a/swift/ql/test/TestUtils.qll b/swift/ql/test/TestUtils.qll index 9b5429f8ba92..3cc64e753b37 100644 --- a/swift/ql/test/TestUtils.qll +++ b/swift/ql/test/TestUtils.qll @@ -9,6 +9,8 @@ predicate toBeTested(Element e) { e instanceof File and (exists(e.(File).getRelativePath()) or e instanceof UnknownFile) or + e instanceof IntegerType + or e instanceof ParameterizedProtocolType or e instanceof PackType diff --git a/swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr.expected b/swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr.expected new file mode 100644 index 000000000000..fa57faafb196 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr.expected @@ -0,0 +1,2 @@ +| type_value_exprs.swift:4:13:4:13 | TypeValueExpr | hasType: | yes | getTypeRepr: | type_value_exprs.swift:4:13:4:13 | (no string representation) | +| type_value_exprs.swift:5:13:5:13 | TypeValueExpr | hasType: | yes | getTypeRepr: | type_value_exprs.swift:5:13:5:13 | (no string representation) | diff --git a/swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr.ql b/swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr.ql new file mode 100644 index 000000000000..d434781d1527 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr.ql @@ -0,0 +1,11 @@ +// generated by codegen/codegen.py, do not edit +import codeql.swift.elements +import TestUtils + +from TypeValueExpr x, string hasType, TypeRepr getTypeRepr +where + toBeTested(x) and + not x.isUnknown() and + (if x.hasType() then hasType = "yes" else hasType = "no") and + getTypeRepr = x.getTypeRepr() +select x, "hasType:", hasType, "getTypeRepr:", getTypeRepr diff --git a/swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr_getType.expected b/swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr_getType.expected new file mode 100644 index 000000000000..43e481417906 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr_getType.expected @@ -0,0 +1,2 @@ +| type_value_exprs.swift:4:13:4:13 | TypeValueExpr | Int | +| type_value_exprs.swift:5:13:5:13 | TypeValueExpr | Int | diff --git a/swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr_getType.ql b/swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr_getType.ql new file mode 100644 index 000000000000..3c08a5c76d44 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/TypeValueExpr_getType.ql @@ -0,0 +1,7 @@ +// generated by codegen/codegen.py, do not edit +import codeql.swift.elements +import TestUtils + +from TypeValueExpr x +where toBeTested(x) and not x.isUnknown() +select x, x.getType() diff --git a/swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/type_value_exprs.swift b/swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/type_value_exprs.swift new file mode 100644 index 000000000000..d9ac932879cb --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/expr/TypeValueExpr/type_value_exprs.swift @@ -0,0 +1,8 @@ +//codeql-extractor-options: -enable-experimental-feature ValueGenerics -disable-availability-checking + +struct A { + var x = N; + var y = N; +} + +func f(with a : A<128>) {} diff --git a/swift/ql/test/extractor-tests/generated/type/IntegerType/IntegerType.expected b/swift/ql/test/extractor-tests/generated/type/IntegerType/IntegerType.expected new file mode 100644 index 000000000000..7fba23db8bdc --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/type/IntegerType/IntegerType.expected @@ -0,0 +1,2 @@ +| 128 | getName: | 128 | getCanonicalType: | 128 | getValue: | 128 | +| 256 | getName: | 256 | getCanonicalType: | 256 | getValue: | 256 | diff --git a/swift/ql/test/extractor-tests/generated/type/IntegerType/IntegerType.ql b/swift/ql/test/extractor-tests/generated/type/IntegerType/IntegerType.ql new file mode 100644 index 000000000000..dea3771c7c5d --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/type/IntegerType/IntegerType.ql @@ -0,0 +1,12 @@ +// generated by codegen/codegen.py, do not edit +import codeql.swift.elements +import TestUtils + +from IntegerType x, string getName, Type getCanonicalType, string getValue +where + toBeTested(x) and + not x.isUnknown() and + getName = x.getName() and + getCanonicalType = x.getCanonicalType() and + getValue = x.getValue() +select x, "getName:", getName, "getCanonicalType:", getCanonicalType, "getValue:", getValue diff --git a/swift/ql/test/extractor-tests/generated/type/IntegerType/integer_type.swift b/swift/ql/test/extractor-tests/generated/type/IntegerType/integer_type.swift new file mode 100644 index 000000000000..ce2127e600d2 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/type/IntegerType/integer_type.swift @@ -0,0 +1,9 @@ +//codeql-extractor-options: -enable-experimental-feature ValueGenerics -disable-availability-checking + +struct A { + var x = N; +} + +func f(with a : A<128>) {} + +func g(with a : A<256>) {} diff --git a/swift/schema.py b/swift/schema.py index 4e11bc7a33d1..917f5a3a30cc 100644 --- a/swift/schema.py +++ b/swift/schema.py @@ -1469,3 +1469,9 @@ class UnsafeCastExpr(ImplicitConversionExpr): """ A conversion that performs an unsafe bitcast. """ + +class TypeValueExpr(Expr): + type_repr: TypeRepr | child + +class IntegerType(Type): + value: string From 98384bf4c2084a1faefcb199379ff5be89572aad Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 2 May 2025 14:32:04 +0200 Subject: [PATCH 232/336] Swift: Support `BuiltinFixedArrayType` --- swift/extractor/infra/SwiftTagTraits.h | 4 +-- swift/ql/.generated.list | 14 ++++++---- swift/ql/.gitattributes | 4 +++ swift/ql/lib/codeql/swift/elements.qll | 1 + .../elements/type/BuiltinFixedArrayType.qll | 12 ++++++++ .../BuiltinFixedArrayTypeConstructor.qll | 14 ++++++++++ .../internal/BuiltinFixedArrayTypeImpl.qll | 19 +++++++++++++ .../codeql/swift/generated/ParentChild.qll | 18 ++++++++++++ swift/ql/lib/codeql/swift/generated/Raw.qll | 8 ++++++ swift/ql/lib/codeql/swift/generated/Synth.qll | 28 +++++++++++++++++-- .../swift/generated/SynthConstructors.qll | 1 + .../generated/type/BuiltinFixedArrayType.qll | 24 ++++++++++++++++ swift/ql/lib/swift.dbscheme | 5 ++++ .../type/BuiltinType/BuiltinType.expected | 3 ++ .../type/BuiltinType/fixed_array.swift | 9 ++++++ swift/schema.py | 6 ++++ 16 files changed, 161 insertions(+), 9 deletions(-) create mode 100644 swift/ql/lib/codeql/swift/elements/type/BuiltinFixedArrayType.qll create mode 100644 swift/ql/lib/codeql/swift/elements/type/internal/BuiltinFixedArrayTypeConstructor.qll create mode 100644 swift/ql/lib/codeql/swift/elements/type/internal/BuiltinFixedArrayTypeImpl.qll create mode 100644 swift/ql/lib/codeql/swift/generated/type/BuiltinFixedArrayType.qll create mode 100644 swift/ql/test/extractor-tests/generated/type/BuiltinType/fixed_array.swift diff --git a/swift/extractor/infra/SwiftTagTraits.h b/swift/extractor/infra/SwiftTagTraits.h index 285f48cc940e..b204c06ff0b9 100644 --- a/swift/extractor/infra/SwiftTagTraits.h +++ b/swift/extractor/infra/SwiftTagTraits.h @@ -285,8 +285,8 @@ MAP(swift::TypeBase, TypeTag) MAP(swift::BuiltinVectorType, BuiltinVectorTypeTag) MAP(swift::BuiltinPackIndexType, void) // SIL type, cannot really appear in the frontend run MAP(swift::BuiltinNonDefaultDistributedActorStorageType, void) // Does not appear in AST/SIL, only used during IRGen - MAP(swift::BuiltinFixedArrayType, void) // TODO swift 6.1 - MAP(swift::BuiltinUnboundGenericType, void) // TODO swift 6.1 + MAP(swift::BuiltinFixedArrayType, BuiltinFixedArrayTypeTag) + MAP(swift::BuiltinUnboundGenericType, void) // Only used during type resolution MAP(swift::TupleType, TupleTypeTag) MAP(swift::ReferenceStorageType, ReferenceStorageTypeTag) MAP(swift::WeakStorageType, WeakStorageTypeTag) diff --git a/swift/ql/.generated.list b/swift/ql/.generated.list index fcec2a9fbe21..f693ce9e9fc5 100644 --- a/swift/ql/.generated.list +++ b/swift/ql/.generated.list @@ -537,6 +537,7 @@ lib/codeql/swift/elements/type/BoundGenericType.qll 089e5e8d09c62a23d575dcab68cd lib/codeql/swift/elements/type/BuiltinBridgeObjectType.qll b0064e09b53efe801b0bf950ff00698a84e2f714e853e4859ed5f3246025a1bd aa14b6ae2ec510c4ddd2cc073bf971809536ab8fd8763fd05bd171b0bbe83860 lib/codeql/swift/elements/type/BuiltinDefaultActorStorageType.qll e867a9d0b2c61b7eb61f5143c78e31f8d98d3245d79e0e3281d4c172175f496b 265e87f2e37ca968af572cc619294d1ee91dd66ebb0d1bb1ba9ab7159de52f0b lib/codeql/swift/elements/type/BuiltinExecutorType.qll 2b141553bbc02a00d97579ba9d0e38fa0978d40ce954b0caf64826aa259dbc08 a81465fd0e87ad5b8e418d8f21c337b3e96388a3b92b3332f0d6b0ff7663e5c7 +lib/codeql/swift/elements/type/BuiltinFixedArrayType.qll 24a57f15a53070e6308841cd5dac4d55059e84d9fb18a77eec1130647dcdc97c 9f4167ef5190cbeee71abd068bdb0a280b690a16349cd408244d4cf9edfb357a lib/codeql/swift/elements/type/BuiltinFloatType.qll 81f49325077b75cea682904ddab24d1b2fdc5c93b0b28830c08e866d5c9307a7 e26a348d66e3824ccd92729624ce2b2ebc82a844aa47035e0a963a62b08b772d lib/codeql/swift/elements/type/BuiltinIntegerLiteralType.qll 34ee35733cf26f90d799a79f8a2362b199ea2ecb6ba83eb5678dda9eb3ed255f e33fdb27d3c22d441277b66ba74136cb88e1da25a2146391b258c68f7fbf5dd3 lib/codeql/swift/elements/type/BuiltinIntegerType.qll b931e79a40fb379a8de377ae4ea1c85befb7b07dbfe913f0ea7f5adf5514b217 5d7e6f21284b8c5ff70773bb64f896a40541c9064bfdd336798ccfda4cb4fb9e @@ -615,6 +616,8 @@ lib/codeql/swift/elements/type/internal/BuiltinDefaultActorStorageTypeConstructo lib/codeql/swift/elements/type/internal/BuiltinDefaultActorStorageTypeImpl.qll 1bf51a54fa58bbf89aaecbf631e44f7be014594c2a595e51c8ac54e790b3c05d a715240732615d22623a70b09c6c4d48d7b1d93dd0dc5a30d207136b3b4c4efc lib/codeql/swift/elements/type/internal/BuiltinExecutorTypeConstructor.qll 2f9aea7e019b4c696294660a89b94d254b6d7bbd5b6d54991a1fc2e3306fed50 28c28b2d2a05a0e415e1b56f743d66b7f5e6a1aa2e6087d8a2743b7e34a602c4 lib/codeql/swift/elements/type/internal/BuiltinExecutorTypeImpl.qll 0a5f8edd92f68cf8a8f0036f52f454f0279771d3bef5e748e61f1f3eaeb51758 92624449d217fe69c6c9e40488039c59306db5f22066ff245ba7d4957a705043 +lib/codeql/swift/elements/type/internal/BuiltinFixedArrayTypeConstructor.qll 0d5af4926703f1c8989c2f8960885e769efe86e0b623e843b788242499771565 2449589a1c1d5748d7ead874cc1dc98ffb49a065a0dc8963f741f66845785a74 +lib/codeql/swift/elements/type/internal/BuiltinFixedArrayTypeImpl.qll 6b69ba8b271646bcd699e338f41c186f3e4e7d401830918407e392312b2f0ad1 ecaca3d762264423094f7c2cb63e33b5d72d970946766eec33d984fa977950b4 lib/codeql/swift/elements/type/internal/BuiltinFloatTypeConstructor.qll f1dab7b9d36213e57083a6effec1b2d859553831394c0e746c592c96a20db6de cceeaa864cfc84511b3cdad6a88d44fc14ea1c8e38db72b0854c3f217a3f9c44 lib/codeql/swift/elements/type/internal/BuiltinFloatTypeImpl.qll 1dc7f7817c4a238751875b0cee98d060a1ea975a22fd90ceef0f9874b85824d6 d98f743c28174fb3294f0ff60232600a4fc80aeefe72e5cc15bb56e09880ec1e lib/codeql/swift/elements/type/internal/BuiltinIntegerLiteralTypeConstructor.qll 3885775f78e18286aa8dc99ab5b6f386a278b34b47f93da28d67faac918e6087 93be2ad0b7235bab613b74582bc1de0ca8b2a4da7a387d09a9b8ef9b38095534 @@ -713,7 +716,7 @@ lib/codeql/swift/elements/type/internal/UnresolvedTypeImpl.qll ee1499dd568753898 lib/codeql/swift/elements/type/internal/VariadicSequenceTypeConstructor.qll fc74a5a2a2effa28ef24509b20ee4373d97cf6e8c71840121bb031c6adedf584 c9b2effc1d01c13c5e6a74a111122fa79a2f6554dda3cb016d68ba397e566ec4 lib/codeql/swift/elements/type/internal/WeakStorageTypeConstructor.qll 5fdce3716aba6318522174a2c455a63480970222ae81c732fb19c6dd3ae2d271 60ea79d6943e129deba0deccb566cf9d73f78398b0f7f0212674d91287d6b2ae lib/codeql/swift/elements/type/internal/WeakStorageTypeImpl.qll 74f79b458f3204ec2519bd654de21bc4fb6b76816bd8ca01990fe897563a1383 34e1810f74cecda5b580ed050438ae1d914b97a36b8f4e2de1c25254c0cac633 -lib/codeql/swift/elements.qll 67832d269392e0c8226bd03918be9b3e4cf11213e54dd3acfe153dd8f8cd33c7 67832d269392e0c8226bd03918be9b3e4cf11213e54dd3acfe153dd8f8cd33c7 +lib/codeql/swift/elements.qll 2c093130866888903f5a97cc41072ad94c795d296fca6492d6db481b1ca39d94 2c093130866888903f5a97cc41072ad94c795d296fca6492d6db481b1ca39d94 lib/codeql/swift/generated/AstNode.qll 6fb80e9b230a1e3ae8193af40744f253d5cc81dc4239156924e5ab606c491efc e5c28418e9a38bde08f323a3986a199620189fc4a8a4dc8f670610a5d3d65b99 lib/codeql/swift/generated/AvailabilityInfo.qll e3a5274c43e72ff124b6988fd8be0c83a41b89337e11104150dd0ca7f51d8a11 889563791ca8d9758dbbccf64a0731c4bdbf721cad32bc6cd723f1072b6aa1de lib/codeql/swift/generated/AvailabilitySpec.qll bc64d5c690c4d18800f0a48cc76a6a9ee4f832041343666da2d8df2aae04ed7e d03bf874293ac0ab09c025f75c0f392473d47bebe3223143adcc13882a366119 @@ -730,12 +733,12 @@ lib/codeql/swift/generated/Locatable.qll 1d37fa20de71c0b9986bfd7a7c0cb82ab7bf3fd lib/codeql/swift/generated/Location.qll 5e20316c3e480ddfe632b7e88e016c19f10a67df1f6ae9c8f128755a6907d6f5 5a0af2d070bcb2ed53d6d0282bf9c60dc64c2dce89c21fdd485e9c7893c1c8fa lib/codeql/swift/generated/MacroRole.qll facf907e75490d69cd401c491215e4719324d751f40ea46c86ccf24cf3663c1f 969d8d4b44e3f1a9c193a152a4d83a303e56d2dbb871fc920c47a33f699cf018 lib/codeql/swift/generated/OtherAvailabilitySpec.qll d9feaa2a71acff3184ca389045b0a49d09156210df0e034923d715b432ad594b 046737621a8bcf69bf805afb0cff476bd15259f12f0d77fce3206dd01b31518f -lib/codeql/swift/generated/ParentChild.qll 3b7e2e04c92f395f446fbf2dcf62f97a1b066523a5feb90c1cede9a1e644d4e4 58b8a96626a061b11ea0783b0356467358ef80bc9148666f78d6b64a0457a899 +lib/codeql/swift/generated/ParentChild.qll d66e5c28e93a3085fbae0ada238a96577ad21fd64a37ce967032bf5df8bdfb1d 2d440ad9c0304f658d54c6c53a8b1db1d3e032ee5522b51c46116413d0cf5dbb lib/codeql/swift/generated/PlatformVersionAvailabilitySpec.qll dc17b49a90a18a8f7607adf2433bc8f0c194fa3e803aa3822f809d4d4fbd6793 be48ea9f8ae17354c8508aaed24337a9e57ce01f288fece3dcecd99776cabcec lib/codeql/swift/generated/PureSynthConstructors.qll bc31a6c4d142fa3fbdcae69d5ba6f1cec00eb9ad92b46c8d7b91ebfa7ef6c1f4 bc31a6c4d142fa3fbdcae69d5ba6f1cec00eb9ad92b46c8d7b91ebfa7ef6c1f4 -lib/codeql/swift/generated/Raw.qll ca16e576312f595283994e8b02a32693826712c76c471f7969271dc09361d13e 3d86c741064a075810e1e92d2c3bdc2a77755b9142904dee95709117af3c29a1 -lib/codeql/swift/generated/Synth.qll a8462dd9e84e0059f6ca4d9c9f42ac75d0d3fd7b65702e1409c583a89665f18c 051e02492cba3ddda863cd80507a49884d73d57c834f00f6d3547e2143c48dbe -lib/codeql/swift/generated/SynthConstructors.qll 9dc761332663708d16ee6303930557858ea56049ce2dbac4b14f995e6c02977d 9dc761332663708d16ee6303930557858ea56049ce2dbac4b14f995e6c02977d +lib/codeql/swift/generated/Raw.qll 96d5f8778f25cd396b5cc56c38dce597c5a9a5c2b1e9ed8b9a4d2eca89e49323 d65072b5c508dad1dd813e19f7431087d8bfc0e5d85aa3d19beffbcbbec585ec +lib/codeql/swift/generated/Synth.qll 2b0f1a8911c1981ff50b78331bdd1f3f6023ad87a4ae3a92088901f493bb62c0 bc94ca1d86033e04b0999da84b61955ea1d8f4ac2379be527802512a42a16964 +lib/codeql/swift/generated/SynthConstructors.qll d30b83f9d8d310414bb1261af386b70502df48159d06579bb2610e18ef546c3d d30b83f9d8d310414bb1261af386b70502df48159d06579bb2610e18ef546c3d lib/codeql/swift/generated/UnknownFile.qll 247ddf2ebb49ce5ed4bf7bf91a969ddff37de6c78d43d8affccaf7eb586e06f2 452b29f0465ef45e978ef8b647b75e5a2a1e53f2a568fc003bc8f52f73b3fa4d lib/codeql/swift/generated/UnknownLocation.qll d871000b4f53ffca4f67ea23ca5626e5dcce125d62a4d4b9969e08cc974af6fc b05971d7774e60790362fb810fb7086314f40a2de747b8cb1bc823ec6494a4dd lib/codeql/swift/generated/UnspecifiedElement.qll d9ad4ba1ffff90cc465e8ba0dea8c4e8ba67dce5529b53b63ab6dc8e13c85e67 025218e1fee8ee382b63ad38009dfec73dc604d2ba80b9ad956c7c96eeed7022 @@ -970,6 +973,7 @@ lib/codeql/swift/generated/type/BoundGenericType.qll 5e7a2210b766437ca301f9675f7 lib/codeql/swift/generated/type/BuiltinBridgeObjectType.qll 97f30768a8788ec4547ce8a8f06fdd165286177e3819bf2e6590b9479f5bada4 ea3161c34d1d18783b38deac43c73048e4510015307d93f77cd95c149e988846 lib/codeql/swift/generated/type/BuiltinDefaultActorStorageType.qll 10e49de9a8bc3e67285c111f7869c8baceb70e478661d5557ebc8c86f41b4aec 1a0ce85eb325f666fbc2ac49c6f994efd552de6f2105e0a7ba9a10e39f3d1591 lib/codeql/swift/generated/type/BuiltinExecutorType.qll 8f58d4d413910aded894bfa9b54748adfc2b78f4ee271ac6db5f5b0214f36a66 69da70d76146155529b7b2426b3a459abe318f887240aac1aed5719fda5f386a +lib/codeql/swift/generated/type/BuiltinFixedArrayType.qll 9bd26596da9137b07324222c9ed39ec0781e44673314fba96a0c7cf16f65cc7d cc2d40961b070a89f3350ab95b92ae33372277e499d7b2a9ea34721cc1fe1923 lib/codeql/swift/generated/type/BuiltinFloatType.qll 6306a806107bba052fe0b1335c8c4d4391cdb6aa5f42f14c70743113928c4c36 3265d571630c0437e5d81ba20a0b6112b7e88ee3ffca737557186001cf8aa04a lib/codeql/swift/generated/type/BuiltinIntegerLiteralType.qll 3f49aac9b81c440b902a658294cf95aff5cb79b0d6cee8b1abd8a08ad45c7966 6c184dcf5d9376f193f07fe4722ea7cab51f1dfdef4d72c3042842d73cca31fe lib/codeql/swift/generated/type/BuiltinIntegerType.qll 3cfcbc4ebea6051d1f6dedcf098888c72c02bf697cebb52a0060c1885bea61f0 1c78df7a184e3615024d6e361b88dd619828a0aa7d342564610a95b02cc67d1e diff --git a/swift/ql/.gitattributes b/swift/ql/.gitattributes index 2d8114e910cb..761b2efeb7cd 100644 --- a/swift/ql/.gitattributes +++ b/swift/ql/.gitattributes @@ -539,6 +539,7 @@ /lib/codeql/swift/elements/type/BuiltinBridgeObjectType.qll linguist-generated /lib/codeql/swift/elements/type/BuiltinDefaultActorStorageType.qll linguist-generated /lib/codeql/swift/elements/type/BuiltinExecutorType.qll linguist-generated +/lib/codeql/swift/elements/type/BuiltinFixedArrayType.qll linguist-generated /lib/codeql/swift/elements/type/BuiltinFloatType.qll linguist-generated /lib/codeql/swift/elements/type/BuiltinIntegerLiteralType.qll linguist-generated /lib/codeql/swift/elements/type/BuiltinIntegerType.qll linguist-generated @@ -617,6 +618,8 @@ /lib/codeql/swift/elements/type/internal/BuiltinDefaultActorStorageTypeImpl.qll linguist-generated /lib/codeql/swift/elements/type/internal/BuiltinExecutorTypeConstructor.qll linguist-generated /lib/codeql/swift/elements/type/internal/BuiltinExecutorTypeImpl.qll linguist-generated +/lib/codeql/swift/elements/type/internal/BuiltinFixedArrayTypeConstructor.qll linguist-generated +/lib/codeql/swift/elements/type/internal/BuiltinFixedArrayTypeImpl.qll linguist-generated /lib/codeql/swift/elements/type/internal/BuiltinFloatTypeConstructor.qll linguist-generated /lib/codeql/swift/elements/type/internal/BuiltinFloatTypeImpl.qll linguist-generated /lib/codeql/swift/elements/type/internal/BuiltinIntegerLiteralTypeConstructor.qll linguist-generated @@ -972,6 +975,7 @@ /lib/codeql/swift/generated/type/BuiltinBridgeObjectType.qll linguist-generated /lib/codeql/swift/generated/type/BuiltinDefaultActorStorageType.qll linguist-generated /lib/codeql/swift/generated/type/BuiltinExecutorType.qll linguist-generated +/lib/codeql/swift/generated/type/BuiltinFixedArrayType.qll linguist-generated /lib/codeql/swift/generated/type/BuiltinFloatType.qll linguist-generated /lib/codeql/swift/generated/type/BuiltinIntegerLiteralType.qll linguist-generated /lib/codeql/swift/generated/type/BuiltinIntegerType.qll linguist-generated diff --git a/swift/ql/lib/codeql/swift/elements.qll b/swift/ql/lib/codeql/swift/elements.qll index f840aa9df513..2551a7ece9b1 100644 --- a/swift/ql/lib/codeql/swift/elements.qll +++ b/swift/ql/lib/codeql/swift/elements.qll @@ -250,6 +250,7 @@ import codeql.swift.elements.type.BoundGenericType import codeql.swift.elements.type.BuiltinBridgeObjectType import codeql.swift.elements.type.BuiltinDefaultActorStorageType import codeql.swift.elements.type.BuiltinExecutorType +import codeql.swift.elements.type.BuiltinFixedArrayType import codeql.swift.elements.type.BuiltinFloatType import codeql.swift.elements.type.BuiltinIntegerLiteralType import codeql.swift.elements.type.BuiltinIntegerType diff --git a/swift/ql/lib/codeql/swift/elements/type/BuiltinFixedArrayType.qll b/swift/ql/lib/codeql/swift/elements/type/BuiltinFixedArrayType.qll new file mode 100644 index 000000000000..bf523a0a7852 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/type/BuiltinFixedArrayType.qll @@ -0,0 +1,12 @@ +// generated by codegen/codegen.py, do not edit +/** + * This module provides the public class `BuiltinFixedArrayType`. + */ + +private import internal.BuiltinFixedArrayTypeImpl +import codeql.swift.elements.type.BuiltinType + +/** + * A builtin type representing N values stored contiguously. + */ +final class BuiltinFixedArrayType = Impl::BuiltinFixedArrayType; diff --git a/swift/ql/lib/codeql/swift/elements/type/internal/BuiltinFixedArrayTypeConstructor.qll b/swift/ql/lib/codeql/swift/elements/type/internal/BuiltinFixedArrayTypeConstructor.qll new file mode 100644 index 000000000000..51c78ebf215b --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/type/internal/BuiltinFixedArrayTypeConstructor.qll @@ -0,0 +1,14 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +/** + * This module defines the hook used internally to tweak the characteristic predicate of + * `BuiltinFixedArrayType` synthesized instances. + * INTERNAL: Do not use. + */ + +private import codeql.swift.generated.Raw + +/** + * The characteristic predicate of `BuiltinFixedArrayType` synthesized instances. + * INTERNAL: Do not use. + */ +predicate constructBuiltinFixedArrayType(Raw::BuiltinFixedArrayType id) { any() } diff --git a/swift/ql/lib/codeql/swift/elements/type/internal/BuiltinFixedArrayTypeImpl.qll b/swift/ql/lib/codeql/swift/elements/type/internal/BuiltinFixedArrayTypeImpl.qll new file mode 100644 index 000000000000..ff157961c40f --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/type/internal/BuiltinFixedArrayTypeImpl.qll @@ -0,0 +1,19 @@ +// generated by codegen/codegen.py, remove this comment if you wish to edit this file +/** + * This module provides a hand-modifiable wrapper around the generated class `BuiltinFixedArrayType`. + * + * INTERNAL: Do not use. + */ + +private import codeql.swift.generated.type.BuiltinFixedArrayType + +/** + * INTERNAL: This module contains the customizable definition of `BuiltinFixedArrayType` and should not + * be referenced directly. + */ +module Impl { + /** + * A builtin type representing N values stored contiguously. + */ + class BuiltinFixedArrayType extends Generated::BuiltinFixedArrayType { } +} diff --git a/swift/ql/lib/codeql/swift/generated/ParentChild.qll b/swift/ql/lib/codeql/swift/generated/ParentChild.qll index 8ab3348f470b..49ffc37a473c 100644 --- a/swift/ql/lib/codeql/swift/generated/ParentChild.qll +++ b/swift/ql/lib/codeql/swift/generated/ParentChild.qll @@ -4564,6 +4564,22 @@ private module Impl { ) } + private Element getImmediateChildOfBuiltinFixedArrayType( + BuiltinFixedArrayType e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinType, int n | + b = 0 and + bBuiltinType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinType(e, i, _)) | i) and + n = bBuiltinType and + ( + none() + or + result = getImmediateChildOfBuiltinType(e, index - b, partialPredicateCall) + ) + ) + } + private Element getImmediateChildOfBuiltinFloatType( BuiltinFloatType e, int index, string partialPredicateCall ) { @@ -5679,6 +5695,8 @@ private module Impl { or result = getImmediateChildOfBuiltinExecutorType(e, index, partialAccessor) or + result = getImmediateChildOfBuiltinFixedArrayType(e, index, partialAccessor) + or result = getImmediateChildOfBuiltinFloatType(e, index, partialAccessor) or result = getImmediateChildOfBuiltinJobType(e, index, partialAccessor) diff --git a/swift/ql/lib/codeql/swift/generated/Raw.qll b/swift/ql/lib/codeql/swift/generated/Raw.qll index 88ba766fc866..a2779b148e93 100644 --- a/swift/ql/lib/codeql/swift/generated/Raw.qll +++ b/swift/ql/lib/codeql/swift/generated/Raw.qll @@ -3546,6 +3546,14 @@ module Raw { override string toString() { result = "BuiltinExecutorType" } } + /** + * INTERNAL: Do not use. + * A builtin type representing N values stored contiguously. + */ + class BuiltinFixedArrayType extends @builtin_fixed_array_type, BuiltinType { + override string toString() { result = "BuiltinFixedArrayType" } + } + /** * INTERNAL: Do not use. */ diff --git a/swift/ql/lib/codeql/swift/generated/Synth.qll b/swift/ql/lib/codeql/swift/generated/Synth.qll index 7eecd52e6266..09f52604bb92 100644 --- a/swift/ql/lib/codeql/swift/generated/Synth.qll +++ b/swift/ql/lib/codeql/swift/generated/Synth.qll @@ -900,6 +900,10 @@ module Synth { * INTERNAL: Do not use. */ TBuiltinExecutorType(Raw::BuiltinExecutorType id) { constructBuiltinExecutorType(id) } or + /** + * INTERNAL: Do not use. + */ + TBuiltinFixedArrayType(Raw::BuiltinFixedArrayType id) { constructBuiltinFixedArrayType(id) } or /** * INTERNAL: Do not use. */ @@ -1389,8 +1393,8 @@ module Synth { */ class TBuiltinType = TAnyBuiltinIntegerType or TBuiltinBridgeObjectType or TBuiltinDefaultActorStorageType or - TBuiltinExecutorType or TBuiltinFloatType or TBuiltinJobType or TBuiltinNativeObjectType or - TBuiltinRawPointerType or TBuiltinRawUnsafeContinuationType or + TBuiltinExecutorType or TBuiltinFixedArrayType or TBuiltinFloatType or TBuiltinJobType or + TBuiltinNativeObjectType or TBuiltinRawPointerType or TBuiltinRawUnsafeContinuationType or TBuiltinUnsafeValueBufferType or TBuiltinVectorType; /** @@ -2861,6 +2865,14 @@ module Synth { result = TBuiltinExecutorType(e) } + /** + * INTERNAL: Do not use. + * Converts a raw element to a synthesized `TBuiltinFixedArrayType`, if possible. + */ + TBuiltinFixedArrayType convertBuiltinFixedArrayTypeFromRaw(Raw::Element e) { + result = TBuiltinFixedArrayType(e) + } + /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TBuiltinFloatType`, if possible. @@ -4022,6 +4034,8 @@ module Synth { or result = convertBuiltinExecutorTypeFromRaw(e) or + result = convertBuiltinFixedArrayTypeFromRaw(e) + or result = convertBuiltinFloatTypeFromRaw(e) or result = convertBuiltinJobTypeFromRaw(e) @@ -5593,6 +5607,14 @@ module Synth { e = TBuiltinExecutorType(result) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TBuiltinFixedArrayType` to a raw DB element, if possible. + */ + Raw::Element convertBuiltinFixedArrayTypeToRaw(TBuiltinFixedArrayType e) { + e = TBuiltinFixedArrayType(result) + } + /** * INTERNAL: Do not use. * Converts a synthesized `TBuiltinFloatType` to a raw DB element, if possible. @@ -6754,6 +6776,8 @@ module Synth { or result = convertBuiltinExecutorTypeToRaw(e) or + result = convertBuiltinFixedArrayTypeToRaw(e) + or result = convertBuiltinFloatTypeToRaw(e) or result = convertBuiltinJobTypeToRaw(e) diff --git a/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll b/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll index a9225a1b0ce4..8ffefd96281d 100644 --- a/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll +++ b/swift/ql/lib/codeql/swift/generated/SynthConstructors.qll @@ -207,6 +207,7 @@ import codeql.swift.elements.type.internal.BoundGenericStructTypeConstructor import codeql.swift.elements.type.internal.BuiltinBridgeObjectTypeConstructor import codeql.swift.elements.type.internal.BuiltinDefaultActorStorageTypeConstructor import codeql.swift.elements.type.internal.BuiltinExecutorTypeConstructor +import codeql.swift.elements.type.internal.BuiltinFixedArrayTypeConstructor import codeql.swift.elements.type.internal.BuiltinFloatTypeConstructor import codeql.swift.elements.type.internal.BuiltinIntegerLiteralTypeConstructor import codeql.swift.elements.type.internal.BuiltinIntegerTypeConstructor diff --git a/swift/ql/lib/codeql/swift/generated/type/BuiltinFixedArrayType.qll b/swift/ql/lib/codeql/swift/generated/type/BuiltinFixedArrayType.qll new file mode 100644 index 000000000000..b61533168b77 --- /dev/null +++ b/swift/ql/lib/codeql/swift/generated/type/BuiltinFixedArrayType.qll @@ -0,0 +1,24 @@ +// generated by codegen/codegen.py, do not edit +/** + * This module provides the generated definition of `BuiltinFixedArrayType`. + * INTERNAL: Do not import directly. + */ + +private import codeql.swift.generated.Synth +private import codeql.swift.generated.Raw +import codeql.swift.elements.type.internal.BuiltinTypeImpl::Impl as BuiltinTypeImpl + +/** + * INTERNAL: This module contains the fully generated definition of `BuiltinFixedArrayType` and should not + * be referenced directly. + */ +module Generated { + /** + * A builtin type representing N values stored contiguously. + * INTERNAL: Do not reference the `Generated::BuiltinFixedArrayType` class directly. + * Use the subclass `BuiltinFixedArrayType`, where the following predicates are available. + */ + class BuiltinFixedArrayType extends Synth::TBuiltinFixedArrayType, BuiltinTypeImpl::BuiltinType { + override string getAPrimaryQlClass() { result = "BuiltinFixedArrayType" } + } +} diff --git a/swift/ql/lib/swift.dbscheme b/swift/ql/lib/swift.dbscheme index 4295ec72e82d..987ab0bc0911 100644 --- a/swift/ql/lib/swift.dbscheme +++ b/swift/ql/lib/swift.dbscheme @@ -2220,6 +2220,7 @@ any_generic_type_parents( //dir=type | @builtin_bridge_object_type | @builtin_default_actor_storage_type | @builtin_executor_type +| @builtin_fixed_array_type | @builtin_float_type | @builtin_job_type | @builtin_native_object_type @@ -2402,6 +2403,10 @@ builtin_executor_types( //dir=type unique int id: @builtin_executor_type ); +builtin_fixed_array_types( //dir=type + unique int id: @builtin_fixed_array_type +); + builtin_float_types( //dir=type unique int id: @builtin_float_type ); diff --git a/swift/ql/test/extractor-tests/generated/type/BuiltinType/BuiltinType.expected b/swift/ql/test/extractor-tests/generated/type/BuiltinType/BuiltinType.expected index 27e4e6f08683..1b64e9f4a224 100644 --- a/swift/ql/test/extractor-tests/generated/type/BuiltinType/BuiltinType.expected +++ b/swift/ql/test/extractor-tests/generated/type/BuiltinType/BuiltinType.expected @@ -2,6 +2,9 @@ | Builtin.Executor | BuiltinExecutorType | getName: | Executor | getCanonicalType: | Builtin.Executor | | Builtin.FPIEEE32 | BuiltinFloatType | getName: | FPIEEE32 | getCanonicalType: | Builtin.FPIEEE32 | | Builtin.FPIEEE64 | BuiltinFloatType | getName: | FPIEEE64 | getCanonicalType: | Builtin.FPIEEE64 | +| Builtin.FixedArray<4, Int> | BuiltinFixedArrayType | getName: | FixedArray<4, Int> | getCanonicalType: | Builtin.FixedArray<4, Int> | +| Builtin.FixedArray | BuiltinFixedArrayType | getName: | FixedArray | getCanonicalType: | Builtin.FixedArray | +| Builtin.FixedArray<\u03c4_0_0, \u03c4_0_1> | BuiltinFixedArrayType | getName: | FixedArray<\u03c4_0_0, \u03c4_0_1> | getCanonicalType: | Builtin.FixedArray<\u03c4_0_0, \u03c4_0_1> | | Builtin.IntLiteral | BuiltinIntegerLiteralType | getName: | IntLiteral | getCanonicalType: | Builtin.IntLiteral | | Builtin.Job | BuiltinJobType | getName: | Job | getCanonicalType: | Builtin.Job | | Builtin.NativeObject | BuiltinNativeObjectType | getName: | NativeObject | getCanonicalType: | Builtin.NativeObject | diff --git a/swift/ql/test/extractor-tests/generated/type/BuiltinType/fixed_array.swift b/swift/ql/test/extractor-tests/generated/type/BuiltinType/fixed_array.swift new file mode 100644 index 000000000000..ab4229921061 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/type/BuiltinType/fixed_array.swift @@ -0,0 +1,9 @@ +//codeql-extractor-options: -enable-experimental-feature BuiltinModule -enable-experimental-feature ValueGenerics -disable-availability-checking + +import Builtin + +struct A { + var x: Builtin.FixedArray +} + +func f(x: Builtin.FixedArray<4, Int>) {} diff --git a/swift/schema.py b/swift/schema.py index 917f5a3a30cc..fc923d0c6a36 100644 --- a/swift/schema.py +++ b/swift/schema.py @@ -1475,3 +1475,9 @@ class TypeValueExpr(Expr): class IntegerType(Type): value: string + +class BuiltinFixedArrayType(BuiltinType): + """ + A builtin type representing N values stored contiguously. + """ + pass From 95ac458d2a992f7dc5a9e045964a0126a14113bc Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 2 May 2025 15:00:33 +0200 Subject: [PATCH 233/336] Swift: Add upgrade and downgrade scripts --- .../downgrade.ql | 50 + .../old.dbscheme | 2832 +++++++++++++++++ .../swift.dbscheme | 2810 ++++++++++++++++ .../upgrade.properties | 13 + .../old.dbscheme | 2810 ++++++++++++++++ .../swift.dbscheme | 2832 +++++++++++++++++ .../upgrade.properties | 2 + 7 files changed, 11349 insertions(+) create mode 100644 swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/downgrade.ql create mode 100644 swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/old.dbscheme create mode 100644 swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/swift.dbscheme create mode 100644 swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/upgrade.properties create mode 100644 swift/ql/lib/upgrades/4dd3d5ca8a89952485b3e3b2141b6bb8c22cf945/old.dbscheme create mode 100644 swift/ql/lib/upgrades/4dd3d5ca8a89952485b3e3b2141b6bb8c22cf945/swift.dbscheme create mode 100644 swift/ql/lib/upgrades/4dd3d5ca8a89952485b3e3b2141b6bb8c22cf945/upgrade.properties diff --git a/swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/downgrade.ql b/swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/downgrade.ql new file mode 100644 index 000000000000..ee11b5a86544 --- /dev/null +++ b/swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/downgrade.ql @@ -0,0 +1,50 @@ +class Element extends @element { + string toString() { none() } +} + +predicate removedClass(Element e, string name, Element child) { + type_value_exprs(e, child) and + name = "TypeValueExpr" + or + unsafe_cast_exprs(e) and + name = "UnsafeCastExpr" and + implicit_conversion_exprs(e, child) +} + +predicate removedClass(Element e, string name) { + integer_types(e, _) and + name = "IntegerType" + or + builtin_fixed_array_types(e) and + name = "BuiltinFixedArrayType" + or + removedClass(e, name, _) +} + +query predicate new_unspecified_elements(Element e, string property, string error) { + unspecified_elements(e, property, error) + or + exists(string name | + removedClass(e, name) and + property = "" and + error = name + " nodes removed during database downgrade. Please update your CodeQL code." + ) +} + +query predicate new_unspecified_element_children(Element e, int index, Element child) { + unspecified_element_children(e, index, child) + or + removedClass(e, _, child) and index = 0 +} + +query predicate new_implicit_conversion_exprs(Element e, Element child) { + implicit_conversion_exprs(e, child) and not removedClass(e, _) +} + +query predicate new_expr_types(Element e, Element type) { + expr_types(e, type) and not removedClass(e, _) +} + +query predicate new_types(Element e, string name, Element canonicalType) { + types(e, name, canonicalType) and not removedClass(e, _) +} diff --git a/swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/old.dbscheme b/swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/old.dbscheme new file mode 100644 index 000000000000..987ab0bc0911 --- /dev/null +++ b/swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/old.dbscheme @@ -0,0 +1,2832 @@ +// generated by codegen/codegen.py, do not edit + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @callable +| @case_label_item +| @condition_element +| @decl +| @expr +| @key_path_component +| @macro_role +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +@callable = + @closure_expr +| @function +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +key_path_components( + unique int id: @key_path_component, + int kind: int ref, + int component_type: @type_or_none ref +); + +#keyset[id, index] +key_path_component_subscript_arguments( + int id: @key_path_component ref, + int index: int ref, + int subscript_argument: @argument_or_none ref +); + +#keyset[id] +key_path_component_tuple_indices( + int id: @key_path_component ref, + int tuple_index: int ref +); + +#keyset[id] +key_path_component_decl_refs( + int id: @key_path_component ref, + int decl_ref: @value_decl_or_none ref +); + +macro_roles( + unique int id: @macro_role, + int kind: int ref, + int macro_syntax: int ref +); + +#keyset[id, index] +macro_role_conformances( + int id: @macro_role ref, + int index: int ref, + int conformance: @expr_or_none ref +); + +#keyset[id, index] +macro_role_names( + int id: @macro_role ref, + int index: int ref, + string name: string ref +); + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +#keyset[id, index] +unspecified_element_children( + int id: @unspecified_element ref, + int index: int ref, + int child: @ast_node_or_none ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @extension_decl +| @function +| @generic_type_decl +| @macro_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_storage_decl +| @enum_element_decl +| @function +| @macro_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessors( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor: @accessor_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@function = + @accessor_or_named_function +| @deinitializer +| @initializer +; + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +macro_decls( //dir=decl + unique int id: @macro_decl, + string name: string ref +); + +#keyset[id, index] +macro_decl_parameters( //dir=decl + int id: @macro_decl ref, + int index: int ref, + int parameter: @param_decl_or_none ref +); + +#keyset[id, index] +macro_decl_roles( //dir=decl + int id: @macro_decl ref, + int index: int ref, + int role: @macro_role_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_inherited_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int inherited_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +@accessor_or_named_function = + @accessor +| @named_function +; + +deinitializers( //dir=decl + unique int id: @deinitializer +); + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +initializers( //dir=decl + unique int id: @initializer +); + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int imported_module: @module_decl_or_none ref +); + +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessors( //dir=decl + unique int id: @accessor +); + +#keyset[id] +accessor_is_getter( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_setter( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_will_set( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_did_set( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_read( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_modify( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_unsafe_address( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_unsafe_mutable_address( //dir=decl + int id: @accessor ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +named_functions( //dir=decl + unique int id: @named_function +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl, + int aliased_type: @type_or_none ref +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @closure_expr +| @collection_expr +| @consume_expr +| @copy_expr +| @current_context_isolation_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @extract_function_isolation_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initialization_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @materialize_pack_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_initializer_ref_expr +| @overloaded_decl_ref_expr +| @pack_element_expr +| @pack_expansion_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_initializer_expr +| @sequence_expr +| @single_value_stmt_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @type_value_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@closure_expr = + @auto_closure_expr +| @explicit_closure_expr +; + +@collection_expr = + @array_expr +| @dictionary_expr +; + +consume_exprs( //dir=expr + unique int id: @consume_expr, + int sub_expr: @expr_or_none ref +); + +copy_exprs( //dir=expr + unique int id: @copy_expr, + int sub_expr: @expr_or_none ref +); + +current_context_isolation_exprs( //dir=expr + unique int id: @current_context_isolation_expr, + int actor: @expr_or_none ref +); + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +extract_function_isolation_exprs( //dir=expr + unique int id: @extract_function_isolation_expr, + int function_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @borrow_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @actor_isolation_erasure_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unreachable_expr +| @unresolved_type_conversion_expr +| @unsafe_cast_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id, index] +key_path_expr_components( //dir=expr + int id: @key_path_expr ref, + int index: int ref, + int component: @key_path_component_or_none ref +); + +lazy_initialization_exprs( //dir=expr + unique int id: @lazy_initialization_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +materialize_pack_exprs( //dir=expr + unique int id: @materialize_pack_expr, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @function_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_initializer_ref_exprs( //dir=expr + unique int id: @other_initializer_ref_expr, + int initializer: @initializer_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +pack_element_exprs( //dir=expr + unique int id: @pack_element_expr, + int sub_expr: @expr_or_none ref +); + +pack_expansion_exprs( //dir=expr + unique int id: @pack_expansion_expr, + int pattern_expr: @expr_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_initializer_exprs( //dir=expr + unique int id: @rebind_self_in_initializer_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +single_value_stmt_exprs( //dir=expr + unique int id: @single_value_stmt_expr, + int stmt: @stmt_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +type_value_exprs( //dir=expr + unique int id: @type_value_expr, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +actor_isolation_erasure_exprs( //dir=expr + unique int id: @actor_isolation_erasure_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +borrow_exprs( //dir=expr + unique int id: @borrow_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +explicit_closure_exprs( //dir=expr + unique int id: @explicit_closure_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @dot_syntax_call_expr +| @initializer_ref_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unreachable_exprs( //dir=expr + unique int id: @unreachable_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +unsafe_cast_exprs( //dir=expr + unique int id: @unsafe_cast_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +initializer_ref_call_exprs( //dir=expr + unique int id: @initializer_ref_call_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +#keyset[id] +pattern_types( //dir=pattern + int id: @pattern ref, + int type_: @type_or_none ref +); + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + int var_decl: @var_decl_or_none ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @discard_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @then_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +discard_stmts( //dir=stmt + unique int id: @discard_stmt, + int sub_expr: @expr_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +then_stmts( //dir=stmt + unique int id: @then_stmt, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +for_each_stmt_variables( //dir=stmt + int id: @for_each_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +#keyset[id] +for_each_stmt_iterator_vars( //dir=stmt + int id: @for_each_stmt ref, + int iteratorVar: @pattern_binding_decl_or_none ref +); + +#keyset[id] +for_each_stmt_next_calls( //dir=stmt + int id: @for_each_stmt ref, + int nextCall: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @integer_type +| @l_value_type +| @module_type +| @pack_element_type +| @pack_expansion_type +| @pack_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_fixed_array_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +integer_types( //dir=type + unique int id: @integer_type, + string value: string ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +pack_element_types( //dir=type + unique int id: @pack_element_type, + int pack_type: @type_or_none ref +); + +pack_expansion_types( //dir=type + unique int id: @pack_expansion_type, + int pattern_type: @type_or_none ref, + int count_type: @type_or_none ref +); + +pack_types( //dir=type + unique int id: @pack_type +); + +#keyset[id, index] +pack_type_elements( //dir=type + int id: @pack_type ref, + int index: int ref, + int element: @type_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @local_archetype_type +| @opaque_type_archetype_type +| @pack_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_fixed_array_types( //dir=type + unique int id: @builtin_fixed_array_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@local_archetype_type = + @element_archetype_type +| @opened_archetype_type +; + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +pack_archetype_types( //dir=type + unique int id: @pack_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +element_archetype_types( //dir=type + unique int id: @element_archetype_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@accessor_or_none = + @accessor +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@function_or_none = + @function +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@initializer_or_none = + @initializer +| @unspecified_element +; + +@key_path_component_or_none = + @key_path_component +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@macro_role_or_none = + @macro_role +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/swift.dbscheme b/swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/swift.dbscheme new file mode 100644 index 000000000000..4dd3d5ca8a89 --- /dev/null +++ b/swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/swift.dbscheme @@ -0,0 +1,2810 @@ +// generated by codegen/codegen.py, do not edit + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @callable +| @case_label_item +| @condition_element +| @decl +| @expr +| @key_path_component +| @macro_role +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +@callable = + @closure_expr +| @function +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +key_path_components( + unique int id: @key_path_component, + int kind: int ref, + int component_type: @type_or_none ref +); + +#keyset[id, index] +key_path_component_subscript_arguments( + int id: @key_path_component ref, + int index: int ref, + int subscript_argument: @argument_or_none ref +); + +#keyset[id] +key_path_component_tuple_indices( + int id: @key_path_component ref, + int tuple_index: int ref +); + +#keyset[id] +key_path_component_decl_refs( + int id: @key_path_component ref, + int decl_ref: @value_decl_or_none ref +); + +macro_roles( + unique int id: @macro_role, + int kind: int ref, + int macro_syntax: int ref +); + +#keyset[id, index] +macro_role_conformances( + int id: @macro_role ref, + int index: int ref, + int conformance: @expr_or_none ref +); + +#keyset[id, index] +macro_role_names( + int id: @macro_role ref, + int index: int ref, + string name: string ref +); + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +#keyset[id, index] +unspecified_element_children( + int id: @unspecified_element ref, + int index: int ref, + int child: @ast_node_or_none ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @extension_decl +| @function +| @generic_type_decl +| @macro_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_storage_decl +| @enum_element_decl +| @function +| @macro_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessors( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor: @accessor_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@function = + @accessor_or_named_function +| @deinitializer +| @initializer +; + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +macro_decls( //dir=decl + unique int id: @macro_decl, + string name: string ref +); + +#keyset[id, index] +macro_decl_parameters( //dir=decl + int id: @macro_decl ref, + int index: int ref, + int parameter: @param_decl_or_none ref +); + +#keyset[id, index] +macro_decl_roles( //dir=decl + int id: @macro_decl ref, + int index: int ref, + int role: @macro_role_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_inherited_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int inherited_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +@accessor_or_named_function = + @accessor +| @named_function +; + +deinitializers( //dir=decl + unique int id: @deinitializer +); + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +initializers( //dir=decl + unique int id: @initializer +); + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int imported_module: @module_decl_or_none ref +); + +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessors( //dir=decl + unique int id: @accessor +); + +#keyset[id] +accessor_is_getter( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_setter( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_will_set( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_did_set( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_read( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_modify( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_unsafe_address( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_unsafe_mutable_address( //dir=decl + int id: @accessor ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +named_functions( //dir=decl + unique int id: @named_function +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl, + int aliased_type: @type_or_none ref +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @closure_expr +| @collection_expr +| @consume_expr +| @copy_expr +| @current_context_isolation_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @extract_function_isolation_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initialization_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @materialize_pack_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_initializer_ref_expr +| @overloaded_decl_ref_expr +| @pack_element_expr +| @pack_expansion_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_initializer_expr +| @sequence_expr +| @single_value_stmt_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@closure_expr = + @auto_closure_expr +| @explicit_closure_expr +; + +@collection_expr = + @array_expr +| @dictionary_expr +; + +consume_exprs( //dir=expr + unique int id: @consume_expr, + int sub_expr: @expr_or_none ref +); + +copy_exprs( //dir=expr + unique int id: @copy_expr, + int sub_expr: @expr_or_none ref +); + +current_context_isolation_exprs( //dir=expr + unique int id: @current_context_isolation_expr, + int actor: @expr_or_none ref +); + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +extract_function_isolation_exprs( //dir=expr + unique int id: @extract_function_isolation_expr, + int function_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @borrow_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @actor_isolation_erasure_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unreachable_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id, index] +key_path_expr_components( //dir=expr + int id: @key_path_expr ref, + int index: int ref, + int component: @key_path_component_or_none ref +); + +lazy_initialization_exprs( //dir=expr + unique int id: @lazy_initialization_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +materialize_pack_exprs( //dir=expr + unique int id: @materialize_pack_expr, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @function_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_initializer_ref_exprs( //dir=expr + unique int id: @other_initializer_ref_expr, + int initializer: @initializer_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +pack_element_exprs( //dir=expr + unique int id: @pack_element_expr, + int sub_expr: @expr_or_none ref +); + +pack_expansion_exprs( //dir=expr + unique int id: @pack_expansion_expr, + int pattern_expr: @expr_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_initializer_exprs( //dir=expr + unique int id: @rebind_self_in_initializer_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +single_value_stmt_exprs( //dir=expr + unique int id: @single_value_stmt_expr, + int stmt: @stmt_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +actor_isolation_erasure_exprs( //dir=expr + unique int id: @actor_isolation_erasure_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +borrow_exprs( //dir=expr + unique int id: @borrow_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +explicit_closure_exprs( //dir=expr + unique int id: @explicit_closure_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @dot_syntax_call_expr +| @initializer_ref_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unreachable_exprs( //dir=expr + unique int id: @unreachable_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +initializer_ref_call_exprs( //dir=expr + unique int id: @initializer_ref_call_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +#keyset[id] +pattern_types( //dir=pattern + int id: @pattern ref, + int type_: @type_or_none ref +); + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + int var_decl: @var_decl_or_none ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @discard_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @then_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +discard_stmts( //dir=stmt + unique int id: @discard_stmt, + int sub_expr: @expr_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +then_stmts( //dir=stmt + unique int id: @then_stmt, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +for_each_stmt_variables( //dir=stmt + int id: @for_each_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +#keyset[id] +for_each_stmt_iterator_vars( //dir=stmt + int id: @for_each_stmt ref, + int iteratorVar: @pattern_binding_decl_or_none ref +); + +#keyset[id] +for_each_stmt_next_calls( //dir=stmt + int id: @for_each_stmt ref, + int nextCall: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @pack_element_type +| @pack_expansion_type +| @pack_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +pack_element_types( //dir=type + unique int id: @pack_element_type, + int pack_type: @type_or_none ref +); + +pack_expansion_types( //dir=type + unique int id: @pack_expansion_type, + int pattern_type: @type_or_none ref, + int count_type: @type_or_none ref +); + +pack_types( //dir=type + unique int id: @pack_type +); + +#keyset[id, index] +pack_type_elements( //dir=type + int id: @pack_type ref, + int index: int ref, + int element: @type_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @local_archetype_type +| @opaque_type_archetype_type +| @pack_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@local_archetype_type = + @element_archetype_type +| @opened_archetype_type +; + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +pack_archetype_types( //dir=type + unique int id: @pack_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +element_archetype_types( //dir=type + unique int id: @element_archetype_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@accessor_or_none = + @accessor +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@function_or_none = + @function +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@initializer_or_none = + @initializer +| @unspecified_element +; + +@key_path_component_or_none = + @key_path_component +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@macro_role_or_none = + @macro_role +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/upgrade.properties b/swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/upgrade.properties new file mode 100644 index 000000000000..5817523dc525 --- /dev/null +++ b/swift/downgrades/987ab0bc0911f8c88449210e21d2ee80ebcb488a/upgrade.properties @@ -0,0 +1,13 @@ +description: Add `UnsafeCastExpr`, `TypeValueExpr`, `IntegerType`, and `BuiltinFixedArrayType`. +compatibility: backwards + +builtin_fixed_array_types.rel: delete +integer_types.rel: delete +type_value_exprs.rel: delete +unsafe_cast_exprs.rel: delete + +unspecified_elements.rel: run downgrade.ql new_unspecified_elements +unspecified_element_children.rel: run downgrade.ql new_unspecified_element_children +implicit_conversion_exprs.rel: run downgrade.ql new_implicit_conversion_exprs +expr_types.rel: run downgrade.ql new_expr_types +types.rel: run downgrade.ql new_types diff --git a/swift/ql/lib/upgrades/4dd3d5ca8a89952485b3e3b2141b6bb8c22cf945/old.dbscheme b/swift/ql/lib/upgrades/4dd3d5ca8a89952485b3e3b2141b6bb8c22cf945/old.dbscheme new file mode 100644 index 000000000000..4dd3d5ca8a89 --- /dev/null +++ b/swift/ql/lib/upgrades/4dd3d5ca8a89952485b3e3b2141b6bb8c22cf945/old.dbscheme @@ -0,0 +1,2810 @@ +// generated by codegen/codegen.py, do not edit + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @callable +| @case_label_item +| @condition_element +| @decl +| @expr +| @key_path_component +| @macro_role +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +@callable = + @closure_expr +| @function +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +key_path_components( + unique int id: @key_path_component, + int kind: int ref, + int component_type: @type_or_none ref +); + +#keyset[id, index] +key_path_component_subscript_arguments( + int id: @key_path_component ref, + int index: int ref, + int subscript_argument: @argument_or_none ref +); + +#keyset[id] +key_path_component_tuple_indices( + int id: @key_path_component ref, + int tuple_index: int ref +); + +#keyset[id] +key_path_component_decl_refs( + int id: @key_path_component ref, + int decl_ref: @value_decl_or_none ref +); + +macro_roles( + unique int id: @macro_role, + int kind: int ref, + int macro_syntax: int ref +); + +#keyset[id, index] +macro_role_conformances( + int id: @macro_role ref, + int index: int ref, + int conformance: @expr_or_none ref +); + +#keyset[id, index] +macro_role_names( + int id: @macro_role ref, + int index: int ref, + string name: string ref +); + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +#keyset[id, index] +unspecified_element_children( + int id: @unspecified_element ref, + int index: int ref, + int child: @ast_node_or_none ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @extension_decl +| @function +| @generic_type_decl +| @macro_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_storage_decl +| @enum_element_decl +| @function +| @macro_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessors( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor: @accessor_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@function = + @accessor_or_named_function +| @deinitializer +| @initializer +; + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +macro_decls( //dir=decl + unique int id: @macro_decl, + string name: string ref +); + +#keyset[id, index] +macro_decl_parameters( //dir=decl + int id: @macro_decl ref, + int index: int ref, + int parameter: @param_decl_or_none ref +); + +#keyset[id, index] +macro_decl_roles( //dir=decl + int id: @macro_decl ref, + int index: int ref, + int role: @macro_role_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_inherited_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int inherited_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +@accessor_or_named_function = + @accessor +| @named_function +; + +deinitializers( //dir=decl + unique int id: @deinitializer +); + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +initializers( //dir=decl + unique int id: @initializer +); + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int imported_module: @module_decl_or_none ref +); + +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessors( //dir=decl + unique int id: @accessor +); + +#keyset[id] +accessor_is_getter( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_setter( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_will_set( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_did_set( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_read( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_modify( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_unsafe_address( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_unsafe_mutable_address( //dir=decl + int id: @accessor ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +named_functions( //dir=decl + unique int id: @named_function +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl, + int aliased_type: @type_or_none ref +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @closure_expr +| @collection_expr +| @consume_expr +| @copy_expr +| @current_context_isolation_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @extract_function_isolation_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initialization_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @materialize_pack_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_initializer_ref_expr +| @overloaded_decl_ref_expr +| @pack_element_expr +| @pack_expansion_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_initializer_expr +| @sequence_expr +| @single_value_stmt_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@closure_expr = + @auto_closure_expr +| @explicit_closure_expr +; + +@collection_expr = + @array_expr +| @dictionary_expr +; + +consume_exprs( //dir=expr + unique int id: @consume_expr, + int sub_expr: @expr_or_none ref +); + +copy_exprs( //dir=expr + unique int id: @copy_expr, + int sub_expr: @expr_or_none ref +); + +current_context_isolation_exprs( //dir=expr + unique int id: @current_context_isolation_expr, + int actor: @expr_or_none ref +); + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +extract_function_isolation_exprs( //dir=expr + unique int id: @extract_function_isolation_expr, + int function_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @borrow_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @actor_isolation_erasure_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unreachable_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id, index] +key_path_expr_components( //dir=expr + int id: @key_path_expr ref, + int index: int ref, + int component: @key_path_component_or_none ref +); + +lazy_initialization_exprs( //dir=expr + unique int id: @lazy_initialization_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +materialize_pack_exprs( //dir=expr + unique int id: @materialize_pack_expr, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @function_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_initializer_ref_exprs( //dir=expr + unique int id: @other_initializer_ref_expr, + int initializer: @initializer_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +pack_element_exprs( //dir=expr + unique int id: @pack_element_expr, + int sub_expr: @expr_or_none ref +); + +pack_expansion_exprs( //dir=expr + unique int id: @pack_expansion_expr, + int pattern_expr: @expr_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_initializer_exprs( //dir=expr + unique int id: @rebind_self_in_initializer_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +single_value_stmt_exprs( //dir=expr + unique int id: @single_value_stmt_expr, + int stmt: @stmt_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +actor_isolation_erasure_exprs( //dir=expr + unique int id: @actor_isolation_erasure_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +borrow_exprs( //dir=expr + unique int id: @borrow_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +explicit_closure_exprs( //dir=expr + unique int id: @explicit_closure_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @dot_syntax_call_expr +| @initializer_ref_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unreachable_exprs( //dir=expr + unique int id: @unreachable_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +initializer_ref_call_exprs( //dir=expr + unique int id: @initializer_ref_call_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +#keyset[id] +pattern_types( //dir=pattern + int id: @pattern ref, + int type_: @type_or_none ref +); + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + int var_decl: @var_decl_or_none ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @discard_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @then_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +discard_stmts( //dir=stmt + unique int id: @discard_stmt, + int sub_expr: @expr_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +then_stmts( //dir=stmt + unique int id: @then_stmt, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +for_each_stmt_variables( //dir=stmt + int id: @for_each_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +#keyset[id] +for_each_stmt_iterator_vars( //dir=stmt + int id: @for_each_stmt ref, + int iteratorVar: @pattern_binding_decl_or_none ref +); + +#keyset[id] +for_each_stmt_next_calls( //dir=stmt + int id: @for_each_stmt ref, + int nextCall: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @pack_element_type +| @pack_expansion_type +| @pack_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +pack_element_types( //dir=type + unique int id: @pack_element_type, + int pack_type: @type_or_none ref +); + +pack_expansion_types( //dir=type + unique int id: @pack_expansion_type, + int pattern_type: @type_or_none ref, + int count_type: @type_or_none ref +); + +pack_types( //dir=type + unique int id: @pack_type +); + +#keyset[id, index] +pack_type_elements( //dir=type + int id: @pack_type ref, + int index: int ref, + int element: @type_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @local_archetype_type +| @opaque_type_archetype_type +| @pack_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@local_archetype_type = + @element_archetype_type +| @opened_archetype_type +; + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +pack_archetype_types( //dir=type + unique int id: @pack_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +element_archetype_types( //dir=type + unique int id: @element_archetype_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@accessor_or_none = + @accessor +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@function_or_none = + @function +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@initializer_or_none = + @initializer +| @unspecified_element +; + +@key_path_component_or_none = + @key_path_component +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@macro_role_or_none = + @macro_role +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/ql/lib/upgrades/4dd3d5ca8a89952485b3e3b2141b6bb8c22cf945/swift.dbscheme b/swift/ql/lib/upgrades/4dd3d5ca8a89952485b3e3b2141b6bb8c22cf945/swift.dbscheme new file mode 100644 index 000000000000..987ab0bc0911 --- /dev/null +++ b/swift/ql/lib/upgrades/4dd3d5ca8a89952485b3e3b2141b6bb8c22cf945/swift.dbscheme @@ -0,0 +1,2832 @@ +// generated by codegen/codegen.py, do not edit + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @callable +| @case_label_item +| @condition_element +| @decl +| @expr +| @key_path_component +| @macro_role +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +@callable = + @closure_expr +| @function +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +key_path_components( + unique int id: @key_path_component, + int kind: int ref, + int component_type: @type_or_none ref +); + +#keyset[id, index] +key_path_component_subscript_arguments( + int id: @key_path_component ref, + int index: int ref, + int subscript_argument: @argument_or_none ref +); + +#keyset[id] +key_path_component_tuple_indices( + int id: @key_path_component ref, + int tuple_index: int ref +); + +#keyset[id] +key_path_component_decl_refs( + int id: @key_path_component ref, + int decl_ref: @value_decl_or_none ref +); + +macro_roles( + unique int id: @macro_role, + int kind: int ref, + int macro_syntax: int ref +); + +#keyset[id, index] +macro_role_conformances( + int id: @macro_role ref, + int index: int ref, + int conformance: @expr_or_none ref +); + +#keyset[id, index] +macro_role_names( + int id: @macro_role ref, + int index: int ref, + string name: string ref +); + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +#keyset[id, index] +unspecified_element_children( + int id: @unspecified_element ref, + int index: int ref, + int child: @ast_node_or_none ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @extension_decl +| @function +| @generic_type_decl +| @macro_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_storage_decl +| @enum_element_decl +| @function +| @macro_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessors( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor: @accessor_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@function = + @accessor_or_named_function +| @deinitializer +| @initializer +; + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +macro_decls( //dir=decl + unique int id: @macro_decl, + string name: string ref +); + +#keyset[id, index] +macro_decl_parameters( //dir=decl + int id: @macro_decl ref, + int index: int ref, + int parameter: @param_decl_or_none ref +); + +#keyset[id, index] +macro_decl_roles( //dir=decl + int id: @macro_decl ref, + int index: int ref, + int role: @macro_role_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_inherited_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int inherited_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +@accessor_or_named_function = + @accessor +| @named_function +; + +deinitializers( //dir=decl + unique int id: @deinitializer +); + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +initializers( //dir=decl + unique int id: @initializer +); + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int imported_module: @module_decl_or_none ref +); + +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessors( //dir=decl + unique int id: @accessor +); + +#keyset[id] +accessor_is_getter( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_setter( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_will_set( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_did_set( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_read( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_modify( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_unsafe_address( //dir=decl + int id: @accessor ref +); + +#keyset[id] +accessor_is_unsafe_mutable_address( //dir=decl + int id: @accessor ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +named_functions( //dir=decl + unique int id: @named_function +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl, + int aliased_type: @type_or_none ref +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @closure_expr +| @collection_expr +| @consume_expr +| @copy_expr +| @current_context_isolation_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @extract_function_isolation_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initialization_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @materialize_pack_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_initializer_ref_expr +| @overloaded_decl_ref_expr +| @pack_element_expr +| @pack_expansion_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_initializer_expr +| @sequence_expr +| @single_value_stmt_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @type_value_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@closure_expr = + @auto_closure_expr +| @explicit_closure_expr +; + +@collection_expr = + @array_expr +| @dictionary_expr +; + +consume_exprs( //dir=expr + unique int id: @consume_expr, + int sub_expr: @expr_or_none ref +); + +copy_exprs( //dir=expr + unique int id: @copy_expr, + int sub_expr: @expr_or_none ref +); + +current_context_isolation_exprs( //dir=expr + unique int id: @current_context_isolation_expr, + int actor: @expr_or_none ref +); + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +extract_function_isolation_exprs( //dir=expr + unique int id: @extract_function_isolation_expr, + int function_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @borrow_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @actor_isolation_erasure_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unreachable_expr +| @unresolved_type_conversion_expr +| @unsafe_cast_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id, index] +key_path_expr_components( //dir=expr + int id: @key_path_expr ref, + int index: int ref, + int component: @key_path_component_or_none ref +); + +lazy_initialization_exprs( //dir=expr + unique int id: @lazy_initialization_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +materialize_pack_exprs( //dir=expr + unique int id: @materialize_pack_expr, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @function_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_initializer_ref_exprs( //dir=expr + unique int id: @other_initializer_ref_expr, + int initializer: @initializer_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +pack_element_exprs( //dir=expr + unique int id: @pack_element_expr, + int sub_expr: @expr_or_none ref +); + +pack_expansion_exprs( //dir=expr + unique int id: @pack_expansion_expr, + int pattern_expr: @expr_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_initializer_exprs( //dir=expr + unique int id: @rebind_self_in_initializer_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +single_value_stmt_exprs( //dir=expr + unique int id: @single_value_stmt_expr, + int stmt: @stmt_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +type_value_exprs( //dir=expr + unique int id: @type_value_expr, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +actor_isolation_erasure_exprs( //dir=expr + unique int id: @actor_isolation_erasure_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +borrow_exprs( //dir=expr + unique int id: @borrow_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +explicit_closure_exprs( //dir=expr + unique int id: @explicit_closure_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @dot_syntax_call_expr +| @initializer_ref_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unreachable_exprs( //dir=expr + unique int id: @unreachable_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +unsafe_cast_exprs( //dir=expr + unique int id: @unsafe_cast_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +initializer_ref_call_exprs( //dir=expr + unique int id: @initializer_ref_call_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +#keyset[id] +pattern_types( //dir=pattern + int id: @pattern ref, + int type_: @type_or_none ref +); + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + int var_decl: @var_decl_or_none ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @discard_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @then_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +discard_stmts( //dir=stmt + unique int id: @discard_stmt, + int sub_expr: @expr_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +then_stmts( //dir=stmt + unique int id: @then_stmt, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +for_each_stmt_variables( //dir=stmt + int id: @for_each_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +#keyset[id] +for_each_stmt_iterator_vars( //dir=stmt + int id: @for_each_stmt ref, + int iteratorVar: @pattern_binding_decl_or_none ref +); + +#keyset[id] +for_each_stmt_next_calls( //dir=stmt + int id: @for_each_stmt ref, + int nextCall: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @integer_type +| @l_value_type +| @module_type +| @pack_element_type +| @pack_expansion_type +| @pack_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_fixed_array_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +integer_types( //dir=type + unique int id: @integer_type, + string value: string ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +pack_element_types( //dir=type + unique int id: @pack_element_type, + int pack_type: @type_or_none ref +); + +pack_expansion_types( //dir=type + unique int id: @pack_expansion_type, + int pattern_type: @type_or_none ref, + int count_type: @type_or_none ref +); + +pack_types( //dir=type + unique int id: @pack_type +); + +#keyset[id, index] +pack_type_elements( //dir=type + int id: @pack_type ref, + int index: int ref, + int element: @type_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @local_archetype_type +| @opaque_type_archetype_type +| @pack_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_fixed_array_types( //dir=type + unique int id: @builtin_fixed_array_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@local_archetype_type = + @element_archetype_type +| @opened_archetype_type +; + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +pack_archetype_types( //dir=type + unique int id: @pack_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +element_archetype_types( //dir=type + unique int id: @element_archetype_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@accessor_or_none = + @accessor +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@function_or_none = + @function +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@initializer_or_none = + @initializer +| @unspecified_element +; + +@key_path_component_or_none = + @key_path_component +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@macro_role_or_none = + @macro_role +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/ql/lib/upgrades/4dd3d5ca8a89952485b3e3b2141b6bb8c22cf945/upgrade.properties b/swift/ql/lib/upgrades/4dd3d5ca8a89952485b3e3b2141b6bb8c22cf945/upgrade.properties new file mode 100644 index 000000000000..2beb5c2591d8 --- /dev/null +++ b/swift/ql/lib/upgrades/4dd3d5ca8a89952485b3e3b2141b6bb8c22cf945/upgrade.properties @@ -0,0 +1,2 @@ +description: Add `UnsafeCastExpr`, `TypeValueExpr`, `IntegerType`, and `BuiltinFixedArrayType`. +compatibility: full From 4ca98ba816af1facfe9f6743a95fadbd38cec97f Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Fri, 18 Apr 2025 09:05:30 +0200 Subject: [PATCH 234/336] Rust: test with format! macro in a block --- .../PathResolutionConsistency.expected | 24 ++++---- .../security/CWE-089/SqlInjection.expected | 57 +++++++------------ .../test/query-tests/security/CWE-089/sqlx.rs | 6 +- 3 files changed, 38 insertions(+), 49 deletions(-) diff --git a/rust/ql/test/query-tests/security/CWE-089/CONSISTENCY/PathResolutionConsistency.expected b/rust/ql/test/query-tests/security/CWE-089/CONSISTENCY/PathResolutionConsistency.expected index 9567c4ea5177..857bfe313800 100644 --- a/rust/ql/test/query-tests/security/CWE-089/CONSISTENCY/PathResolutionConsistency.expected +++ b/rust/ql/test/query-tests/security/CWE-089/CONSISTENCY/PathResolutionConsistency.expected @@ -1,13 +1,13 @@ multipleMethodCallTargets -| sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | -| sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | -| sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | -| sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | -| sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | -| sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | -| sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | -| sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | -| sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | -| sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | -| sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | -| sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | +| sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str | diff --git a/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected b/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected index 7c3c14194747..e56e7e3ca36b 100644 --- a/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected +++ b/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected @@ -1,12 +1,10 @@ #select -| sqlx.rs:62:26:62:46 | safe_query_3.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:62:26:62:46 | safe_query_3.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | -| sqlx.rs:63:26:63:48 | unsafe_query_1.as_str() | sqlx.rs:47:22:47:35 | ...::args | sqlx.rs:63:26:63:48 | unsafe_query_1.as_str() | This query depends on a $@. | sqlx.rs:47:22:47:35 | ...::args | user-provided value | -| sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | -| sqlx.rs:67:30:67:52 | unsafe_query_4.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:67:30:67:52 | unsafe_query_4.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | -| sqlx.rs:73:25:73:45 | safe_query_3.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:73:25:73:45 | safe_query_3.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | -| sqlx.rs:74:25:74:47 | unsafe_query_1.as_str() | sqlx.rs:47:22:47:35 | ...::args | sqlx.rs:74:25:74:47 | unsafe_query_1.as_str() | This query depends on a $@. | sqlx.rs:47:22:47:35 | ...::args | user-provided value | -| sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | -| sqlx.rs:78:29:78:51 | unsafe_query_4.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:78:29:78:51 | unsafe_query_4.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | +| sqlx.rs:66:26:66:46 | safe_query_3.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:66:26:66:46 | safe_query_3.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | +| sqlx.rs:67:26:67:48 | unsafe_query_1.as_str() | sqlx.rs:47:22:47:35 | ...::args | sqlx.rs:67:26:67:48 | unsafe_query_1.as_str() | This query depends on a $@. | sqlx.rs:47:22:47:35 | ...::args | user-provided value | +| sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | +| sqlx.rs:77:25:77:45 | safe_query_3.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:77:25:77:45 | safe_query_3.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | +| sqlx.rs:78:25:78:47 | unsafe_query_1.as_str() | sqlx.rs:47:22:47:35 | ...::args | sqlx.rs:78:25:78:47 | unsafe_query_1.as_str() | This query depends on a $@. | sqlx.rs:47:22:47:35 | ...::args | user-provided value | +| sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | edges | sqlx.rs:47:9:47:18 | arg_string | sqlx.rs:53:27:53:36 | arg_string | provenance | | | sqlx.rs:47:22:47:35 | ...::args | sqlx.rs:47:22:47:37 | ...::args(...) [element] | provenance | Src:MaD:1 | @@ -15,7 +13,6 @@ edges | sqlx.rs:47:22:47:77 | ... .unwrap_or(...) | sqlx.rs:47:9:47:18 | arg_string | provenance | | | sqlx.rs:48:9:48:21 | remote_string | sqlx.rs:49:25:49:52 | remote_string.parse() [Ok] | provenance | MaD:8 | | sqlx.rs:48:9:48:21 | remote_string | sqlx.rs:54:27:54:39 | remote_string | provenance | | -| sqlx.rs:48:9:48:21 | remote_string | sqlx.rs:56:34:56:89 | MacroExpr | provenance | | | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:48:25:48:69 | ...::get(...) [Ok] | provenance | Src:MaD:2 | | sqlx.rs:48:25:48:69 | ...::get(...) [Ok] | sqlx.rs:48:25:48:78 | ... .unwrap() | provenance | MaD:6 | | sqlx.rs:48:25:48:78 | ... .unwrap() | sqlx.rs:48:25:48:85 | ... .text() [Ok] | provenance | MaD:11 | @@ -24,28 +21,21 @@ edges | sqlx.rs:49:9:49:21 | remote_number | sqlx.rs:52:32:52:87 | MacroExpr | provenance | | | sqlx.rs:49:25:49:52 | remote_string.parse() [Ok] | sqlx.rs:49:25:49:65 | ... .unwrap_or(...) | provenance | MaD:7 | | sqlx.rs:49:25:49:65 | ... .unwrap_or(...) | sqlx.rs:49:9:49:21 | remote_number | provenance | | -| sqlx.rs:52:9:52:20 | safe_query_3 | sqlx.rs:62:26:62:46 | safe_query_3.as_str() | provenance | MaD:3 | -| sqlx.rs:52:9:52:20 | safe_query_3 | sqlx.rs:73:25:73:45 | safe_query_3.as_str() | provenance | MaD:3 | +| sqlx.rs:52:9:52:20 | safe_query_3 | sqlx.rs:66:26:66:46 | safe_query_3.as_str() | provenance | MaD:3 | +| sqlx.rs:52:9:52:20 | safe_query_3 | sqlx.rs:77:25:77:45 | safe_query_3.as_str() | provenance | MaD:3 | | sqlx.rs:52:24:52:88 | res | sqlx.rs:52:32:52:87 | { ... } | provenance | | | sqlx.rs:52:32:52:87 | ...::format(...) | sqlx.rs:52:24:52:88 | res | provenance | | | sqlx.rs:52:32:52:87 | ...::must_use(...) | sqlx.rs:52:9:52:20 | safe_query_3 | provenance | | | sqlx.rs:52:32:52:87 | MacroExpr | sqlx.rs:52:32:52:87 | ...::format(...) | provenance | MaD:4 | | sqlx.rs:52:32:52:87 | { ... } | sqlx.rs:52:32:52:87 | ...::must_use(...) | provenance | MaD:9 | -| sqlx.rs:53:9:53:22 | unsafe_query_1 [&ref] | sqlx.rs:63:26:63:48 | unsafe_query_1.as_str() | provenance | MaD:3 | -| sqlx.rs:53:9:53:22 | unsafe_query_1 [&ref] | sqlx.rs:74:25:74:47 | unsafe_query_1.as_str() | provenance | MaD:3 | +| sqlx.rs:53:9:53:22 | unsafe_query_1 [&ref] | sqlx.rs:67:26:67:48 | unsafe_query_1.as_str() | provenance | MaD:3 | +| sqlx.rs:53:9:53:22 | unsafe_query_1 [&ref] | sqlx.rs:78:25:78:47 | unsafe_query_1.as_str() | provenance | MaD:3 | | sqlx.rs:53:26:53:36 | &arg_string [&ref] | sqlx.rs:53:9:53:22 | unsafe_query_1 [&ref] | provenance | | | sqlx.rs:53:27:53:36 | arg_string | sqlx.rs:53:26:53:36 | &arg_string [&ref] | provenance | | -| sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | provenance | MaD:3 | -| sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | provenance | MaD:3 | +| sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() | provenance | MaD:3 | +| sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | provenance | MaD:3 | | sqlx.rs:54:26:54:39 | &remote_string [&ref] | sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | provenance | | | sqlx.rs:54:27:54:39 | remote_string | sqlx.rs:54:26:54:39 | &remote_string [&ref] | provenance | | -| sqlx.rs:56:9:56:22 | unsafe_query_4 | sqlx.rs:67:30:67:52 | unsafe_query_4.as_str() | provenance | MaD:3 | -| sqlx.rs:56:9:56:22 | unsafe_query_4 | sqlx.rs:78:29:78:51 | unsafe_query_4.as_str() | provenance | MaD:3 | -| sqlx.rs:56:26:56:90 | res | sqlx.rs:56:34:56:89 | { ... } | provenance | | -| sqlx.rs:56:34:56:89 | ...::format(...) | sqlx.rs:56:26:56:90 | res | provenance | | -| sqlx.rs:56:34:56:89 | ...::must_use(...) | sqlx.rs:56:9:56:22 | unsafe_query_4 | provenance | | -| sqlx.rs:56:34:56:89 | MacroExpr | sqlx.rs:56:34:56:89 | ...::format(...) | provenance | MaD:4 | -| sqlx.rs:56:34:56:89 | { ... } | sqlx.rs:56:34:56:89 | ...::must_use(...) | provenance | MaD:9 | models | 1 | Source: lang:std; crate::env::args; commandargs; ReturnValue.Element | | 2 | Source: repo:https://github.com/seanmonstar/reqwest:reqwest; crate::blocking::get; remote; ReturnValue.Field[crate::result::Result::Ok(0)] | @@ -85,18 +75,13 @@ nodes | sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | semmle.label | unsafe_query_2 [&ref] | | sqlx.rs:54:26:54:39 | &remote_string [&ref] | semmle.label | &remote_string [&ref] | | sqlx.rs:54:27:54:39 | remote_string | semmle.label | remote_string | -| sqlx.rs:56:9:56:22 | unsafe_query_4 | semmle.label | unsafe_query_4 | -| sqlx.rs:56:26:56:90 | res | semmle.label | res | -| sqlx.rs:56:34:56:89 | ...::format(...) | semmle.label | ...::format(...) | -| sqlx.rs:56:34:56:89 | ...::must_use(...) | semmle.label | ...::must_use(...) | -| sqlx.rs:56:34:56:89 | MacroExpr | semmle.label | MacroExpr | -| sqlx.rs:56:34:56:89 | { ... } | semmle.label | { ... } | -| sqlx.rs:62:26:62:46 | safe_query_3.as_str() | semmle.label | safe_query_3.as_str() | -| sqlx.rs:63:26:63:48 | unsafe_query_1.as_str() | semmle.label | unsafe_query_1.as_str() | -| sqlx.rs:65:30:65:52 | unsafe_query_2.as_str() | semmle.label | unsafe_query_2.as_str() | -| sqlx.rs:67:30:67:52 | unsafe_query_4.as_str() | semmle.label | unsafe_query_4.as_str() | -| sqlx.rs:73:25:73:45 | safe_query_3.as_str() | semmle.label | safe_query_3.as_str() | -| sqlx.rs:74:25:74:47 | unsafe_query_1.as_str() | semmle.label | unsafe_query_1.as_str() | -| sqlx.rs:76:29:76:51 | unsafe_query_2.as_str() | semmle.label | unsafe_query_2.as_str() | -| sqlx.rs:78:29:78:51 | unsafe_query_4.as_str() | semmle.label | unsafe_query_4.as_str() | +| sqlx.rs:66:26:66:46 | safe_query_3.as_str() | semmle.label | safe_query_3.as_str() | +| sqlx.rs:67:26:67:48 | unsafe_query_1.as_str() | semmle.label | unsafe_query_1.as_str() | +| sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() | semmle.label | unsafe_query_2.as_str() | +| sqlx.rs:77:25:77:45 | safe_query_3.as_str() | semmle.label | safe_query_3.as_str() | +| sqlx.rs:78:25:78:47 | unsafe_query_1.as_str() | semmle.label | unsafe_query_1.as_str() | +| sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | semmle.label | unsafe_query_2.as_str() | subpaths +testFailures +| sqlx.rs:71:63:71:109 | //... | Missing result: Alert[rust/sql-injection]=remote1 | +| sqlx.rs:82:77:82:123 | //... | Missing result: Alert[rust/sql-injection]=remote1 | diff --git a/rust/ql/test/query-tests/security/CWE-089/sqlx.rs b/rust/ql/test/query-tests/security/CWE-089/sqlx.rs index f051cf49e08d..3de58350f20c 100644 --- a/rust/ql/test/query-tests/security/CWE-089/sqlx.rs +++ b/rust/ql/test/query-tests/security/CWE-089/sqlx.rs @@ -53,7 +53,11 @@ async fn test_sqlx_mysql(url: &str, enable_remote: bool) -> Result<(), sqlx::Err let unsafe_query_1 = &arg_string; let unsafe_query_2 = &remote_string; let unsafe_query_3 = String::from("SELECT * FROM people WHERE firstname='") + &remote_string + "'"; - let unsafe_query_4 = format!("SELECT * FROM people WHERE firstname='{remote_string}'"); + let unsafe_query_4 = if remote_string == "*" { + "SELECT * FROM people".to_string() + } else { + format!("SELECT * FROM people WHERE firstname='{remote_string}'") + }; let prepared_query_1 = String::from("SELECT * FROM people WHERE firstname=?"); // (prepared arguments are safe) // direct execution From 9ca6706550db248a35a10a3f278b0b779d1dd9b7 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Thu, 17 Apr 2025 18:57:26 +0200 Subject: [PATCH 235/336] Rust: make MacroStmts a CFG Expr --- rust/extractor/src/generated/.generated.list | 2 +- rust/extractor/src/generated/top.rs | 117 ++++++++++-------- rust/ql/.generated.list | 12 +- .../internal/ControlFlowGraphImpl.qll | 2 +- .../internal/generated/CfgNodes.qll | 64 ++++++++++ .../lib/codeql/rust/elements/MacroStmts.qll | 1 - .../internal/generated/MacroStmts.qll | 4 +- .../internal/generated/ParentChild.qll | 44 +++---- .../rust/elements/internal/generated/Raw.qll | 46 +++---- .../elements/internal/generated/Synth.qll | 30 ++--- rust/ql/lib/rust.dbscheme | 36 +++--- .../controlflow/BasicBlocks.expected | 8 +- .../library-tests/controlflow/Cfg.expected | 58 ++++----- .../dataflow/local/DataFlowStep.expected | 3 + .../test/library-tests/variables/Cfg.expected | 24 ++-- rust/schema/annotations.py | 6 +- 16 files changed, 267 insertions(+), 190 deletions(-) diff --git a/rust/extractor/src/generated/.generated.list b/rust/extractor/src/generated/.generated.list index 82b6665615b5..158f55acad5f 100644 --- a/rust/extractor/src/generated/.generated.list +++ b/rust/extractor/src/generated/.generated.list @@ -1,2 +1,2 @@ mod.rs 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7 -top.rs 060225ccbae440eef117e2ef0a82f3deba29e6ba2d35f00281f9c0e6a945e692 060225ccbae440eef117e2ef0a82f3deba29e6ba2d35f00281f9c0e6a945e692 +top.rs f7c07bc5a6ad3e1a3af05d16b5b448509f9f8403a510bfca1db42348d3c7038b f7c07bc5a6ad3e1a3af05d16b5b448509f9f8403a510bfca1db42348d3c7038b diff --git a/rust/extractor/src/generated/top.rs b/rust/extractor/src/generated/top.rs index caeeb7552a7d..a79bfc7bd0a6 100644 --- a/rust/extractor/src/generated/top.rs +++ b/rust/extractor/src/generated/top.rs @@ -1515,60 +1515,6 @@ impl From> for trap::Label { } } -#[derive(Debug)] -pub struct MacroStmts { - pub id: trap::TrapId, - pub expr: Option>, - pub statements: Vec>, -} - -impl trap::TrapEntry for MacroStmts { - fn extract_id(&mut self) -> trap::TrapId { - std::mem::replace(&mut self.id, trap::TrapId::Star) - } - - fn emit(self, id: trap::Label, out: &mut trap::Writer) { - out.add_tuple("macro_stmts", vec![id.into()]); - if let Some(v) = self.expr { - out.add_tuple("macro_stmts_exprs", vec![id.into(), v.into()]); - } - for (i, v) in self.statements.into_iter().enumerate() { - out.add_tuple("macro_stmts_statements", vec![id.into(), i.into(), v.into()]); - } - } -} - -impl trap::TrapClass for MacroStmts { - fn class_name() -> &'static str { "MacroStmts" } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme MacroStmts is a subclass of AstNode - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme MacroStmts is a subclass of Locatable - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme MacroStmts is a subclass of Element - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - #[derive(Debug)] pub struct MatchArm { pub id: trap::TrapId, @@ -6479,6 +6425,69 @@ impl From> for trap::Label { } } +#[derive(Debug)] +pub struct MacroStmts { + pub id: trap::TrapId, + pub expr: Option>, + pub statements: Vec>, +} + +impl trap::TrapEntry for MacroStmts { + fn extract_id(&mut self) -> trap::TrapId { + std::mem::replace(&mut self.id, trap::TrapId::Star) + } + + fn emit(self, id: trap::Label, out: &mut trap::Writer) { + out.add_tuple("macro_stmts", vec![id.into()]); + if let Some(v) = self.expr { + out.add_tuple("macro_stmts_exprs", vec![id.into(), v.into()]); + } + for (i, v) in self.statements.into_iter().enumerate() { + out.add_tuple("macro_stmts_statements", vec![id.into(), i.into(), v.into()]); + } + } +} + +impl trap::TrapClass for MacroStmts { + fn class_name() -> &'static str { "MacroStmts" } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme MacroStmts is a subclass of Expr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme MacroStmts is a subclass of AstNode + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme MacroStmts is a subclass of Locatable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme MacroStmts is a subclass of Element + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + #[derive(Debug)] pub struct MacroTypeRepr { pub id: trap::TrapId, diff --git a/rust/ql/.generated.list b/rust/ql/.generated.list index 0ff3e721e231..bc447c524e86 100644 --- a/rust/ql/.generated.list +++ b/rust/ql/.generated.list @@ -1,4 +1,4 @@ -lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll d1cc3cfc9ae558b1cb473e3bfca66e5c424445b98ce343eb6f3050321fe4f8a0 8d00e385230b45360bc6281af01e0f674c58117593fd1b3cb7eb0c8a45517542 +lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll 08d3062aa600c5dceba897f067b1142a382b7a342acc9f7e7548b0b9df0dab36 b9bc250dbd89e95bf8fd12eacfa725ad1b50ac644599da6100cff33adfb8a18e lib/codeql/rust/elements/Abi.qll 4c973d28b6d628f5959d1f1cc793704572fd0acaae9a97dfce82ff9d73f73476 250f68350180af080f904cd34cb2af481c5c688dc93edf7365fd0ae99855e893 lib/codeql/rust/elements/Addressable.qll 13011bfd2e1556694c3d440cc34af8527da4df49ad92b62f2939d3699ff2cea5 ddb25935f7553a1a384b1abe2e4b4fa90ab50b952dadec32fd867afcb054f4be lib/codeql/rust/elements/ArgList.qll 661f5100f5d3ef8351452d9058b663a2a5c720eea8cf11bedd628969741486a2 28e424aac01a90fb58cd6f9f83c7e4cf379eea39e636bc0ba07efc818be71c71 @@ -95,7 +95,7 @@ lib/codeql/rust/elements/MacroExpr.qll ea9fed13f610bab1a2c4541c994510e0cb806530b lib/codeql/rust/elements/MacroItems.qll 00a5d41f7bb836d952abbd9382e42f72a9d81e65646a15a460b35ccd07a866c6 00efdb4d701b5599d76096f740da9ec157804865267b7e29bc2a214cbf03763e lib/codeql/rust/elements/MacroPat.qll dbf193b4fb544ac0b5a7dcfc31a6652de7239b6e643ff15b05868b2c142e940c 19b45c0a1eb1198e450c05d564b5d4aa0d6da29e7db84b9521eadf901e20a932 lib/codeql/rust/elements/MacroRules.qll a94535506798077043b9c1470992ac4310bf67bcce5f722080886d1b3e6d90d1 bd8e08a7171991abc85100b45267631e66d1b332caf1e5882cd17caee5cf18a3 -lib/codeql/rust/elements/MacroStmts.qll 6e9a1f90231cb72b27d3ff9479e399a9fba4abd0872a5005ab2fac45d5ca9be0 d6ca3a8254fc45794a93c451a3305c9b4be033a467ad72158d40d6f675a377a0 +lib/codeql/rust/elements/MacroStmts.qll 02c4e34d266d4564ea0433a3d6186402db516dc2dd9017d7c769a76300c2286d f4517fb9fea2ea64d4f2c1998a6899d2452878000ed6f8f31c5106ef0fb6783a lib/codeql/rust/elements/MacroTypeRepr.qll 92fa5f6d20cce8fa3f2b4b823a8a77fdb7c11f2c2b12b8f900828c3a54eca334 51289f2622d1bb58d9a093255da2c05084a0b184f02e69e2526ec7fefdfdfd75 lib/codeql/rust/elements/MatchArm.qll c39fd6cc0da24b1ff8d1e42835bcfee7695ad13580e3c7c50acd7c881b1cd894 62a31d2bd125e6aaebefc406e541a641271d3c497a377959f94dd4735b2bfbf8 lib/codeql/rust/elements/MatchArmList.qll e6c48fd7419d88e996b82eb45e4aa2686dfd079b283b02be7710192fb2cb93a0 0ec63a0ca56f5f7f80093fd3e77b198b74c6289e67be55dc6a4deb610753c7bd @@ -557,7 +557,7 @@ lib/codeql/rust/elements/internal/generated/MacroExpr.qll 03a1daa41866f51e479ac2 lib/codeql/rust/elements/internal/generated/MacroItems.qll 894890f61e118b3727d03ca813ae7220a15e45195f2d1d059cb1bba6802128c8 db3854b347f8782a3ec9f9a1439da822727b66f0bd33727383184ab65dbf29ac lib/codeql/rust/elements/internal/generated/MacroPat.qll 26bc55459a66359ad83ed7b25284a25cdbd48a868fd1bbf7e23e18b449395c43 f16ede334becba951873e585c52a3a9873c9251e3dab9a3c1a1681f632f2079f lib/codeql/rust/elements/internal/generated/MacroRules.qll 4fbd94f22b5ee0f3e5aaae39c2b9a5e9b7bf878a1017811ca589942f6de92843 49fb69543ee867bae196febea6918e621f335afdf4d3ccbf219965b37c7537b1 -lib/codeql/rust/elements/internal/generated/MacroStmts.qll cb4f3c2721a4d0c8522e51f567c675f4fc95f39bac8a2bd97e125d5553515ad2 09b5a739ccee75e6c556b34ecd6f78c7dc799029d9bc7df2e6169098d24f0ccd +lib/codeql/rust/elements/internal/generated/MacroStmts.qll d19f8b925d3b926c94e3d17c71aa4500899ec3cdd22c7e3428444e7e8e70bf97 69e64fc2089d6109de012956d1e9ddd86d468bb132e9b562efc06f359b00b0e7 lib/codeql/rust/elements/internal/generated/MacroTypeRepr.qll 4242e253fa36ee3f7d9d0677811ff5bc4ecfb02c76d768446a6a6dcd38061f68 a676632f3bb83142a0838601ae2a582d5c32d7939e4261eb8fccf3962bb06cb2 lib/codeql/rust/elements/internal/generated/MatchArm.qll f8c4c955c50f8398159c492d9d0a74f7b71e9510fcb8a3aab1d06e0f7e15b263 713939c7ef77ca73d95788096163c26213ab49f34ed41c6f4bc09a1ef9607b0d lib/codeql/rust/elements/internal/generated/MatchArmList.qll 13362680c037fe83fef4653562cc10a4429078316b5ec7c47b076336cf4aca2e 41c674293c13eceaca62134ae0c6778541f6a5201cbc5c146f0ba01b898dc267 @@ -579,7 +579,7 @@ lib/codeql/rust/elements/internal/generated/ParamList.qll c808c9d84dd7800573832b lib/codeql/rust/elements/internal/generated/ParenExpr.qll bc0731505bfe88516205ec360582a4222d2681d11342c93e15258590ddee82f2 d4bd6e0c80cf1d63746c88d4bcb3a01d4c75732e5da09e3ebd9437ced227fb60 lib/codeql/rust/elements/internal/generated/ParenPat.qll 4f168ef5d5bb87a903251cc31b2e44a759b099ec69c90af31783fbb15778c940 0e34f94a45a13396fd57d94c245dc64d1adde2ab0e22b56946f7e94c04e297fc lib/codeql/rust/elements/internal/generated/ParenTypeRepr.qll 40ab5c592e7699c621787793743e33988de71ff42ca27599f5ab3ddb70e3f7d8 12c0a6eed2202ee3e892f61da3b3ce77ac3190854cdf3097e8d2be98aa3cb91d -lib/codeql/rust/elements/internal/generated/ParentChild.qll d1770632e8d0c649ebcbcab9cbc653531ecf521bbf5d891941db8c0927ae6796 fb40a76aff319ec5f7dae9a05da083b337887b0918b3702641b39342213ddf6f +lib/codeql/rust/elements/internal/generated/ParentChild.qll 27c4e9351e8dcf0290a5959b634c15398196b312e75f7ef4716e7c56090a90aa 99b4716d995792105d1a20300f8710d3ae26ca59f3a0db076114509d8bdab85e lib/codeql/rust/elements/internal/generated/ParenthesizedArgList.qll c5fa328ea60d3a3333d7c7bb3480969c1873166c7ac8ebb9d0afad7a8099d1a8 2dbbb6200d96f7db7dea4a55bdeab8d67b14d39a43e0bd54ada019f7e466f163 lib/codeql/rust/elements/internal/generated/Pat.qll 3605ac062be2f294ee73336e9669027b8b655f4ad55660e1eab35266275154ee 7f9400db2884d336dd1d21df2a8093759c2a110be9bf6482ce8e80ae0fd74ed4 lib/codeql/rust/elements/internal/generated/Path.qll 9b12afb46fc5a9ad3a811b05472621bbecccb900c47504feb7f29d96b28421ca bcacbffc36fb3e0c9b26523b5963af0ffa9fd6b19f00a2a31bdb2316071546bd @@ -594,7 +594,7 @@ lib/codeql/rust/elements/internal/generated/PtrTypeRepr.qll 51d1e9e683fc79dddbff lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f lib/codeql/rust/elements/internal/generated/RangeExpr.qll 23cca03bf43535f33b22a38894f70d669787be4e4f5b8fe5c8f7b964d30e9027 18624cef6c6b679eeace2a98737e472432e0ead354cca02192b4d45330f047c9 lib/codeql/rust/elements/internal/generated/RangePat.qll 80826a6a6868a803aa2372e31c52a03e1811a3f1f2abdb469f91ca0bfdd9ecb6 34ee1e208c1690cba505dff2c588837c0cd91e185e2a87d1fe673191962276a9 -lib/codeql/rust/elements/internal/generated/Raw.qll 6e33d9fa21ee3287a0ebc27856a09f4fdc4d587b5a31ff1c4337106de7ca1a2e eece38e6accb6b9d8838fd05edd7cbaf6f7ee37190adbef2b023ad91064d1622 +lib/codeql/rust/elements/internal/generated/Raw.qll 8aaa20dd4d49220f3eff2ac64f7a8d34f343d198b59785a06922c3642322e056 3d14ea25f0ad20af1bfb1b8e3e0e5fba9f1a1f764132c0d42972e08893ebd31b lib/codeql/rust/elements/internal/generated/RefExpr.qll 7d995884e3dc1c25fc719f5d7253179344d63650e217e9ff6530285fe7a57f64 f2c3c12551deea4964b66553fb9b6423ee16fec53bd63db4796191aa60dc6c66 lib/codeql/rust/elements/internal/generated/RefPat.qll 456ede39837463ee22a630ec7ab6c8630d3664a8ea206fcc6e4f199e92fa564c 5622062765f32930465ba6b170e986706f159f6070f48adee3c20e24e8df4e05 lib/codeql/rust/elements/internal/generated/RefTypeRepr.qll 3d8c0bd296d33b91a81633f697a43269a6538df06d277262d3990d3f6880ef57 13680f39e89bcd8299c218aba396f3deec804597e6f7cb7d4a7e7c748b6faa77 @@ -620,7 +620,7 @@ lib/codeql/rust/elements/internal/generated/StructFieldList.qll 8911a44217d091b0 lib/codeql/rust/elements/internal/generated/StructPat.qll c76fa005c2fd0448a8803233e1e8818c4123301eb66ac5cf69d0b9eaafc61e98 6e0dffccdce24bca20e87d5ba0f0995c9a1ae8983283e71e7dbfcf6fffc67a58 lib/codeql/rust/elements/internal/generated/StructPatField.qll 5b5c7302dbc4a902ca8e69ff31875c867e295a16a626ba3cef29cd0aa248f179 4e192a0df79947f5cb0d47fdbbba7986137a6a40a1be92ae119873e2fad67edf lib/codeql/rust/elements/internal/generated/StructPatFieldList.qll e34c003e660ba059ba81bb73b3c8d21bd2a47d0251569c46277dc9ccf2947b0a 85113f35ba5f6b9e01ad4072246a4de1ac0e4528348ac564868e96f34a3e09e2 -lib/codeql/rust/elements/internal/generated/Synth.qll 409b9ae5c78f47f271eb05a9eb7043df6cd6ca35ce381843714667f1f2dfdf9a aa4d5082abccd7cd47a493447eea79b0a3ff81439c333f05087030e76f0fa8e5 +lib/codeql/rust/elements/internal/generated/Synth.qll e35b960eeea21a70c94bd81001357fd18b1ecccef0a7b514e2a64e9091db21a2 319b9fa102d87d93d2157cd0fe7b5934d0892185e740d98b50c44cc5e99a4cd6 lib/codeql/rust/elements/internal/generated/SynthConstructors.qll fe007cf6eab5f0cf89ea1ea91e1f9b23e0fcf0f2872f52ef352584503f90aa29 fe007cf6eab5f0cf89ea1ea91e1f9b23e0fcf0f2872f52ef352584503f90aa29 lib/codeql/rust/elements/internal/generated/Token.qll 77a91a25ca5669703cf3a4353b591cef4d72caa6b0b9db07bb9e005d69c848d1 2fdffc4882ed3a6ca9ac6d1fb5f1ac5a471ca703e2ffdc642885fa558d6e373b lib/codeql/rust/elements/internal/generated/TokenTree.qll 8577c2b097c1be2f0f7daa5acfcf146f78674a424d99563e08a84dd3e6d91b46 d2f30764e84dbfc0a6a5d3d8a5f935cd432413688cb32da9c94e420fbc10665c diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll index 900580914e2f..298d7e49438a 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll @@ -146,7 +146,7 @@ class MacroCallTree extends StandardPostOrderTree, MacroCall { override AstNode getChildNode(int i) { i = 0 and result = this.getExpanded() } } -class MacroStmtsTree extends StandardPreOrderTree, MacroStmts { +class MacroStmtsTree extends StandardPostOrderTree, MacroStmts { override AstNode getChildNode(int i) { result = this.getStatement(i) or diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll b/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll index 12ef6847b821..34ccb8d23818 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll @@ -1900,6 +1900,58 @@ module MakeCfgNodes Input> { predicate hasMacroCall() { exists(this.getMacroCall()) } } + final private class ParentMacroStmts extends ParentAstNode, MacroStmts { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A sequence of statements generated by a `MacroCall`. For example: + * ```rust + * fn main() { + * println!("Hello, world!"); // This macro expands into a list of statements + * } + * ``` + */ + final class MacroStmtsCfgNode extends CfgNodeFinal, ExprCfgNode { + private MacroStmts node; + + MacroStmtsCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `MacroStmts`. */ + MacroStmts getMacroStmts() { result = node } + + /** + * Gets the expression of this macro statements, if it exists. + */ + ExprCfgNode getExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result) + } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + + /** + * Gets the `index`th statement of this macro statements (0-based). + */ + Stmt getStatement(int index) { result = node.getStatement(index) } + + /** + * Gets any of the statements of this macro statements. + */ + Stmt getAStatement() { result = this.getStatement(_) } + + /** + * Gets the number of statements of this macro statements. + */ + int getNumberOfStatements() { result = count(int i | exists(this.getStatement(i))) } + } + final private class ParentMatchExpr extends ParentAstNode, MatchExpr { override predicate relevantChild(AstNode child) { none() @@ -3723,6 +3775,18 @@ module MakeCfgNodes Input> { cfgNode ) or + pred = "getExpr" and + parent = + any(Nodes::MacroStmtsCfgNode cfgNode, MacroStmts astNode | + astNode = cfgNode.getMacroStmts() and + child = getDesugared(astNode.getExpr()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or pred = "getScrutinee" and parent = any(Nodes::MatchExprCfgNode cfgNode, MatchExpr astNode | diff --git a/rust/ql/lib/codeql/rust/elements/MacroStmts.qll b/rust/ql/lib/codeql/rust/elements/MacroStmts.qll index 77416d936995..9ef0c12b35fd 100644 --- a/rust/ql/lib/codeql/rust/elements/MacroStmts.qll +++ b/rust/ql/lib/codeql/rust/elements/MacroStmts.qll @@ -4,7 +4,6 @@ */ private import internal.MacroStmtsImpl -import codeql.rust.elements.AstNode import codeql.rust.elements.Expr import codeql.rust.elements.Stmt diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/MacroStmts.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/MacroStmts.qll index e80debcb27dc..636e0d1ea091 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/MacroStmts.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/MacroStmts.qll @@ -6,8 +6,8 @@ private import codeql.rust.elements.internal.generated.Synth private import codeql.rust.elements.internal.generated.Raw -import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl import codeql.rust.elements.Expr +import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl import codeql.rust.elements.Stmt /** @@ -25,7 +25,7 @@ module Generated { * INTERNAL: Do not reference the `Generated::MacroStmts` class directly. * Use the subclass `MacroStmts`, where the following predicates are available. */ - class MacroStmts extends Synth::TMacroStmts, AstNodeImpl::AstNode { + class MacroStmts extends Synth::TMacroStmts, ExprImpl::Expr { override string getAPrimaryQlClass() { result = "MacroStmts" } /** diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll index 4268ef3f8409..57e18e373b8a 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll @@ -616,26 +616,6 @@ private module Impl { ) } - private Element getImmediateChildOfMacroStmts(MacroStmts e, int index, string partialPredicateCall) { - exists(int b, int bAstNode, int n, int nExpr, int nStatement | - b = 0 and - bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and - n = bAstNode and - nExpr = n + 1 and - nStatement = nExpr + 1 + max(int i | i = -1 or exists(e.getStatement(i)) | i) and - ( - none() - or - result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall) - or - index = n and result = e.getExpr() and partialPredicateCall = "Expr()" - or - result = e.getStatement(index - nExpr) and - partialPredicateCall = "Statement(" + (index - nExpr).toString() + ")" - ) - ) - } - private Element getImmediateChildOfMatchArm(MatchArm e, int index, string partialPredicateCall) { exists(int b, int bAstNode, int n, int nAttr, int nExpr, int nGuard, int nPat | b = 0 and @@ -2420,6 +2400,26 @@ private module Impl { ) } + private Element getImmediateChildOfMacroStmts(MacroStmts e, int index, string partialPredicateCall) { + exists(int b, int bExpr, int n, int nExpr, int nStatement | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nExpr = n + 1 and + nStatement = nExpr + 1 + max(int i | i = -1 or exists(e.getStatement(i)) | i) and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getExpr() and partialPredicateCall = "Expr()" + or + result = e.getStatement(index - nExpr) and + partialPredicateCall = "Statement(" + (index - nExpr).toString() + ")" + ) + ) + } + private Element getImmediateChildOfMacroTypeRepr( MacroTypeRepr e, int index, string partialPredicateCall ) { @@ -4156,8 +4156,6 @@ private module Impl { or result = getImmediateChildOfMacroItems(e, index, partialAccessor) or - result = getImmediateChildOfMacroStmts(e, index, partialAccessor) - or result = getImmediateChildOfMatchArm(e, index, partialAccessor) or result = getImmediateChildOfMatchArmList(e, index, partialAccessor) @@ -4304,6 +4302,8 @@ private module Impl { or result = getImmediateChildOfMacroPat(e, index, partialAccessor) or + result = getImmediateChildOfMacroStmts(e, index, partialAccessor) + or result = getImmediateChildOfMacroTypeRepr(e, index, partialAccessor) or result = getImmediateChildOfMatchExpr(e, index, partialAccessor) diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll index 3bd57ae98620..b1e26574de14 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll @@ -502,29 +502,6 @@ module Raw { Item getItem(int index) { macro_items_items(this, index, result) } } - /** - * INTERNAL: Do not use. - * A sequence of statements generated by a `MacroCall`. For example: - * ```rust - * fn main() { - * println!("Hello, world!"); // This macro expands into a list of statements - * } - * ``` - */ - class MacroStmts extends @macro_stmts, AstNode { - override string toString() { result = "MacroStmts" } - - /** - * Gets the expression of this macro statements, if it exists. - */ - Expr getExpr() { macro_stmts_exprs(this, result) } - - /** - * Gets the `index`th statement of this macro statements (0-based). - */ - Stmt getStatement(int index) { macro_stmts_statements(this, index, result) } - } - /** * INTERNAL: Do not use. * A match arm. For example: @@ -2401,6 +2378,29 @@ module Raw { MacroCall getMacroCall() { macro_pat_macro_calls(this, result) } } + /** + * INTERNAL: Do not use. + * A sequence of statements generated by a `MacroCall`. For example: + * ```rust + * fn main() { + * println!("Hello, world!"); // This macro expands into a list of statements + * } + * ``` + */ + class MacroStmts extends @macro_stmts, Expr { + override string toString() { result = "MacroStmts" } + + /** + * Gets the expression of this macro statements, if it exists. + */ + Expr getExpr() { macro_stmts_exprs(this, result) } + + /** + * Gets the `index`th statement of this macro statements (0-based). + */ + Stmt getStatement(int index) { macro_stmts_statements(this, index, result) } + } + /** * INTERNAL: Do not use. * A MacroTypeRepr. For example: diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll index 6d7c69fde132..abc696eb51e8 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll @@ -716,14 +716,14 @@ module Synth { TAsmOption or TAsmPiece or TAsmRegSpec or TAssocItem or TAssocItemList or TAttr or TCallable or TClosureBinder or TExpr or TExternItem or TExternItemList or TFieldList or TFormatArgsArg or TGenericArg or TGenericArgList or TGenericParam or TGenericParamList or - TItemList or TLabel or TLetElse or TMacroItems or TMacroStmts or TMatchArm or - TMatchArmList or TMatchGuard or TMeta or TName or TParamBase or TParamList or - TParenthesizedArgList or TPat or TPath or TPathSegment or TRename or TResolvable or - TRetTypeRepr or TReturnTypeSyntax or TSourceFile or TStmt or TStmtList or - TStructExprField or TStructExprFieldList or TStructField or TStructPatField or - TStructPatFieldList or TToken or TTokenTree or TTupleField or TTypeBound or - TTypeBoundList or TTypeRepr or TUseBoundGenericArg or TUseBoundGenericArgs or TUseTree or - TUseTreeList or TVariantDef or TVariantList or TVisibility or TWhereClause or TWherePred; + TItemList or TLabel or TLetElse or TMacroItems or TMatchArm or TMatchArmList or + TMatchGuard or TMeta or TName or TParamBase or TParamList or TParenthesizedArgList or + TPat or TPath or TPathSegment or TRename or TResolvable or TRetTypeRepr or + TReturnTypeSyntax or TSourceFile or TStmt or TStmtList or TStructExprField or + TStructExprFieldList or TStructField or TStructPatField or TStructPatFieldList or TToken or + TTokenTree or TTupleField or TTypeBound or TTypeBoundList or TTypeRepr or + TUseBoundGenericArg or TUseBoundGenericArgs or TUseTree or TUseTreeList or TVariantDef or + TVariantList or TVisibility or TWhereClause or TWherePred; /** * INTERNAL: Do not use. @@ -742,9 +742,9 @@ module Synth { TArrayExpr or TArrayExprInternal or TAsmExpr or TAwaitExpr or TBecomeExpr or TBinaryExpr or TBreakExpr or TCallExprBase or TCastExpr or TClosureExpr or TContinueExpr or TFieldExpr or TFormatArgsExpr or TIfExpr or TIndexExpr or TLabelableExpr or TLetExpr or TLiteralExpr or - TMacroExpr or TMatchExpr or TOffsetOfExpr or TParenExpr or TPathExprBase or TPrefixExpr or - TRangeExpr or TRefExpr or TReturnExpr or TStructExpr or TTryExpr or TTupleExpr or - TUnderscoreExpr or TYeetExpr or TYieldExpr; + TMacroExpr or TMacroStmts or TMatchExpr or TOffsetOfExpr or TParenExpr or TPathExprBase or + TPrefixExpr or TRangeExpr or TRefExpr or TReturnExpr or TStructExpr or TTryExpr or + TTupleExpr or TUnderscoreExpr or TYeetExpr or TYieldExpr; /** * INTERNAL: Do not use. @@ -1973,8 +1973,6 @@ module Synth { or result = convertMacroItemsFromRaw(e) or - result = convertMacroStmtsFromRaw(e) - or result = convertMatchArmFromRaw(e) or result = convertMatchArmListFromRaw(e) @@ -2129,6 +2127,8 @@ module Synth { or result = convertMacroExprFromRaw(e) or + result = convertMacroStmtsFromRaw(e) + or result = convertMatchExprFromRaw(e) or result = convertOffsetOfExprFromRaw(e) @@ -3573,8 +3573,6 @@ module Synth { or result = convertMacroItemsToRaw(e) or - result = convertMacroStmtsToRaw(e) - or result = convertMatchArmToRaw(e) or result = convertMatchArmListToRaw(e) @@ -3729,6 +3727,8 @@ module Synth { or result = convertMacroExprToRaw(e) or + result = convertMacroStmtsToRaw(e) + or result = convertMatchExprToRaw(e) or result = convertOffsetOfExprToRaw(e) diff --git a/rust/ql/lib/rust.dbscheme b/rust/ql/lib/rust.dbscheme index e8707b675dc5..48a13c5eec36 100644 --- a/rust/ql/lib/rust.dbscheme +++ b/rust/ql/lib/rust.dbscheme @@ -182,7 +182,6 @@ named_crates( | @label | @let_else | @macro_items -| @macro_stmts | @match_arm | @match_arm_list | @match_guard @@ -439,6 +438,7 @@ closure_binder_generic_param_lists( | @let_expr | @literal_expr | @macro_expr +| @macro_stmts | @match_expr | @offset_of_expr | @paren_expr @@ -585,23 +585,6 @@ macro_items_items( int item: @item ref ); -macro_stmts( - unique int id: @macro_stmts -); - -#keyset[id] -macro_stmts_exprs( - int id: @macro_stmts ref, - int expr: @expr ref -); - -#keyset[id, index] -macro_stmts_statements( - int id: @macro_stmts ref, - int index: int ref, - int statement: @stmt ref -); - match_arms( unique int id: @match_arm ); @@ -2118,6 +2101,23 @@ macro_pat_macro_calls( int macro_call: @macro_call ref ); +macro_stmts( + unique int id: @macro_stmts +); + +#keyset[id] +macro_stmts_exprs( + int id: @macro_stmts ref, + int expr: @expr ref +); + +#keyset[id, index] +macro_stmts_statements( + int id: @macro_stmts ref, + int index: int ref, + int statement: @stmt ref +); + macro_type_reprs( unique int id: @macro_type_repr ); diff --git a/rust/ql/test/library-tests/controlflow/BasicBlocks.expected b/rust/ql/test/library-tests/controlflow/BasicBlocks.expected index d5d978b9f52a..2b87a4996b17 100644 --- a/rust/ql/test/library-tests/controlflow/BasicBlocks.expected +++ b/rust/ql/test/library-tests/controlflow/BasicBlocks.expected @@ -560,9 +560,9 @@ dominates | test.rs:355:13:355:22 | Err(...) | test.rs:355:13:355:22 | Err(...) | | test.rs:362:5:365:5 | enter fn test_let_match | test.rs:362:5:365:5 | enter fn test_let_match | | test.rs:362:5:365:5 | enter fn test_let_match | test.rs:363:18:363:18 | n | -| test.rs:362:5:365:5 | enter fn test_let_match | test.rs:363:39:363:53 | MacroStmts | +| test.rs:362:5:365:5 | enter fn test_let_match | test.rs:363:39:363:53 | ExprStmt | | test.rs:363:18:363:18 | n | test.rs:363:18:363:18 | n | -| test.rs:363:39:363:53 | MacroStmts | test.rs:363:39:363:53 | MacroStmts | +| test.rs:363:39:363:53 | ExprStmt | test.rs:363:39:363:53 | ExprStmt | | test.rs:367:5:373:5 | enter fn test_let_with_return | test.rs:367:5:373:5 | enter fn test_let_with_return | | test.rs:367:5:373:5 | enter fn test_let_with_return | test.rs:367:5:373:5 | exit fn test_let_with_return (normal) | | test.rs:367:5:373:5 | enter fn test_let_with_return | test.rs:369:18:369:20 | ret | @@ -1258,7 +1258,7 @@ postDominance | test.rs:362:5:365:5 | enter fn test_let_match | test.rs:362:5:365:5 | enter fn test_let_match | | test.rs:363:18:363:18 | n | test.rs:362:5:365:5 | enter fn test_let_match | | test.rs:363:18:363:18 | n | test.rs:363:18:363:18 | n | -| test.rs:363:39:363:53 | MacroStmts | test.rs:363:39:363:53 | MacroStmts | +| test.rs:363:39:363:53 | ExprStmt | test.rs:363:39:363:53 | ExprStmt | | test.rs:367:5:373:5 | enter fn test_let_with_return | test.rs:367:5:373:5 | enter fn test_let_with_return | | test.rs:367:5:373:5 | exit fn test_let_with_return (normal) | test.rs:367:5:373:5 | enter fn test_let_with_return | | test.rs:367:5:373:5 | exit fn test_let_with_return (normal) | test.rs:367:5:373:5 | exit fn test_let_with_return (normal) | @@ -1629,7 +1629,7 @@ immediateDominator | test.rs:354:16:354:20 | value | test.rs:352:5:357:5 | enter fn test_match_with_no_arms | | test.rs:355:13:355:22 | Err(...) | test.rs:352:5:357:5 | enter fn test_match_with_no_arms | | test.rs:363:18:363:18 | n | test.rs:362:5:365:5 | enter fn test_let_match | -| test.rs:363:39:363:53 | MacroStmts | test.rs:362:5:365:5 | enter fn test_let_match | +| test.rs:363:39:363:53 | ExprStmt | test.rs:362:5:365:5 | enter fn test_let_match | | test.rs:367:5:373:5 | exit fn test_let_with_return (normal) | test.rs:367:5:373:5 | enter fn test_let_with_return | | test.rs:369:18:369:20 | ret | test.rs:367:5:373:5 | enter fn test_let_with_return | | test.rs:370:13:370:16 | None | test.rs:367:5:373:5 | enter fn test_let_with_return | diff --git a/rust/ql/test/library-tests/controlflow/Cfg.expected b/rust/ql/test/library-tests/controlflow/Cfg.expected index 1705b88e3d75..0b79e26e95a7 100644 --- a/rust/ql/test/library-tests/controlflow/Cfg.expected +++ b/rust/ql/test/library-tests/controlflow/Cfg.expected @@ -391,40 +391,40 @@ edges | test.rs:171:17:171:29 | ...::_print | test.rs:171:26:171:28 | "1\\n" | | | test.rs:171:17:171:29 | MacroExpr | test.rs:170:22:172:13 | { ... } | | | test.rs:171:17:171:29 | println!... | test.rs:171:17:171:29 | MacroExpr | | -| test.rs:171:17:171:30 | ExprStmt | test.rs:171:26:171:28 | MacroStmts | | +| test.rs:171:17:171:30 | ExprStmt | test.rs:171:26:171:28 | ExprStmt | | | test.rs:171:26:171:28 | "1\\n" | test.rs:171:26:171:28 | FormatArgsExpr | | | test.rs:171:26:171:28 | ...::_print(...) | test.rs:171:26:171:28 | { ... } | | | test.rs:171:26:171:28 | ...::format_args_nl!... | test.rs:171:26:171:28 | MacroExpr | | | test.rs:171:26:171:28 | ExprStmt | test.rs:171:17:171:29 | ...::_print | | | test.rs:171:26:171:28 | FormatArgsExpr | test.rs:171:26:171:28 | ...::format_args_nl!... | | | test.rs:171:26:171:28 | MacroExpr | test.rs:171:26:171:28 | ...::_print(...) | | -| test.rs:171:26:171:28 | MacroStmts | test.rs:171:26:171:28 | ExprStmt | | -| test.rs:171:26:171:28 | { ... } | test.rs:171:17:171:29 | println!... | | +| test.rs:171:26:171:28 | MacroStmts | test.rs:171:17:171:29 | println!... | | +| test.rs:171:26:171:28 | { ... } | test.rs:171:26:171:28 | MacroStmts | | | test.rs:172:20:174:13 | { ... } | test.rs:170:13:174:13 | if cond2 {...} else {...} | | | test.rs:173:17:173:29 | ...::_print | test.rs:173:26:173:28 | "2\\n" | | | test.rs:173:17:173:29 | MacroExpr | test.rs:172:20:174:13 | { ... } | | | test.rs:173:17:173:29 | println!... | test.rs:173:17:173:29 | MacroExpr | | -| test.rs:173:17:173:30 | ExprStmt | test.rs:173:26:173:28 | MacroStmts | | +| test.rs:173:17:173:30 | ExprStmt | test.rs:173:26:173:28 | ExprStmt | | | test.rs:173:26:173:28 | "2\\n" | test.rs:173:26:173:28 | FormatArgsExpr | | | test.rs:173:26:173:28 | ...::_print(...) | test.rs:173:26:173:28 | { ... } | | | test.rs:173:26:173:28 | ...::format_args_nl!... | test.rs:173:26:173:28 | MacroExpr | | | test.rs:173:26:173:28 | ExprStmt | test.rs:173:17:173:29 | ...::_print | | | test.rs:173:26:173:28 | FormatArgsExpr | test.rs:173:26:173:28 | ...::format_args_nl!... | | | test.rs:173:26:173:28 | MacroExpr | test.rs:173:26:173:28 | ...::_print(...) | | -| test.rs:173:26:173:28 | MacroStmts | test.rs:173:26:173:28 | ExprStmt | | -| test.rs:173:26:173:28 | { ... } | test.rs:173:17:173:29 | println!... | | +| test.rs:173:26:173:28 | MacroStmts | test.rs:173:17:173:29 | println!... | | +| test.rs:173:26:173:28 | { ... } | test.rs:173:26:173:28 | MacroStmts | | | test.rs:175:13:175:25 | ...::_print | test.rs:175:22:175:24 | "3\\n" | | | test.rs:175:13:175:25 | MacroExpr | test.rs:169:18:176:9 | { ... } | | | test.rs:175:13:175:25 | println!... | test.rs:175:13:175:25 | MacroExpr | | -| test.rs:175:13:175:26 | ExprStmt | test.rs:175:22:175:24 | MacroStmts | | +| test.rs:175:13:175:26 | ExprStmt | test.rs:175:22:175:24 | ExprStmt | | | test.rs:175:22:175:24 | "3\\n" | test.rs:175:22:175:24 | FormatArgsExpr | | | test.rs:175:22:175:24 | ...::_print(...) | test.rs:175:22:175:24 | { ... } | | | test.rs:175:22:175:24 | ...::format_args_nl!... | test.rs:175:22:175:24 | MacroExpr | | | test.rs:175:22:175:24 | ExprStmt | test.rs:175:13:175:25 | ...::_print | | | test.rs:175:22:175:24 | FormatArgsExpr | test.rs:175:22:175:24 | ...::format_args_nl!... | | | test.rs:175:22:175:24 | MacroExpr | test.rs:175:22:175:24 | ...::_print(...) | | -| test.rs:175:22:175:24 | MacroStmts | test.rs:175:22:175:24 | ExprStmt | | -| test.rs:175:22:175:24 | { ... } | test.rs:175:13:175:25 | println!... | | +| test.rs:175:22:175:24 | MacroStmts | test.rs:175:13:175:25 | println!... | | +| test.rs:175:22:175:24 | { ... } | test.rs:175:22:175:24 | MacroStmts | | | test.rs:179:5:188:5 | enter fn test_nested_if_match | test.rs:179:29:179:29 | a | | | test.rs:179:5:188:5 | exit fn test_nested_if_match (normal) | test.rs:179:5:188:5 | exit fn test_nested_if_match | | | test.rs:179:29:179:29 | a | test.rs:179:29:179:29 | a | | @@ -889,7 +889,7 @@ edges | test.rs:362:46:365:5 | { ... } | test.rs:362:5:365:5 | exit fn test_let_match (normal) | | | test.rs:363:9:363:57 | let ... = a else {...} | test.rs:363:23:363:23 | a | | | test.rs:363:13:363:19 | Some(...) | test.rs:363:18:363:18 | n | match | -| test.rs:363:13:363:19 | Some(...) | test.rs:363:39:363:53 | MacroStmts | no-match | +| test.rs:363:13:363:19 | Some(...) | test.rs:363:39:363:53 | ExprStmt | no-match | | test.rs:363:18:363:18 | n | test.rs:363:18:363:18 | n | | | test.rs:363:18:363:18 | n | test.rs:364:9:364:9 | n | match | | test.rs:363:23:363:23 | a | test.rs:363:13:363:19 | Some(...) | | @@ -902,11 +902,11 @@ edges | test.rs:363:39:363:53 | ...::panic_fmt(...) | test.rs:363:39:363:53 | { ... } | | | test.rs:363:39:363:53 | ExprStmt | test.rs:363:32:363:54 | ...::panic_fmt | | | test.rs:363:39:363:53 | FormatArgsExpr | test.rs:363:39:363:53 | ...::const_format_args!... | | -| test.rs:363:39:363:53 | MacroExpr | test.rs:363:32:363:54 | panic!... | | | test.rs:363:39:363:53 | MacroExpr | test.rs:363:39:363:53 | ...::panic_fmt(...) | | -| test.rs:363:39:363:53 | MacroStmts | test.rs:363:39:363:53 | ExprStmt | | -| test.rs:363:39:363:53 | MacroStmts | test.rs:363:39:363:53 | MacroStmts | | -| test.rs:363:39:363:53 | { ... } | test.rs:363:39:363:53 | ...::panic_2021!... | | +| test.rs:363:39:363:53 | MacroExpr | test.rs:363:39:363:53 | MacroStmts | | +| test.rs:363:39:363:53 | MacroStmts | test.rs:363:32:363:54 | panic!... | | +| test.rs:363:39:363:53 | MacroStmts | test.rs:363:39:363:53 | ...::panic_2021!... | | +| test.rs:363:39:363:53 | { ... } | test.rs:363:39:363:53 | MacroStmts | | | test.rs:364:9:364:9 | n | test.rs:362:46:365:5 | { ... } | | | test.rs:367:5:373:5 | enter fn test_let_with_return | test.rs:367:29:367:29 | m | | | test.rs:367:5:373:5 | exit fn test_let_with_return (normal) | test.rs:367:5:373:5 | exit fn test_let_with_return | | @@ -1183,15 +1183,15 @@ edges | test.rs:495:9:495:33 | ...::_print | test.rs:495:18:495:32 | "hello, world!\\n" | | | test.rs:495:9:495:33 | MacroExpr | test.rs:494:26:496:5 | { ... } | | | test.rs:495:9:495:33 | println!... | test.rs:495:9:495:33 | MacroExpr | | -| test.rs:495:9:495:34 | ExprStmt | test.rs:495:18:495:32 | MacroStmts | | +| test.rs:495:9:495:34 | ExprStmt | test.rs:495:18:495:32 | ExprStmt | | | test.rs:495:18:495:32 | "hello, world!\\n" | test.rs:495:18:495:32 | FormatArgsExpr | | | test.rs:495:18:495:32 | ...::_print(...) | test.rs:495:18:495:32 | { ... } | | | test.rs:495:18:495:32 | ...::format_args_nl!... | test.rs:495:18:495:32 | MacroExpr | | | test.rs:495:18:495:32 | ExprStmt | test.rs:495:9:495:33 | ...::_print | | | test.rs:495:18:495:32 | FormatArgsExpr | test.rs:495:18:495:32 | ...::format_args_nl!... | | | test.rs:495:18:495:32 | MacroExpr | test.rs:495:18:495:32 | ...::_print(...) | | -| test.rs:495:18:495:32 | MacroStmts | test.rs:495:18:495:32 | ExprStmt | | -| test.rs:495:18:495:32 | { ... } | test.rs:495:9:495:33 | println!... | | +| test.rs:495:18:495:32 | MacroStmts | test.rs:495:9:495:33 | println!... | | +| test.rs:495:18:495:32 | { ... } | test.rs:495:18:495:32 | MacroStmts | | | test.rs:498:5:517:5 | enter fn async_block | test.rs:498:26:498:26 | b | | | test.rs:498:5:517:5 | exit fn async_block (normal) | test.rs:498:5:517:5 | exit fn async_block | | | test.rs:498:26:498:26 | b | test.rs:498:26:498:26 | b | | @@ -1207,15 +1207,15 @@ edges | test.rs:500:13:500:41 | ...::_print | test.rs:500:22:500:40 | "godbye, everyone!\\n" | | | test.rs:500:13:500:41 | MacroExpr | test.rs:499:26:501:9 | exit { ... } (normal) | | | test.rs:500:13:500:41 | println!... | test.rs:500:13:500:41 | MacroExpr | | -| test.rs:500:13:500:42 | ExprStmt | test.rs:500:22:500:40 | MacroStmts | | +| test.rs:500:13:500:42 | ExprStmt | test.rs:500:22:500:40 | ExprStmt | | | test.rs:500:22:500:40 | "godbye, everyone!\\n" | test.rs:500:22:500:40 | FormatArgsExpr | | | test.rs:500:22:500:40 | ...::_print(...) | test.rs:500:22:500:40 | { ... } | | | test.rs:500:22:500:40 | ...::format_args_nl!... | test.rs:500:22:500:40 | MacroExpr | | | test.rs:500:22:500:40 | ExprStmt | test.rs:500:13:500:41 | ...::_print | | | test.rs:500:22:500:40 | FormatArgsExpr | test.rs:500:22:500:40 | ...::format_args_nl!... | | | test.rs:500:22:500:40 | MacroExpr | test.rs:500:22:500:40 | ...::_print(...) | | -| test.rs:500:22:500:40 | MacroStmts | test.rs:500:22:500:40 | ExprStmt | | -| test.rs:500:22:500:40 | { ... } | test.rs:500:13:500:41 | println!... | | +| test.rs:500:22:500:40 | MacroStmts | test.rs:500:13:500:41 | println!... | | +| test.rs:500:22:500:40 | { ... } | test.rs:500:22:500:40 | MacroStmts | | | test.rs:502:9:504:10 | let ... = ... | test.rs:502:31:504:9 | { ... } | | | test.rs:502:13:502:27 | say_how_are_you | test.rs:502:13:502:27 | say_how_are_you | | | test.rs:502:13:502:27 | say_how_are_you | test.rs:505:9:505:28 | let ... = ... | match | @@ -1225,15 +1225,15 @@ edges | test.rs:503:13:503:36 | ...::_print | test.rs:503:22:503:35 | "how are you?\\n" | | | test.rs:503:13:503:36 | MacroExpr | test.rs:502:31:504:9 | exit { ... } (normal) | | | test.rs:503:13:503:36 | println!... | test.rs:503:13:503:36 | MacroExpr | | -| test.rs:503:13:503:37 | ExprStmt | test.rs:503:22:503:35 | MacroStmts | | +| test.rs:503:13:503:37 | ExprStmt | test.rs:503:22:503:35 | ExprStmt | | | test.rs:503:22:503:35 | "how are you?\\n" | test.rs:503:22:503:35 | FormatArgsExpr | | | test.rs:503:22:503:35 | ...::_print(...) | test.rs:503:22:503:35 | { ... } | | | test.rs:503:22:503:35 | ...::format_args_nl!... | test.rs:503:22:503:35 | MacroExpr | | | test.rs:503:22:503:35 | ExprStmt | test.rs:503:13:503:36 | ...::_print | | | test.rs:503:22:503:35 | FormatArgsExpr | test.rs:503:22:503:35 | ...::format_args_nl!... | | | test.rs:503:22:503:35 | MacroExpr | test.rs:503:22:503:35 | ...::_print(...) | | -| test.rs:503:22:503:35 | MacroStmts | test.rs:503:22:503:35 | ExprStmt | | -| test.rs:503:22:503:35 | { ... } | test.rs:503:13:503:36 | println!... | | +| test.rs:503:22:503:35 | MacroStmts | test.rs:503:13:503:36 | println!... | | +| test.rs:503:22:503:35 | { ... } | test.rs:503:22:503:35 | MacroStmts | | | test.rs:505:9:505:28 | let ... = ... | test.rs:505:20:505:27 | { ... } | | | test.rs:505:13:505:16 | noop | test.rs:505:13:505:16 | noop | | | test.rs:505:13:505:16 | noop | test.rs:506:9:506:26 | ExprStmt | match | @@ -1290,30 +1290,30 @@ edges | test.rs:533:13:533:49 | ...::panic_2021!... | test.rs:533:13:533:49 | MacroExpr | | | test.rs:533:13:533:49 | ...::panic_explicit | test.rs:533:13:533:49 | ...::panic_explicit(...) | | | test.rs:533:13:533:49 | ...::panic_explicit(...) | test.rs:533:13:533:49 | { ... } | | -| test.rs:533:13:533:49 | ExprStmt | test.rs:533:13:533:49 | MacroStmts | | +| test.rs:533:13:533:49 | ExprStmt | test.rs:533:13:533:49 | fn panic_cold_explicit | | | test.rs:533:13:533:49 | ExprStmt | test.rs:533:13:533:49 | panic_cold_explicit | | | test.rs:533:13:533:49 | MacroExpr | test.rs:532:9:534:9 | { ... } | | | test.rs:533:13:533:49 | MacroExpr | test.rs:533:13:533:49 | { ... } | | -| test.rs:533:13:533:49 | MacroStmts | test.rs:533:13:533:49 | fn panic_cold_explicit | | +| test.rs:533:13:533:49 | MacroStmts | test.rs:533:13:533:49 | ...::panic_2021!... | | | test.rs:533:13:533:49 | assert!... | test.rs:533:13:533:49 | MacroExpr | | | test.rs:533:13:533:49 | enter fn panic_cold_explicit | test.rs:533:13:533:49 | ...::panic_explicit | | | test.rs:533:13:533:49 | exit fn panic_cold_explicit (normal) | test.rs:533:13:533:49 | exit fn panic_cold_explicit | | | test.rs:533:13:533:49 | fn panic_cold_explicit | test.rs:533:13:533:49 | ExprStmt | | | test.rs:533:13:533:49 | panic_cold_explicit | test.rs:533:13:533:49 | panic_cold_explicit(...) | | | test.rs:533:13:533:49 | panic_cold_explicit(...) | test.rs:533:13:533:49 | { ... } | | -| test.rs:533:13:533:49 | { ... } | test.rs:533:13:533:49 | ...::panic_2021!... | | +| test.rs:533:13:533:49 | { ... } | test.rs:533:13:533:49 | MacroStmts | | | test.rs:533:13:533:49 | { ... } | test.rs:533:13:533:49 | exit fn panic_cold_explicit (normal) | | | test.rs:533:13:533:49 | { ... } | test.rs:533:21:533:48 | if ... {...} | | -| test.rs:533:13:533:50 | ExprStmt | test.rs:533:21:533:48 | MacroStmts | | +| test.rs:533:13:533:50 | ExprStmt | test.rs:533:21:533:42 | ...::size_of::<...> | | | test.rs:533:21:533:42 | ...::size_of::<...> | test.rs:533:21:533:44 | ...::size_of::<...>(...) | | | test.rs:533:21:533:44 | ...::size_of::<...>(...) | test.rs:533:48:533:48 | 0 | | | test.rs:533:21:533:48 | ... > ... | test.rs:533:21:533:48 | [boolean(false)] ! ... | true | | test.rs:533:21:533:48 | ... > ... | test.rs:533:21:533:48 | [boolean(true)] ! ... | false | -| test.rs:533:21:533:48 | MacroStmts | test.rs:533:21:533:42 | ...::size_of::<...> | | +| test.rs:533:21:533:48 | MacroStmts | test.rs:533:13:533:49 | assert!... | | | test.rs:533:21:533:48 | [boolean(false)] ! ... | test.rs:533:21:533:48 | if ... {...} | false | | test.rs:533:21:533:48 | [boolean(true)] ! ... | test.rs:533:13:533:49 | ExprStmt | true | | test.rs:533:21:533:48 | if ... {...} | test.rs:533:21:533:48 | { ... } | | -| test.rs:533:21:533:48 | { ... } | test.rs:533:13:533:49 | assert!... | | +| test.rs:533:21:533:48 | { ... } | test.rs:533:21:533:48 | MacroStmts | | | test.rs:533:48:533:48 | 0 | test.rs:533:21:533:48 | ... > ... | | | test.rs:536:9:536:10 | 42 | test.rs:529:41:537:5 | { ... } | | | test.rs:539:5:548:5 | enter fn const_block_panic | test.rs:540:9:540:30 | Const | | diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index 6c2a7c2ba85b..a03453383b0d 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -10,12 +10,14 @@ localStep | main.rs:6:9:6:9 | s | main.rs:6:9:6:9 | s | | main.rs:6:9:6:14 | ...: i64 | main.rs:6:9:6:9 | s | | main.rs:7:14:7:20 | FormatArgsExpr | main.rs:7:14:7:20 | MacroExpr | +| main.rs:7:14:7:20 | MacroStmts | main.rs:7:5:7:21 | MacroExpr | | main.rs:7:14:7:20 | [post] MacroExpr | main.rs:7:14:7:20 | [post] FormatArgsExpr | | main.rs:10:13:10:14 | [SSA] sr | main.rs:11:20:11:21 | sr | | main.rs:10:13:10:14 | sr | main.rs:10:13:10:14 | [SSA] sr | | main.rs:10:13:10:14 | sr | main.rs:10:13:10:14 | sr | | main.rs:10:13:10:20 | ...: ... | main.rs:10:13:10:14 | sr | | main.rs:11:14:11:21 | FormatArgsExpr | main.rs:11:14:11:21 | MacroExpr | +| main.rs:11:14:11:21 | MacroStmts | main.rs:11:5:11:22 | MacroExpr | | main.rs:11:14:11:21 | [post] MacroExpr | main.rs:11:14:11:21 | [post] FormatArgsExpr | | main.rs:22:9:22:9 | [SSA] s | main.rs:23:10:23:10 | s | | main.rs:22:9:22:9 | s | main.rs:22:9:22:9 | [SSA] s | @@ -680,6 +682,7 @@ localStep | main.rs:462:16:462:16 | s | main.rs:462:16:462:16 | s | | main.rs:462:16:462:24 | ...: String | main.rs:462:16:462:16 | s | | main.rs:463:14:463:20 | FormatArgsExpr | main.rs:463:14:463:20 | MacroExpr | +| main.rs:463:14:463:20 | MacroStmts | main.rs:463:5:463:21 | MacroExpr | | main.rs:463:14:463:20 | [post] MacroExpr | main.rs:463:14:463:20 | [post] FormatArgsExpr | | main.rs:467:9:467:9 | [SSA] a | main.rs:468:13:468:13 | a | | main.rs:467:9:467:9 | a | main.rs:467:9:467:9 | [SSA] a | diff --git a/rust/ql/test/library-tests/variables/Cfg.expected b/rust/ql/test/library-tests/variables/Cfg.expected index 2f3d99277101..2c04ca30410a 100644 --- a/rust/ql/test/library-tests/variables/Cfg.expected +++ b/rust/ql/test/library-tests/variables/Cfg.expected @@ -8,15 +8,15 @@ edges | main.rs:4:5:4:21 | ...::_print | main.rs:4:14:4:17 | "{}\\n" | | | main.rs:4:5:4:21 | MacroExpr | main.rs:3:23:5:1 | { ... } | | | main.rs:4:5:4:21 | println!... | main.rs:4:5:4:21 | MacroExpr | | -| main.rs:4:5:4:22 | ExprStmt | main.rs:4:14:4:20 | MacroStmts | | +| main.rs:4:5:4:22 | ExprStmt | main.rs:4:14:4:20 | ExprStmt | | | main.rs:4:14:4:17 | "{}\\n" | main.rs:4:20:4:20 | s | | | main.rs:4:14:4:20 | ...::_print(...) | main.rs:4:14:4:20 | { ... } | | | main.rs:4:14:4:20 | ...::format_args_nl!... | main.rs:4:14:4:20 | MacroExpr | | | main.rs:4:14:4:20 | ExprStmt | main.rs:4:5:4:21 | ...::_print | | | main.rs:4:14:4:20 | FormatArgsExpr | main.rs:4:14:4:20 | ...::format_args_nl!... | | | main.rs:4:14:4:20 | MacroExpr | main.rs:4:14:4:20 | ...::_print(...) | | -| main.rs:4:14:4:20 | MacroStmts | main.rs:4:14:4:20 | ExprStmt | | -| main.rs:4:14:4:20 | { ... } | main.rs:4:5:4:21 | println!... | | +| main.rs:4:14:4:20 | MacroStmts | main.rs:4:5:4:21 | println!... | | +| main.rs:4:14:4:20 | { ... } | main.rs:4:14:4:20 | MacroStmts | | | main.rs:4:20:4:20 | s | main.rs:4:14:4:20 | FormatArgsExpr | | | main.rs:7:1:9:1 | enter fn print_i64 | main.rs:7:14:7:14 | i | | | main.rs:7:1:9:1 | exit fn print_i64 (normal) | main.rs:7:1:9:1 | exit fn print_i64 | | @@ -27,15 +27,15 @@ edges | main.rs:8:5:8:21 | ...::_print | main.rs:8:14:8:17 | "{}\\n" | | | main.rs:8:5:8:21 | MacroExpr | main.rs:7:22:9:1 | { ... } | | | main.rs:8:5:8:21 | println!... | main.rs:8:5:8:21 | MacroExpr | | -| main.rs:8:5:8:22 | ExprStmt | main.rs:8:14:8:20 | MacroStmts | | +| main.rs:8:5:8:22 | ExprStmt | main.rs:8:14:8:20 | ExprStmt | | | main.rs:8:14:8:17 | "{}\\n" | main.rs:8:20:8:20 | i | | | main.rs:8:14:8:20 | ...::_print(...) | main.rs:8:14:8:20 | { ... } | | | main.rs:8:14:8:20 | ...::format_args_nl!... | main.rs:8:14:8:20 | MacroExpr | | | main.rs:8:14:8:20 | ExprStmt | main.rs:8:5:8:21 | ...::_print | | | main.rs:8:14:8:20 | FormatArgsExpr | main.rs:8:14:8:20 | ...::format_args_nl!... | | | main.rs:8:14:8:20 | MacroExpr | main.rs:8:14:8:20 | ...::_print(...) | | -| main.rs:8:14:8:20 | MacroStmts | main.rs:8:14:8:20 | ExprStmt | | -| main.rs:8:14:8:20 | { ... } | main.rs:8:5:8:21 | println!... | | +| main.rs:8:14:8:20 | MacroStmts | main.rs:8:5:8:21 | println!... | | +| main.rs:8:14:8:20 | { ... } | main.rs:8:14:8:20 | MacroStmts | | | main.rs:8:20:8:20 | i | main.rs:8:14:8:20 | FormatArgsExpr | | | main.rs:11:1:13:1 | enter fn print_i64_ref | main.rs:11:18:11:18 | i | | | main.rs:11:1:13:1 | exit fn print_i64_ref (normal) | main.rs:11:1:13:1 | exit fn print_i64_ref | | @@ -234,7 +234,7 @@ edges | main.rs:93:19:99:1 | { ... } | main.rs:93:1:99:1 | exit fn let_pattern4 (normal) | | | main.rs:94:5:97:10 | let ... = ... else {...} | main.rs:94:34:94:37 | Some | | | main.rs:94:9:94:16 | Some(...) | main.rs:94:14:94:15 | x5 | match | -| main.rs:94:9:94:16 | Some(...) | main.rs:96:13:96:19 | MacroStmts | no-match | +| main.rs:94:9:94:16 | Some(...) | main.rs:96:13:96:19 | ...::panic | no-match | | main.rs:94:14:94:15 | x5 | main.rs:94:14:94:15 | x5 | | | main.rs:94:14:94:15 | x5 | main.rs:98:5:98:18 | ExprStmt | match | | main.rs:94:34:94:37 | Some | main.rs:94:39:94:42 | "x5" | | @@ -242,9 +242,9 @@ edges | main.rs:94:39:94:42 | "x5" | main.rs:94:34:94:43 | Some(...) | | | main.rs:96:13:96:19 | "not yet implemented" | main.rs:96:13:96:19 | ...::panic(...) | | | main.rs:96:13:96:19 | ...::panic | main.rs:96:13:96:19 | "not yet implemented" | | -| main.rs:96:13:96:19 | ...::panic(...) | main.rs:96:13:96:19 | todo!... | | +| main.rs:96:13:96:19 | ...::panic(...) | main.rs:96:13:96:19 | MacroStmts | | | main.rs:96:13:96:19 | MacroExpr | main.rs:95:14:97:9 | { ... } | | -| main.rs:96:13:96:19 | MacroStmts | main.rs:96:13:96:19 | ...::panic | | +| main.rs:96:13:96:19 | MacroStmts | main.rs:96:13:96:19 | todo!... | | | main.rs:96:13:96:19 | todo!... | main.rs:96:13:96:19 | MacroExpr | | | main.rs:98:5:98:13 | print_str | main.rs:98:15:98:16 | x5 | | | main.rs:98:5:98:17 | print_str(...) | main.rs:93:19:99:1 | { ... } | | @@ -417,7 +417,7 @@ edges | main.rs:175:30:175:31 | 10 | main.rs:178:9:178:29 | ...::Hello {...} | no-match | | main.rs:175:30:175:36 | RangePat | main.rs:175:30:175:31 | 10 | match | | main.rs:175:35:175:36 | 12 | main.rs:175:35:175:36 | 12 | | -| main.rs:175:35:175:36 | 12 | main.rs:176:22:176:51 | MacroStmts | match | +| main.rs:175:35:175:36 | 12 | main.rs:176:22:176:51 | ExprStmt | match | | main.rs:175:35:175:36 | 12 | main.rs:178:9:178:29 | ...::Hello {...} | no-match | | main.rs:175:43:177:9 | { ... } | main.rs:171:5:180:5 | match msg { ... } | | | main.rs:176:13:176:52 | ...::_print | main.rs:176:22:176:51 | "Found an id in another range\\... | | @@ -429,8 +429,8 @@ edges | main.rs:176:22:176:51 | ExprStmt | main.rs:176:13:176:52 | ...::_print | | | main.rs:176:22:176:51 | FormatArgsExpr | main.rs:176:22:176:51 | ...::format_args_nl!... | | | main.rs:176:22:176:51 | MacroExpr | main.rs:176:22:176:51 | ...::_print(...) | | -| main.rs:176:22:176:51 | MacroStmts | main.rs:176:22:176:51 | ExprStmt | | -| main.rs:176:22:176:51 | { ... } | main.rs:176:13:176:52 | println!... | | +| main.rs:176:22:176:51 | MacroStmts | main.rs:176:13:176:52 | println!... | | +| main.rs:176:22:176:51 | { ... } | main.rs:176:22:176:51 | MacroStmts | | | main.rs:178:9:178:29 | ...::Hello {...} | main.rs:178:26:178:27 | id | match | | main.rs:178:26:178:27 | id | main.rs:178:26:178:27 | id | | | main.rs:178:26:178:27 | id | main.rs:179:13:179:21 | print_i64 | match | diff --git a/rust/schema/annotations.py b/rust/schema/annotations.py index a5c3ff56651a..f783e72e6199 100644 --- a/rust/schema/annotations.py +++ b/rust/schema/annotations.py @@ -87,7 +87,8 @@ class _: foo::bar; ``` """ - segment: _ | ql.db_table_name("path_segments_") | doc("last segment of this path") + segment: _ | ql.db_table_name("path_segments_") | doc( + "last segment of this path") @annotate(GenericArgList) @@ -1288,7 +1289,7 @@ class _: """ -@annotate(MacroStmts) +@annotate(MacroStmts, replace_bases={AstNode: Expr}, cfg=True) @rust.doc_test_signature(None) class _: """ @@ -1447,6 +1448,7 @@ class _: type_repr: optional["TypeRepr"] | child | rust.detach trait_type_repr: optional["PathTypeRepr"] | child | rust.detach + @annotate(PathTypeRepr) @qltest.test_with(Path) class _: From 869af58c9d2e246ce728cbaf45ea6feb10b7d571 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Thu, 17 Apr 2025 18:58:05 +0200 Subject: [PATCH 236/336] Rust: add flow step for MacroStmts --- .../rust/dataflow/internal/DataFlowImpl.qll | 1 + .../dataflow/local/DataFlowStep.expected | 3 +++ .../security/CWE-089/SqlInjection.expected | 21 ++++++++++++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll index b29506224406..f750fed04555 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll @@ -203,6 +203,7 @@ private ExprCfgNode getALastEvalNode(ExprCfgNode e) { result = e.(ReturnExprCfgNode).getExpr() or result = e.(BreakExprCfgNode).getExpr() or result = e.(BlockExprCfgNode).getTailExpr() or + result = e.(MacroStmtsCfgNode).getExpr() or result = e.(MatchExprCfgNode).getArmExpr(_) or result = e.(MacroExprCfgNode).getMacroCall().(MacroCallCfgNode).getExpandedNode() or result.(BreakExprCfgNode).getTarget() = e diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index a03453383b0d..123e8801649f 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -12,6 +12,7 @@ localStep | main.rs:7:14:7:20 | FormatArgsExpr | main.rs:7:14:7:20 | MacroExpr | | main.rs:7:14:7:20 | MacroStmts | main.rs:7:5:7:21 | MacroExpr | | main.rs:7:14:7:20 | [post] MacroExpr | main.rs:7:14:7:20 | [post] FormatArgsExpr | +| main.rs:7:14:7:20 | { ... } | main.rs:7:14:7:20 | MacroStmts | | main.rs:10:13:10:14 | [SSA] sr | main.rs:11:20:11:21 | sr | | main.rs:10:13:10:14 | sr | main.rs:10:13:10:14 | [SSA] sr | | main.rs:10:13:10:14 | sr | main.rs:10:13:10:14 | sr | @@ -19,6 +20,7 @@ localStep | main.rs:11:14:11:21 | FormatArgsExpr | main.rs:11:14:11:21 | MacroExpr | | main.rs:11:14:11:21 | MacroStmts | main.rs:11:5:11:22 | MacroExpr | | main.rs:11:14:11:21 | [post] MacroExpr | main.rs:11:14:11:21 | [post] FormatArgsExpr | +| main.rs:11:14:11:21 | { ... } | main.rs:11:14:11:21 | MacroStmts | | main.rs:22:9:22:9 | [SSA] s | main.rs:23:10:23:10 | s | | main.rs:22:9:22:9 | s | main.rs:22:9:22:9 | [SSA] s | | main.rs:22:9:22:9 | s | main.rs:22:9:22:9 | s | @@ -684,6 +686,7 @@ localStep | main.rs:463:14:463:20 | FormatArgsExpr | main.rs:463:14:463:20 | MacroExpr | | main.rs:463:14:463:20 | MacroStmts | main.rs:463:5:463:21 | MacroExpr | | main.rs:463:14:463:20 | [post] MacroExpr | main.rs:463:14:463:20 | [post] FormatArgsExpr | +| main.rs:463:14:463:20 | { ... } | main.rs:463:14:463:20 | MacroStmts | | main.rs:467:9:467:9 | [SSA] a | main.rs:468:13:468:13 | a | | main.rs:467:9:467:9 | a | main.rs:467:9:467:9 | [SSA] a | | main.rs:467:9:467:9 | a | main.rs:467:9:467:9 | a | diff --git a/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected b/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected index e56e7e3ca36b..176556b658cd 100644 --- a/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected +++ b/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected @@ -2,9 +2,11 @@ | sqlx.rs:66:26:66:46 | safe_query_3.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:66:26:66:46 | safe_query_3.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | | sqlx.rs:67:26:67:48 | unsafe_query_1.as_str() | sqlx.rs:47:22:47:35 | ...::args | sqlx.rs:67:26:67:48 | unsafe_query_1.as_str() | This query depends on a $@. | sqlx.rs:47:22:47:35 | ...::args | user-provided value | | sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | +| sqlx.rs:71:30:71:52 | unsafe_query_4.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:71:30:71:52 | unsafe_query_4.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | | sqlx.rs:77:25:77:45 | safe_query_3.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:77:25:77:45 | safe_query_3.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | | sqlx.rs:78:25:78:47 | unsafe_query_1.as_str() | sqlx.rs:47:22:47:35 | ...::args | sqlx.rs:78:25:78:47 | unsafe_query_1.as_str() | This query depends on a $@. | sqlx.rs:47:22:47:35 | ...::args | user-provided value | | sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | +| sqlx.rs:82:29:82:51 | unsafe_query_4.as_str() | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:82:29:82:51 | unsafe_query_4.as_str() | This query depends on a $@. | sqlx.rs:48:25:48:46 | ...::get | user-provided value | edges | sqlx.rs:47:9:47:18 | arg_string | sqlx.rs:53:27:53:36 | arg_string | provenance | | | sqlx.rs:47:22:47:35 | ...::args | sqlx.rs:47:22:47:37 | ...::args(...) [element] | provenance | Src:MaD:1 | @@ -13,6 +15,7 @@ edges | sqlx.rs:47:22:47:77 | ... .unwrap_or(...) | sqlx.rs:47:9:47:18 | arg_string | provenance | | | sqlx.rs:48:9:48:21 | remote_string | sqlx.rs:49:25:49:52 | remote_string.parse() [Ok] | provenance | MaD:8 | | sqlx.rs:48:9:48:21 | remote_string | sqlx.rs:54:27:54:39 | remote_string | provenance | | +| sqlx.rs:48:9:48:21 | remote_string | sqlx.rs:59:17:59:72 | MacroExpr | provenance | | | sqlx.rs:48:25:48:46 | ...::get | sqlx.rs:48:25:48:69 | ...::get(...) [Ok] | provenance | Src:MaD:2 | | sqlx.rs:48:25:48:69 | ...::get(...) [Ok] | sqlx.rs:48:25:48:78 | ... .unwrap() | provenance | MaD:6 | | sqlx.rs:48:25:48:78 | ... .unwrap() | sqlx.rs:48:25:48:85 | ... .text() [Ok] | provenance | MaD:11 | @@ -36,6 +39,13 @@ edges | sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | provenance | MaD:3 | | sqlx.rs:54:26:54:39 | &remote_string [&ref] | sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | provenance | | | sqlx.rs:54:27:54:39 | remote_string | sqlx.rs:54:26:54:39 | &remote_string [&ref] | provenance | | +| sqlx.rs:56:9:56:22 | unsafe_query_4 | sqlx.rs:71:30:71:52 | unsafe_query_4.as_str() | provenance | MaD:3 | +| sqlx.rs:56:9:56:22 | unsafe_query_4 | sqlx.rs:82:29:82:51 | unsafe_query_4.as_str() | provenance | MaD:3 | +| sqlx.rs:59:9:59:73 | res | sqlx.rs:59:17:59:72 | { ... } | provenance | | +| sqlx.rs:59:17:59:72 | ...::format(...) | sqlx.rs:59:9:59:73 | res | provenance | | +| sqlx.rs:59:17:59:72 | ...::must_use(...) | sqlx.rs:56:9:56:22 | unsafe_query_4 | provenance | | +| sqlx.rs:59:17:59:72 | MacroExpr | sqlx.rs:59:17:59:72 | ...::format(...) | provenance | MaD:4 | +| sqlx.rs:59:17:59:72 | { ... } | sqlx.rs:59:17:59:72 | ...::must_use(...) | provenance | MaD:9 | models | 1 | Source: lang:std; crate::env::args; commandargs; ReturnValue.Element | | 2 | Source: repo:https://github.com/seanmonstar/reqwest:reqwest; crate::blocking::get; remote; ReturnValue.Field[crate::result::Result::Ok(0)] | @@ -75,13 +85,18 @@ nodes | sqlx.rs:54:9:54:22 | unsafe_query_2 [&ref] | semmle.label | unsafe_query_2 [&ref] | | sqlx.rs:54:26:54:39 | &remote_string [&ref] | semmle.label | &remote_string [&ref] | | sqlx.rs:54:27:54:39 | remote_string | semmle.label | remote_string | +| sqlx.rs:56:9:56:22 | unsafe_query_4 | semmle.label | unsafe_query_4 | +| sqlx.rs:59:9:59:73 | res | semmle.label | res | +| sqlx.rs:59:17:59:72 | ...::format(...) | semmle.label | ...::format(...) | +| sqlx.rs:59:17:59:72 | ...::must_use(...) | semmle.label | ...::must_use(...) | +| sqlx.rs:59:17:59:72 | MacroExpr | semmle.label | MacroExpr | +| sqlx.rs:59:17:59:72 | { ... } | semmle.label | { ... } | | sqlx.rs:66:26:66:46 | safe_query_3.as_str() | semmle.label | safe_query_3.as_str() | | sqlx.rs:67:26:67:48 | unsafe_query_1.as_str() | semmle.label | unsafe_query_1.as_str() | | sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() | semmle.label | unsafe_query_2.as_str() | +| sqlx.rs:71:30:71:52 | unsafe_query_4.as_str() | semmle.label | unsafe_query_4.as_str() | | sqlx.rs:77:25:77:45 | safe_query_3.as_str() | semmle.label | safe_query_3.as_str() | | sqlx.rs:78:25:78:47 | unsafe_query_1.as_str() | semmle.label | unsafe_query_1.as_str() | | sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | semmle.label | unsafe_query_2.as_str() | +| sqlx.rs:82:29:82:51 | unsafe_query_4.as_str() | semmle.label | unsafe_query_4.as_str() | subpaths -testFailures -| sqlx.rs:71:63:71:109 | //... | Missing result: Alert[rust/sql-injection]=remote1 | -| sqlx.rs:82:77:82:123 | //... | Missing result: Alert[rust/sql-injection]=remote1 | From bc35599f1ad0d85cedb4bb263557e2a6dcaf1ddd Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Fri, 2 May 2025 14:47:59 +0200 Subject: [PATCH 237/336] Rust: rename MacroStmts to MacroBlockExpr --- rust/ast-generator/src/main.rs | 2 + rust/extractor/src/generated/.generated.list | 2 +- rust/extractor/src/generated/top.rs | 126 ++++++++--------- rust/extractor/src/translate/generated.rs | 10 +- rust/ql/.generated.list | 26 ++-- rust/ql/.gitattributes | 14 +- .../internal/ControlFlowGraphImpl.qll | 6 +- .../internal/generated/CfgNodes.qll | 128 +++++++++--------- .../rust/dataflow/internal/DataFlowImpl.qll | 2 +- rust/ql/lib/codeql/rust/elements.qll | 2 +- .../{MacroStmts.qll => MacroBlockExpr.qll} | 6 +- ...ctor.qll => MacroBlockExprConstructor.qll} | 6 +- ...roStmtsImpl.qll => MacroBlockExprImpl.qll} | 8 +- .../internal/generated/MacroBlockExpr.qll | 66 +++++++++ .../internal/generated/MacroStmts.qll | 64 --------- .../internal/generated/ParentChild.qll | 46 ++++--- .../rust/elements/internal/generated/Raw.qll | 46 +++---- .../elements/internal/generated/Synth.qll | 46 +++---- .../internal/generated/SynthConstructors.qll | 2 +- rust/ql/lib/rust.dbscheme | 36 ++--- .../generated/.generated_tests.list | 2 +- .../extractor-tests/generated/.gitattributes | 2 +- .../MacroBlockExpr/MacroBlockExpr.expected | 1 + .../MacroBlockExpr/MacroBlockExpr.ql | 11 ++ .../MacroBlockExpr_getStatement.expected} | 0 .../MacroBlockExpr_getStatement.ql} | 2 +- .../MacroBlockExpr_getTailExpr.expected | 1 + .../MacroBlockExpr_getTailExpr.ql} | 4 +- .../gen_macro_block_expr.rs} | 0 .../MacroCall/MacroCall_getExpanded.expected | 2 +- .../generated/MacroStmts/MacroStmts.expected | 1 - .../generated/MacroStmts/MacroStmts.ql | 11 -- .../MacroStmts/MacroStmts_getExpr.expected | 1 - .../library-tests/controlflow/Cfg.expected | 40 +++--- .../dataflow/local/DataFlowStep.expected | 12 +- .../test/library-tests/variables/Cfg.expected | 16 +-- rust/schema/annotations.py | 2 +- rust/schema/ast.py | 4 +- 38 files changed, 381 insertions(+), 375 deletions(-) rename rust/ql/lib/codeql/rust/elements/{MacroStmts.qll => MacroBlockExpr.qll} (66%) rename rust/ql/lib/codeql/rust/elements/internal/{MacroStmtsConstructor.qll => MacroBlockExprConstructor.qll} (60%) rename rust/ql/lib/codeql/rust/elements/internal/{MacroStmtsImpl.qll => MacroBlockExprImpl.qll} (72%) create mode 100644 rust/ql/lib/codeql/rust/elements/internal/generated/MacroBlockExpr.qll delete mode 100644 rust/ql/lib/codeql/rust/elements/internal/generated/MacroStmts.qll create mode 100644 rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr.expected create mode 100644 rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr.ql rename rust/ql/test/extractor-tests/generated/{MacroStmts/MacroStmts_getStatement.expected => MacroBlockExpr/MacroBlockExpr_getStatement.expected} (100%) rename rust/ql/test/extractor-tests/generated/{MacroStmts/MacroStmts_getStatement.ql => MacroBlockExpr/MacroBlockExpr_getStatement.ql} (83%) create mode 100644 rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getTailExpr.expected rename rust/ql/test/extractor-tests/generated/{MacroStmts/MacroStmts_getExpr.ql => MacroBlockExpr/MacroBlockExpr_getTailExpr.ql} (72%) rename rust/ql/test/extractor-tests/generated/{MacroStmts/gen_macro_stmts.rs => MacroBlockExpr/gen_macro_block_expr.rs} (100%) delete mode 100644 rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts.expected delete mode 100644 rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts.ql delete mode 100644 rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getExpr.expected diff --git a/rust/ast-generator/src/main.rs b/rust/ast-generator/src/main.rs index 8b8d7f5c593c..3f1613573df2 100644 --- a/rust/ast-generator/src/main.rs +++ b/rust/ast-generator/src/main.rs @@ -23,6 +23,7 @@ fn class_name(type_name: &str) -> String { "Literal" => "LiteralExpr".to_owned(), "ArrayExpr" => "ArrayExprInternal".to_owned(), "AsmOptions" => "AsmOptionsList".to_owned(), + "MacroStmts" => "MacroBlockExpr".to_owned(), _ if type_name.starts_with("Record") => type_name.replacen("Record", "Struct", 1), _ if type_name.ends_with("Type") => format!("{}Repr", type_name), _ => type_name.to_owned(), @@ -36,6 +37,7 @@ fn property_name(type_name: &str, field_name: &str) -> String { ("MatchExpr", "expr") => "scrutinee", ("Variant", "expr") => "discriminant", ("FieldExpr", "expr") => "container", + ("MacroBlockExpr", "expr") => "tail_expr", (_, "name_ref") => "identifier", (_, "then_branch") => "then", (_, "else_branch") => "else_", diff --git a/rust/extractor/src/generated/.generated.list b/rust/extractor/src/generated/.generated.list index 158f55acad5f..fdaed238b030 100644 --- a/rust/extractor/src/generated/.generated.list +++ b/rust/extractor/src/generated/.generated.list @@ -1,2 +1,2 @@ mod.rs 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7 -top.rs f7c07bc5a6ad3e1a3af05d16b5b448509f9f8403a510bfca1db42348d3c7038b f7c07bc5a6ad3e1a3af05d16b5b448509f9f8403a510bfca1db42348d3c7038b +top.rs 47c9cc0e39e81a89bf62497e7b3e45c9cd585c425aaac7fc5d07113e8ef9861d 47c9cc0e39e81a89bf62497e7b3e45c9cd585c425aaac7fc5d07113e8ef9861d diff --git a/rust/extractor/src/generated/top.rs b/rust/extractor/src/generated/top.rs index a79bfc7bd0a6..91fe945df62a 100644 --- a/rust/extractor/src/generated/top.rs +++ b/rust/extractor/src/generated/top.rs @@ -6307,6 +6307,69 @@ impl From> for trap::Label { } } +#[derive(Debug)] +pub struct MacroBlockExpr { + pub id: trap::TrapId, + pub tail_expr: Option>, + pub statements: Vec>, +} + +impl trap::TrapEntry for MacroBlockExpr { + fn extract_id(&mut self) -> trap::TrapId { + std::mem::replace(&mut self.id, trap::TrapId::Star) + } + + fn emit(self, id: trap::Label, out: &mut trap::Writer) { + out.add_tuple("macro_block_exprs", vec![id.into()]); + if let Some(v) = self.tail_expr { + out.add_tuple("macro_block_expr_tail_exprs", vec![id.into(), v.into()]); + } + for (i, v) in self.statements.into_iter().enumerate() { + out.add_tuple("macro_block_expr_statements", vec![id.into(), i.into(), v.into()]); + } + } +} + +impl trap::TrapClass for MacroBlockExpr { + fn class_name() -> &'static str { "MacroBlockExpr" } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme MacroBlockExpr is a subclass of Expr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme MacroBlockExpr is a subclass of AstNode + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme MacroBlockExpr is a subclass of Locatable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme MacroBlockExpr is a subclass of Element + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + #[derive(Debug)] pub struct MacroExpr { pub id: trap::TrapId, @@ -6425,69 +6488,6 @@ impl From> for trap::Label { } } -#[derive(Debug)] -pub struct MacroStmts { - pub id: trap::TrapId, - pub expr: Option>, - pub statements: Vec>, -} - -impl trap::TrapEntry for MacroStmts { - fn extract_id(&mut self) -> trap::TrapId { - std::mem::replace(&mut self.id, trap::TrapId::Star) - } - - fn emit(self, id: trap::Label, out: &mut trap::Writer) { - out.add_tuple("macro_stmts", vec![id.into()]); - if let Some(v) = self.expr { - out.add_tuple("macro_stmts_exprs", vec![id.into(), v.into()]); - } - for (i, v) in self.statements.into_iter().enumerate() { - out.add_tuple("macro_stmts_statements", vec![id.into(), i.into(), v.into()]); - } - } -} - -impl trap::TrapClass for MacroStmts { - fn class_name() -> &'static str { "MacroStmts" } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme MacroStmts is a subclass of Expr - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme MacroStmts is a subclass of AstNode - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme MacroStmts is a subclass of Locatable - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme MacroStmts is a subclass of Element - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - #[derive(Debug)] pub struct MacroTypeRepr { pub id: trap::TrapId, diff --git a/rust/extractor/src/translate/generated.rs b/rust/extractor/src/translate/generated.rs index 32b9c2367a64..8628b3e30f3f 100644 --- a/rust/extractor/src/translate/generated.rs +++ b/rust/extractor/src/translate/generated.rs @@ -1365,16 +1365,16 @@ impl Translator<'_> { Some(label) } - pub(crate) fn emit_macro_stmts(&mut self, node: ast::MacroStmts) -> Option> { - let expr = node.expr().and_then(|x| self.emit_expr(x)); + pub(crate) fn emit_macro_stmts(&mut self, node: ast::MacroStmts) -> Option> { + let tail_expr = node.expr().and_then(|x| self.emit_expr(x)); let statements = node.statements().filter_map(|x| self.emit_stmt(x)).collect(); - let label = self.trap.emit(generated::MacroStmts { + let label = self.trap.emit(generated::MacroBlockExpr { id: TrapId::Star, - expr, + tail_expr, statements, }); self.emit_location(label, &node); - emit_detached!(MacroStmts, self, node, label); + emit_detached!(MacroBlockExpr, self, node, label); self.emit_tokens(&node, label.into(), node.syntax().children_with_tokens()); Some(label) } diff --git a/rust/ql/.generated.list b/rust/ql/.generated.list index bc447c524e86..6983e8232562 100644 --- a/rust/ql/.generated.list +++ b/rust/ql/.generated.list @@ -1,4 +1,4 @@ -lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll 08d3062aa600c5dceba897f067b1142a382b7a342acc9f7e7548b0b9df0dab36 b9bc250dbd89e95bf8fd12eacfa725ad1b50ac644599da6100cff33adfb8a18e +lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll 3ec9d072adb1abd802800a104716c6896f1874fd1967cbdf55a94644d6203e71 30b03b44f858e00f3688dccaa0804306242d6fcdb077c18a94c601af32c6c703 lib/codeql/rust/elements/Abi.qll 4c973d28b6d628f5959d1f1cc793704572fd0acaae9a97dfce82ff9d73f73476 250f68350180af080f904cd34cb2af481c5c688dc93edf7365fd0ae99855e893 lib/codeql/rust/elements/Addressable.qll 13011bfd2e1556694c3d440cc34af8527da4df49ad92b62f2939d3699ff2cea5 ddb25935f7553a1a384b1abe2e4b4fa90ab50b952dadec32fd867afcb054f4be lib/codeql/rust/elements/ArgList.qll 661f5100f5d3ef8351452d9058b663a2a5c720eea8cf11bedd628969741486a2 28e424aac01a90fb58cd6f9f83c7e4cf379eea39e636bc0ba07efc818be71c71 @@ -89,13 +89,13 @@ lib/codeql/rust/elements/LiteralPat.qll daffb5f380a47543669c8cc92628b0e0de478c3a lib/codeql/rust/elements/Locatable.qll 2855efa4a469b54e0ca85daa89309a8b991cded6f3f10db361010831ba1e11d3 00c3406d14603f90abea11bf074eaf2c0b623a30e29cf6afc3a247cb58b92f0f lib/codeql/rust/elements/LoopExpr.qll ee171177650fa23eef102a9580765f4b6073a1cc41bab1ec31ad4f84ffe6c2c9 bfcf0cca4dc944270d9748a202829a38c64dfae167c0d3a4202788ceb9daf5f6 lib/codeql/rust/elements/LoopingExpr.qll 7ad7d4bbfd05adc0bb9b4ca90ff3377b8298121ca5360ffb45d5a7a1e20fe37a 964168b2045ee9bad827bba53f10a64d649b3513f2d1e3c17a1b1f11d0fc7f3a +lib/codeql/rust/elements/MacroBlockExpr.qll fb81f067a142053b122e2875a15719565024cfb09326faf12e0f1017307deb58 3ee94ef7e56bd07a8f9304869b0a7b69971b02abbee46d0bebcacb4031760282 lib/codeql/rust/elements/MacroCall.qll a39a11d387355f59af3007dcbab3282e2b9e3289c1f8f4c6b96154ddb802f8c3 88d4575e462af2aa780219ba1338a790547fdfc1d267c4b84f1b929f4bc08d05 lib/codeql/rust/elements/MacroDef.qll acb39275a1a3257084314a46ad4d8477946130f57e401c70c5949ad6aafc5c5f 6a8a8db12a3ec345fede51ca36e8c6acbdce58c5144388bb94f0706416fa152a lib/codeql/rust/elements/MacroExpr.qll ea9fed13f610bab1a2c4541c994510e0cb806530b60beef0d0c36b23e3b620f0 ad11a6bbd3a229ad97a16049cc6b0f3c8740f9f75ea61bbf4eebb072db9b12d2 lib/codeql/rust/elements/MacroItems.qll 00a5d41f7bb836d952abbd9382e42f72a9d81e65646a15a460b35ccd07a866c6 00efdb4d701b5599d76096f740da9ec157804865267b7e29bc2a214cbf03763e lib/codeql/rust/elements/MacroPat.qll dbf193b4fb544ac0b5a7dcfc31a6652de7239b6e643ff15b05868b2c142e940c 19b45c0a1eb1198e450c05d564b5d4aa0d6da29e7db84b9521eadf901e20a932 lib/codeql/rust/elements/MacroRules.qll a94535506798077043b9c1470992ac4310bf67bcce5f722080886d1b3e6d90d1 bd8e08a7171991abc85100b45267631e66d1b332caf1e5882cd17caee5cf18a3 -lib/codeql/rust/elements/MacroStmts.qll 02c4e34d266d4564ea0433a3d6186402db516dc2dd9017d7c769a76300c2286d f4517fb9fea2ea64d4f2c1998a6899d2452878000ed6f8f31c5106ef0fb6783a lib/codeql/rust/elements/MacroTypeRepr.qll 92fa5f6d20cce8fa3f2b4b823a8a77fdb7c11f2c2b12b8f900828c3a54eca334 51289f2622d1bb58d9a093255da2c05084a0b184f02e69e2526ec7fefdfdfd75 lib/codeql/rust/elements/MatchArm.qll c39fd6cc0da24b1ff8d1e42835bcfee7695ad13580e3c7c50acd7c881b1cd894 62a31d2bd125e6aaebefc406e541a641271d3c497a377959f94dd4735b2bfbf8 lib/codeql/rust/elements/MatchArmList.qll e6c48fd7419d88e996b82eb45e4aa2686dfd079b283b02be7710192fb2cb93a0 0ec63a0ca56f5f7f80093fd3e77b198b74c6289e67be55dc6a4deb610753c7bd @@ -310,6 +310,8 @@ lib/codeql/rust/elements/internal/LiteralExprConstructor.qll 8ea3569bd50704ce7d5 lib/codeql/rust/elements/internal/LiteralPatConstructor.qll b660cb428a0cba0b713fc7b07d5d2921de4a2f65a805535fb6387684c40620de 2dbc9fbc56e9de53d24265d6b13738ef5b9ced33cc3c4c1c270e04dc2fc1330f lib/codeql/rust/elements/internal/LoopExprConstructor.qll 45f3f8f7441fcab6adc58831421679ee07bac68ac0417f3cbc90c97426cc805b f7ab3361b4a11e898126378ea277d76949466946762cd6cb5e9e9b4bb9860420 lib/codeql/rust/elements/internal/LoopingExprImpl.qll 17885c1bcf7b5a3f9c7bbad3d4d55e24372af0dedd5e7fc0efcfc0a8b2cdad70 104dc45ca399b9f6e8227ad561679f728d60170398a52b31fc90cb2a2dd3c33c +lib/codeql/rust/elements/internal/MacroBlockExprConstructor.qll 90097c0d2c94083e997396e01cf24349af5eb1788060368dc21ae8cd8ce90d93 e067904a734356e38fbadbc4277629c5987adce6d8f7737f7458ac07e9b264af +lib/codeql/rust/elements/internal/MacroBlockExprImpl.qll f7a8dd1dcde2355353e17d06bb197e2d6e321ea64a39760a074d1887e68d63d6 8d429be9b6aa9f711e050b6b07f35637de22e8635a559e06dd9153a8b7947274 lib/codeql/rust/elements/internal/MacroCallConstructor.qll 707fee4fba1fd632cd00128f493e8919eaaea552ad653af4c1b7a138e362907d b49e7e36bf9306199f2326af042740ff858871b5c79f6aeddf3d5037044dbf1f lib/codeql/rust/elements/internal/MacroDefConstructor.qll 382a3bdf46905d112ee491620cc94f87d584d72f49e01eb1483f749e4709c055 eb61b90d8d8d655c2b00ff576ae20c8da9709eeef754212bc64d8e1558ad05ce lib/codeql/rust/elements/internal/MacroDefImpl.qll f26e787ffd43e8cb079db01eba04412dbf32c338938acf1bc09a2f094bbdfdfe 044f43bc94fe4b6df22afae32e9f039d1d0d9e85ad9f24b6388be71211c37ce5 @@ -321,8 +323,6 @@ lib/codeql/rust/elements/internal/MacroPatConstructor.qll 24744c1bbe21c1d249a042 lib/codeql/rust/elements/internal/MacroPatImpl.qll 7470e2d88c38c7300a64986f058ba92bb22b4945438e2e0e268f180c4f267b71 c1507df74fc4c92887f3e0a4f857f54b61f174ffae5b1af6fb70f466175d658b lib/codeql/rust/elements/internal/MacroRulesConstructor.qll dc04726ad59915ec980501c4cd3b3d2ad774f454ddbf138ff5808eba6bd63dea 8d6bf20feb850c47d1176237027ef131f18c5cbb095f6ab8b3ec58cea9bce856 lib/codeql/rust/elements/internal/MacroRulesImpl.qll 10c03adfb63ee7a4348ff5cffc6ef5300a531b048f28811a51e940b053e69f68 2498bd64aeaea9849c086abeaa6c248e4ce41b4436155f4bd4840965976d5d54 -lib/codeql/rust/elements/internal/MacroStmtsConstructor.qll c293815cd69c002ba6de1db6018672654420f3f8bdd143f9d0c620adddd2be02 d376f8f07661a8cad1b10039076fd7fca353dcacf3ca40ed6507b8c874e849ca -lib/codeql/rust/elements/internal/MacroStmtsImpl.qll 27faff9da93ad7f22a6236c73ebb4d4631161cf4ec1b82958cdf79c85aa2087c 7e2863eaf50d4b285b9240f2c5ff9497cfb4393c8528a0738d725d00f1a78406 lib/codeql/rust/elements/internal/MacroTypeReprConstructor.qll cf8a3bdcd41dda1452200993206593e957825b406b357fc89c6286cb282347ac a82279485416567428ab7bff7b8da7a3d1233fb1cfcdb1b22932ff13bd8c8ec9 lib/codeql/rust/elements/internal/MacroTypeReprImpl.qll 8044498e426597c767308b0bd8894402f7b30f334c71970d7a09dae5e25dd74d c0d566147777f562055727ebfc255e81dfb87ee724782a5a0ceb02f57597c7a0 lib/codeql/rust/elements/internal/MatchArmConstructor.qll b41c1d5822d54127ce376ef62c6a5fa60e11697319fc7d9c9c54fd313d784a93 96cca80e5684e5893c0e9c0dff365ef8ad9e15ff648c9969ba42d91f95abea05 @@ -551,13 +551,13 @@ lib/codeql/rust/elements/internal/generated/LiteralPat.qll f36b09cf39330019c111e lib/codeql/rust/elements/internal/generated/Locatable.qll c897dc1bdd4dfcb6ded83a4a93332ca3d8f421bae02493ea2a0555023071775e b32d242f8c9480dc9b53c1e13a5cb8dcfce575b0373991c082c1db460a3e37b8 lib/codeql/rust/elements/internal/generated/LoopExpr.qll db6bc87e795c9852426ec661fa2c2c54106805897408b43a67f5b82fb4657afd 1492866ccf8213469be85bbdbcae0142f4e2a39df305d4c0d664229ecd1ebdb9 lib/codeql/rust/elements/internal/generated/LoopingExpr.qll 0792c38d84b8c68114da2bbdfef32ef803b696cb0fd06e10e101756d5c46976c 111fe961fad512722006323c3f2a075fddf59bd3eb5c7afc349835fcec8eb102 +lib/codeql/rust/elements/internal/generated/MacroBlockExpr.qll 778376cdfa4caaa9df0b9c21bda5ff0f1037b730aa43efb9fb0a08998ef3999b 6df39efe7823ce590ef6f4bdfa60957ba067205a77d94ac089b2c6a7f6b7b561 lib/codeql/rust/elements/internal/generated/MacroCall.qll fc8988696493992cc4fdce8c0e5610c54ee92ea52ebb05262338f8b612353f50 188a2d7a484bd402a521787371e64f6e00e928306c8d437e6b19bf890a7aa14e lib/codeql/rust/elements/internal/generated/MacroDef.qll e9b3f07ba41aa12a8e0bd6ec1437b26a6c363065ce134b6d059478e96c2273a6 87470dea99da1a6afb3a19565291f9382e851ba864b50a995ac6f29589efbd70 lib/codeql/rust/elements/internal/generated/MacroExpr.qll 03a1daa41866f51e479ac20f51f8406d04e9946b24f3875e3cf75a6b172c3d35 1ae8ca0ee96bd2be32575d87c07cc999a6ff7770151b66c0e3406f9454153786 lib/codeql/rust/elements/internal/generated/MacroItems.qll 894890f61e118b3727d03ca813ae7220a15e45195f2d1d059cb1bba6802128c8 db3854b347f8782a3ec9f9a1439da822727b66f0bd33727383184ab65dbf29ac lib/codeql/rust/elements/internal/generated/MacroPat.qll 26bc55459a66359ad83ed7b25284a25cdbd48a868fd1bbf7e23e18b449395c43 f16ede334becba951873e585c52a3a9873c9251e3dab9a3c1a1681f632f2079f lib/codeql/rust/elements/internal/generated/MacroRules.qll 4fbd94f22b5ee0f3e5aaae39c2b9a5e9b7bf878a1017811ca589942f6de92843 49fb69543ee867bae196febea6918e621f335afdf4d3ccbf219965b37c7537b1 -lib/codeql/rust/elements/internal/generated/MacroStmts.qll d19f8b925d3b926c94e3d17c71aa4500899ec3cdd22c7e3428444e7e8e70bf97 69e64fc2089d6109de012956d1e9ddd86d468bb132e9b562efc06f359b00b0e7 lib/codeql/rust/elements/internal/generated/MacroTypeRepr.qll 4242e253fa36ee3f7d9d0677811ff5bc4ecfb02c76d768446a6a6dcd38061f68 a676632f3bb83142a0838601ae2a582d5c32d7939e4261eb8fccf3962bb06cb2 lib/codeql/rust/elements/internal/generated/MatchArm.qll f8c4c955c50f8398159c492d9d0a74f7b71e9510fcb8a3aab1d06e0f7e15b263 713939c7ef77ca73d95788096163c26213ab49f34ed41c6f4bc09a1ef9607b0d lib/codeql/rust/elements/internal/generated/MatchArmList.qll 13362680c037fe83fef4653562cc10a4429078316b5ec7c47b076336cf4aca2e 41c674293c13eceaca62134ae0c6778541f6a5201cbc5c146f0ba01b898dc267 @@ -579,7 +579,7 @@ lib/codeql/rust/elements/internal/generated/ParamList.qll c808c9d84dd7800573832b lib/codeql/rust/elements/internal/generated/ParenExpr.qll bc0731505bfe88516205ec360582a4222d2681d11342c93e15258590ddee82f2 d4bd6e0c80cf1d63746c88d4bcb3a01d4c75732e5da09e3ebd9437ced227fb60 lib/codeql/rust/elements/internal/generated/ParenPat.qll 4f168ef5d5bb87a903251cc31b2e44a759b099ec69c90af31783fbb15778c940 0e34f94a45a13396fd57d94c245dc64d1adde2ab0e22b56946f7e94c04e297fc lib/codeql/rust/elements/internal/generated/ParenTypeRepr.qll 40ab5c592e7699c621787793743e33988de71ff42ca27599f5ab3ddb70e3f7d8 12c0a6eed2202ee3e892f61da3b3ce77ac3190854cdf3097e8d2be98aa3cb91d -lib/codeql/rust/elements/internal/generated/ParentChild.qll 27c4e9351e8dcf0290a5959b634c15398196b312e75f7ef4716e7c56090a90aa 99b4716d995792105d1a20300f8710d3ae26ca59f3a0db076114509d8bdab85e +lib/codeql/rust/elements/internal/generated/ParentChild.qll abf6697a61edbb76320e68eda5e26ddda6ea1f514c83648183901d751619982c a253318e802b6129fff63123a050fff93a79f9075c130d393ad13995d08f38f7 lib/codeql/rust/elements/internal/generated/ParenthesizedArgList.qll c5fa328ea60d3a3333d7c7bb3480969c1873166c7ac8ebb9d0afad7a8099d1a8 2dbbb6200d96f7db7dea4a55bdeab8d67b14d39a43e0bd54ada019f7e466f163 lib/codeql/rust/elements/internal/generated/Pat.qll 3605ac062be2f294ee73336e9669027b8b655f4ad55660e1eab35266275154ee 7f9400db2884d336dd1d21df2a8093759c2a110be9bf6482ce8e80ae0fd74ed4 lib/codeql/rust/elements/internal/generated/Path.qll 9b12afb46fc5a9ad3a811b05472621bbecccb900c47504feb7f29d96b28421ca bcacbffc36fb3e0c9b26523b5963af0ffa9fd6b19f00a2a31bdb2316071546bd @@ -594,7 +594,7 @@ lib/codeql/rust/elements/internal/generated/PtrTypeRepr.qll 51d1e9e683fc79dddbff lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f lib/codeql/rust/elements/internal/generated/RangeExpr.qll 23cca03bf43535f33b22a38894f70d669787be4e4f5b8fe5c8f7b964d30e9027 18624cef6c6b679eeace2a98737e472432e0ead354cca02192b4d45330f047c9 lib/codeql/rust/elements/internal/generated/RangePat.qll 80826a6a6868a803aa2372e31c52a03e1811a3f1f2abdb469f91ca0bfdd9ecb6 34ee1e208c1690cba505dff2c588837c0cd91e185e2a87d1fe673191962276a9 -lib/codeql/rust/elements/internal/generated/Raw.qll 8aaa20dd4d49220f3eff2ac64f7a8d34f343d198b59785a06922c3642322e056 3d14ea25f0ad20af1bfb1b8e3e0e5fba9f1a1f764132c0d42972e08893ebd31b +lib/codeql/rust/elements/internal/generated/Raw.qll 2fb3828c97d078d37084ce791c698bc56c81fe73e134a319089d65ec55ceb138 0234a0a5fdd741d78238dbae1ce0d841d8473b8f396fee986b6ce2b69f2abe17 lib/codeql/rust/elements/internal/generated/RefExpr.qll 7d995884e3dc1c25fc719f5d7253179344d63650e217e9ff6530285fe7a57f64 f2c3c12551deea4964b66553fb9b6423ee16fec53bd63db4796191aa60dc6c66 lib/codeql/rust/elements/internal/generated/RefPat.qll 456ede39837463ee22a630ec7ab6c8630d3664a8ea206fcc6e4f199e92fa564c 5622062765f32930465ba6b170e986706f159f6070f48adee3c20e24e8df4e05 lib/codeql/rust/elements/internal/generated/RefTypeRepr.qll 3d8c0bd296d33b91a81633f697a43269a6538df06d277262d3990d3f6880ef57 13680f39e89bcd8299c218aba396f3deec804597e6f7cb7d4a7e7c748b6faa77 @@ -620,8 +620,8 @@ lib/codeql/rust/elements/internal/generated/StructFieldList.qll 8911a44217d091b0 lib/codeql/rust/elements/internal/generated/StructPat.qll c76fa005c2fd0448a8803233e1e8818c4123301eb66ac5cf69d0b9eaafc61e98 6e0dffccdce24bca20e87d5ba0f0995c9a1ae8983283e71e7dbfcf6fffc67a58 lib/codeql/rust/elements/internal/generated/StructPatField.qll 5b5c7302dbc4a902ca8e69ff31875c867e295a16a626ba3cef29cd0aa248f179 4e192a0df79947f5cb0d47fdbbba7986137a6a40a1be92ae119873e2fad67edf lib/codeql/rust/elements/internal/generated/StructPatFieldList.qll e34c003e660ba059ba81bb73b3c8d21bd2a47d0251569c46277dc9ccf2947b0a 85113f35ba5f6b9e01ad4072246a4de1ac0e4528348ac564868e96f34a3e09e2 -lib/codeql/rust/elements/internal/generated/Synth.qll e35b960eeea21a70c94bd81001357fd18b1ecccef0a7b514e2a64e9091db21a2 319b9fa102d87d93d2157cd0fe7b5934d0892185e740d98b50c44cc5e99a4cd6 -lib/codeql/rust/elements/internal/generated/SynthConstructors.qll fe007cf6eab5f0cf89ea1ea91e1f9b23e0fcf0f2872f52ef352584503f90aa29 fe007cf6eab5f0cf89ea1ea91e1f9b23e0fcf0f2872f52ef352584503f90aa29 +lib/codeql/rust/elements/internal/generated/Synth.qll eb248f4e57985ec8eabf9ed5cfb8ba8f5ebd6ca17fb712c992811bced0e342d4 bbcbdba484d3b977a0d6b9158c5fa506f59ced2ad3ae8239d536bf826bfb7e31 +lib/codeql/rust/elements/internal/generated/SynthConstructors.qll bcc7f617b775ac0c7f04b1cc333ed7cc0bd91f1fabc8baa03c824d1df03f6076 bcc7f617b775ac0c7f04b1cc333ed7cc0bd91f1fabc8baa03c824d1df03f6076 lib/codeql/rust/elements/internal/generated/Token.qll 77a91a25ca5669703cf3a4353b591cef4d72caa6b0b9db07bb9e005d69c848d1 2fdffc4882ed3a6ca9ac6d1fb5f1ac5a471ca703e2ffdc642885fa558d6e373b lib/codeql/rust/elements/internal/generated/TokenTree.qll 8577c2b097c1be2f0f7daa5acfcf146f78674a424d99563e08a84dd3e6d91b46 d2f30764e84dbfc0a6a5d3d8a5f935cd432413688cb32da9c94e420fbc10665c lib/codeql/rust/elements/internal/generated/Trait.qll 8fa41b50fa0f68333534f2b66bb4ec8e103ff09ac8fa5c2cc64bc04beafec205 ce1c9aa6d0e2f05d28aab8e1165c3b9fb8e24681ade0cf6a9df2e8617abeae7e @@ -658,7 +658,7 @@ lib/codeql/rust/elements/internal/generated/WhileExpr.qll 7edf1f23fbf953a2baabcd lib/codeql/rust/elements/internal/generated/WildcardPat.qll d74b70b57a0a66bfae017a329352a5b27a6b9e73dd5521d627f680e810c6c59e 4b913b548ba27ff3c82fcd32cf996ff329cb57d176d3bebd0fcef394486ea499 lib/codeql/rust/elements/internal/generated/YeetExpr.qll cac328200872a35337b4bcb15c851afb4743f82c080f9738d295571eb01d7392 94af734eea08129b587fed849b643e7572800e8330c0b57d727d41abda47930b lib/codeql/rust/elements/internal/generated/YieldExpr.qll 37e5f0c1e373a22bbc53d8b7f2c0e1f476e5be5080b8437c5e964f4e83fad79a 4a9a68643401637bf48e5c2b2f74a6bf0ddcb4ff76f6bffb61d436b685621e85 -lib/codeql/rust/elements.qll 05fb894d008a9c0478d03fb1639ffc57516b67d9de7f7309331279512f630b4a 05fb894d008a9c0478d03fb1639ffc57516b67d9de7f7309331279512f630b4a +lib/codeql/rust/elements.qll da721d51bc659921998521579df5bff6172d9079d8e243c2b65a5b9eb441b52e da721d51bc659921998521579df5bff6172d9079d8e243c2b65a5b9eb441b52e test/extractor-tests/generated/Abi/Abi.ql 7f6e7dc4af86eca3ebdc79b10373988cd0871bd78b51997d3cffd969105e5fdd 2f936b6ca005c6157c755121584410c03e4a3949c23bee302fbe05ee10ce118f test/extractor-tests/generated/Abi/Abi_getAbiString.ql a496762fcec5a0887b87023bbf93e9b650f02e20113e25c44d6e4281ae8f5335 14109c7ce11ba25e3cd6e7f1b3fcb4cb00622f2a4eac91bfe43145c5f366bc52 test/extractor-tests/generated/ArgList/ArgList.ql e412927756e72165d0e7c5c9bd3fca89d08197bbf760db8fb7683c64bb2229bc 043dba8506946fbb87753e22c387987d7eded6ddb963aa067f9e60ef9024d684 @@ -894,6 +894,9 @@ test/extractor-tests/generated/LoopExpr/LoopExpr.ql 37b320acefa3734331f87414de27 test/extractor-tests/generated/LoopExpr/LoopExpr_getAttr.ql d557c1a34ae8762b32702d6b50e79c25bc506275c33a896b6b94bbbe73d04c49 34846c9eefa0219f4a16e28b518b2afa23f372d0aa03b08d042c5a35375e0cd6 test/extractor-tests/generated/LoopExpr/LoopExpr_getLabel.ql 0b77b9d9fb5903d37bce5a2c0d6b276e6269da56fcb37b83cd931872fb88490f c7f09c526e59dcadec13ec9719980d68b8619d630caab2c26b8368b06c1f2cc0 test/extractor-tests/generated/LoopExpr/LoopExpr_getLoopBody.ql 0267f54077640f3dfeb38524577e4a1229115eeb1c839398d0c5f460c1d65129 96ec876635b8c561f7add19e57574444f630eae3df9ab9bc33ac180e61f3a7b8 +test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr.ql 03144a5448de91801037f3c1e6d29a230e18f9c077c718e5c3801a31cf593977 9a035e3f119b0e0c88fc4c775a032220a01680fbea2cc7f8e98180205b9bb8da +test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getStatement.ql 415a762768df2c850d21742daab5e53cd248dc3dc9652414b99737f1d5c5824b bdd2ba6c004ada34f26dac3bbc7abcd5fe250c77a97faa7fd71fb54a0dd4743a +test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getTailExpr.ql 8f6604c09e85da1a19b0f87340cebeb1cdf4e94b208305c7393082d88cf0b032 5081d9db5b38454fad1daad2f8972661bd2fb4cce2c815a560a15f8a7b9cfcee test/extractor-tests/generated/MacroCall/MacroCall.ql f41552ce4c8132db854132e445aa0c8df514bfd375aa71cc9ed0ae838b7df9f1 442ecbe1481084bb072c6f8cf0eb595b7ad371587e8708610a10f2cc718535f7 test/extractor-tests/generated/MacroCall/MacroCall_getAttr.ql c22a2a29d705e85b03a6586d1eda1a2f4f99f95f7dfeb4e6908ec3188b5ad0ad 9b8d9dcc2116a123c15c520a880efab73ade20e08197c64bc3ed0c50902c4672 test/extractor-tests/generated/MacroCall/MacroCall_getCrateOrigin.ql 3030e87de6f773d510882ee4469146f6008898e23a4a4ccabcbaa7da1a4e765e a10fe67315eda1c59d726d538ead34f35ccffc3e121eeda74c286d49a4ce4f54 @@ -922,9 +925,6 @@ test/extractor-tests/generated/MacroRules/MacroRules_getExtendedCanonicalPath.ql test/extractor-tests/generated/MacroRules/MacroRules_getName.ql 591606e3accae8b8fb49e1218c4867a42724ac209cf99786db0e5d7ea0bf55d5 d2936ef5aa4bbf024372516dde3de578990aafb2b8675bbbf0f72e8b54eb82a8 test/extractor-tests/generated/MacroRules/MacroRules_getTokenTree.ql 7598d33c3d86f9ad8629219b90667b2b65e3a1e18c6b0887291df9455a319cab 69d90446743e78e851145683c17677497fe42ed02f61f2b2974e216dc6e05b01 test/extractor-tests/generated/MacroRules/MacroRules_getVisibility.ql 5306cc85f470d21ebcbe6e98436334b0bf5ba819a0ae186569ba7e88c31636c6 fcbf5c54e5a904767a6f4d37d853072aa0040738e622c49c9a02dec8739d6587 -test/extractor-tests/generated/MacroStmts/MacroStmts.ql 991042263ba99acef0972697ce79132e5650b27bf53be2f975a0da1f29940fd8 64c44e65b3c5d3de5f9532b4ff7ce54b39442b37f63da8b10d789b9b52b85a9e -test/extractor-tests/generated/MacroStmts/MacroStmts_getExpr.ql 5717f20376600e7bf5e471beae1a7c0084f235f0931f8b3f25d2de94ebb86f8b e4685fd9d45b078a6402c285eed3a15cc4550f6656c8bc5e7e274a88d1c7e9b3 -test/extractor-tests/generated/MacroStmts/MacroStmts_getStatement.ql 8958b2212776f487869c29314e7d28f5871f5c3dde62fd9d6f87fb9e94204498 6804f5d4c0c5909689bdcdd5b8ec11ca7a8c0399b47695f66d2f99e39561565a test/extractor-tests/generated/MacroTypeRepr/MacroTypeRepr.ql 49c0dbf587f84023025f90d73d54f5320993f4db7dcc90e21eda53fc0b4d1f57 0a0712171db935c549a9cfddb6721c2c188c584a67be85409ffc3facf6c9a935 test/extractor-tests/generated/MacroTypeRepr/MacroTypeRepr_getMacroCall.ql cae14884e549c74be4b600a264eb236993d7b8ddd86589a9116ee2ba18f181e1 1d4ae2d8ed9ce0d7635a2ae447b41a328e59e97c6df7827ee7d5cf62343e86e1 test/extractor-tests/generated/MatchArm/MatchArm.ql 512aa404c94ba40b859564f07e9dffe6a5e687fafb039556e9145f4f3742981c 529f96e38cede8a26054f8981d4ba1d189c17d14d0f92d622eb20acd8f3d7e5d diff --git a/rust/ql/.gitattributes b/rust/ql/.gitattributes index 382565f3b86b..dec3580d68c9 100644 --- a/rust/ql/.gitattributes +++ b/rust/ql/.gitattributes @@ -91,13 +91,13 @@ /lib/codeql/rust/elements/Locatable.qll linguist-generated /lib/codeql/rust/elements/LoopExpr.qll linguist-generated /lib/codeql/rust/elements/LoopingExpr.qll linguist-generated +/lib/codeql/rust/elements/MacroBlockExpr.qll linguist-generated /lib/codeql/rust/elements/MacroCall.qll linguist-generated /lib/codeql/rust/elements/MacroDef.qll linguist-generated /lib/codeql/rust/elements/MacroExpr.qll linguist-generated /lib/codeql/rust/elements/MacroItems.qll linguist-generated /lib/codeql/rust/elements/MacroPat.qll linguist-generated /lib/codeql/rust/elements/MacroRules.qll linguist-generated -/lib/codeql/rust/elements/MacroStmts.qll linguist-generated /lib/codeql/rust/elements/MacroTypeRepr.qll linguist-generated /lib/codeql/rust/elements/MatchArm.qll linguist-generated /lib/codeql/rust/elements/MatchArmList.qll linguist-generated @@ -312,6 +312,8 @@ /lib/codeql/rust/elements/internal/LiteralPatConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/LoopExprConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/LoopingExprImpl.qll linguist-generated +/lib/codeql/rust/elements/internal/MacroBlockExprConstructor.qll linguist-generated +/lib/codeql/rust/elements/internal/MacroBlockExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/MacroCallConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/MacroDefConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/MacroDefImpl.qll linguist-generated @@ -323,8 +325,6 @@ /lib/codeql/rust/elements/internal/MacroPatImpl.qll linguist-generated /lib/codeql/rust/elements/internal/MacroRulesConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/MacroRulesImpl.qll linguist-generated -/lib/codeql/rust/elements/internal/MacroStmtsConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/MacroStmtsImpl.qll linguist-generated /lib/codeql/rust/elements/internal/MacroTypeReprConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/MacroTypeReprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/MatchArmConstructor.qll linguist-generated @@ -553,13 +553,13 @@ /lib/codeql/rust/elements/internal/generated/Locatable.qll linguist-generated /lib/codeql/rust/elements/internal/generated/LoopExpr.qll linguist-generated /lib/codeql/rust/elements/internal/generated/LoopingExpr.qll linguist-generated +/lib/codeql/rust/elements/internal/generated/MacroBlockExpr.qll linguist-generated /lib/codeql/rust/elements/internal/generated/MacroCall.qll linguist-generated /lib/codeql/rust/elements/internal/generated/MacroDef.qll linguist-generated /lib/codeql/rust/elements/internal/generated/MacroExpr.qll linguist-generated /lib/codeql/rust/elements/internal/generated/MacroItems.qll linguist-generated /lib/codeql/rust/elements/internal/generated/MacroPat.qll linguist-generated /lib/codeql/rust/elements/internal/generated/MacroRules.qll linguist-generated -/lib/codeql/rust/elements/internal/generated/MacroStmts.qll linguist-generated /lib/codeql/rust/elements/internal/generated/MacroTypeRepr.qll linguist-generated /lib/codeql/rust/elements/internal/generated/MatchArm.qll linguist-generated /lib/codeql/rust/elements/internal/generated/MatchArmList.qll linguist-generated @@ -896,6 +896,9 @@ /test/extractor-tests/generated/LoopExpr/LoopExpr_getAttr.ql linguist-generated /test/extractor-tests/generated/LoopExpr/LoopExpr_getLabel.ql linguist-generated /test/extractor-tests/generated/LoopExpr/LoopExpr_getLoopBody.ql linguist-generated +/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr.ql linguist-generated +/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getStatement.ql linguist-generated +/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getTailExpr.ql linguist-generated /test/extractor-tests/generated/MacroCall/MacroCall.ql linguist-generated /test/extractor-tests/generated/MacroCall/MacroCall_getAttr.ql linguist-generated /test/extractor-tests/generated/MacroCall/MacroCall_getCrateOrigin.ql linguist-generated @@ -924,9 +927,6 @@ /test/extractor-tests/generated/MacroRules/MacroRules_getName.ql linguist-generated /test/extractor-tests/generated/MacroRules/MacroRules_getTokenTree.ql linguist-generated /test/extractor-tests/generated/MacroRules/MacroRules_getVisibility.ql linguist-generated -/test/extractor-tests/generated/MacroStmts/MacroStmts.ql linguist-generated -/test/extractor-tests/generated/MacroStmts/MacroStmts_getExpr.ql linguist-generated -/test/extractor-tests/generated/MacroStmts/MacroStmts_getStatement.ql linguist-generated /test/extractor-tests/generated/MacroTypeRepr/MacroTypeRepr.ql linguist-generated /test/extractor-tests/generated/MacroTypeRepr/MacroTypeRepr_getMacroCall.ql linguist-generated /test/extractor-tests/generated/MatchArm/MatchArm.ql linguist-generated diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll index 298d7e49438a..943e6ed020d8 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll @@ -107,7 +107,7 @@ class FormatTemplateVariableAccessTree extends LeafTree, FormatTemplateVariableA class ItemTree extends LeafTree, Item { ItemTree() { not this instanceof MacroCall and - this = [any(StmtList s).getAStatement(), any(MacroStmts s).getAStatement()] + this = [any(StmtList s).getAStatement(), any(MacroBlockExpr s).getAStatement()] } } @@ -146,12 +146,12 @@ class MacroCallTree extends StandardPostOrderTree, MacroCall { override AstNode getChildNode(int i) { i = 0 and result = this.getExpanded() } } -class MacroStmtsTree extends StandardPostOrderTree, MacroStmts { +class MacroBlockExprTree extends StandardPostOrderTree, MacroBlockExpr { override AstNode getChildNode(int i) { result = this.getStatement(i) or i = this.getNumberOfStatements() and - result = this.getExpr() + result = this.getTailExpr() } } diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll b/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll index 34ccb8d23818..f3cf52dab76c 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll @@ -1766,6 +1766,58 @@ module MakeCfgNodes Input> { predicate hasLoopBody() { exists(this.getLoopBody()) } } + final private class ParentMacroBlockExpr extends ParentAstNode, MacroBlockExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getTailExpr() + } + } + + /** + * A sequence of statements generated by a `MacroCall`. For example: + * ```rust + * fn main() { + * println!("Hello, world!"); // This macro expands into a list of statements + * } + * ``` + */ + final class MacroBlockExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private MacroBlockExpr node; + + MacroBlockExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `MacroBlockExpr`. */ + MacroBlockExpr getMacroBlockExpr() { result = node } + + /** + * Gets the tail expression of this macro block expression, if it exists. + */ + ExprCfgNode getTailExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getTailExpr(), this, result) + } + + /** + * Holds if `getTailExpr()` exists. + */ + predicate hasTailExpr() { exists(this.getTailExpr()) } + + /** + * Gets the `index`th statement of this macro block expression (0-based). + */ + Stmt getStatement(int index) { result = node.getStatement(index) } + + /** + * Gets any of the statements of this macro block expression. + */ + Stmt getAStatement() { result = this.getStatement(_) } + + /** + * Gets the number of statements of this macro block expression. + */ + int getNumberOfStatements() { result = count(int i | exists(this.getStatement(i))) } + } + final private class ParentMacroCall extends ParentAstNode, MacroCall { override predicate relevantChild(AstNode child) { none() } } @@ -1900,58 +1952,6 @@ module MakeCfgNodes Input> { predicate hasMacroCall() { exists(this.getMacroCall()) } } - final private class ParentMacroStmts extends ParentAstNode, MacroStmts { - override predicate relevantChild(AstNode child) { - none() - or - child = this.getExpr() - } - } - - /** - * A sequence of statements generated by a `MacroCall`. For example: - * ```rust - * fn main() { - * println!("Hello, world!"); // This macro expands into a list of statements - * } - * ``` - */ - final class MacroStmtsCfgNode extends CfgNodeFinal, ExprCfgNode { - private MacroStmts node; - - MacroStmtsCfgNode() { node = this.getAstNode() } - - /** Gets the underlying `MacroStmts`. */ - MacroStmts getMacroStmts() { result = node } - - /** - * Gets the expression of this macro statements, if it exists. - */ - ExprCfgNode getExpr() { - any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result) - } - - /** - * Holds if `getExpr()` exists. - */ - predicate hasExpr() { exists(this.getExpr()) } - - /** - * Gets the `index`th statement of this macro statements (0-based). - */ - Stmt getStatement(int index) { result = node.getStatement(index) } - - /** - * Gets any of the statements of this macro statements. - */ - Stmt getAStatement() { result = this.getStatement(_) } - - /** - * Gets the number of statements of this macro statements. - */ - int getNumberOfStatements() { result = count(int i | exists(this.getStatement(i))) } - } - final private class ParentMatchExpr extends ParentAstNode, MatchExpr { override predicate relevantChild(AstNode child) { none() @@ -3751,22 +3751,22 @@ module MakeCfgNodes Input> { cfgNode ) or - pred = "getMacroCall" and + pred = "getTailExpr" and parent = - any(Nodes::MacroExprCfgNode cfgNode, MacroExpr astNode | - astNode = cfgNode.getMacroExpr() and - child = getDesugared(astNode.getMacroCall()) and + any(Nodes::MacroBlockExprCfgNode cfgNode, MacroBlockExpr astNode | + astNode = cfgNode.getMacroBlockExpr() and + child = getDesugared(astNode.getTailExpr()) and i = -1 and hasCfgNode(child) and - not child = cfgNode.getMacroCall().getAstNode() + not child = cfgNode.getTailExpr().getAstNode() | cfgNode ) or pred = "getMacroCall" and parent = - any(Nodes::MacroPatCfgNode cfgNode, MacroPat astNode | - astNode = cfgNode.getMacroPat() and + any(Nodes::MacroExprCfgNode cfgNode, MacroExpr astNode | + astNode = cfgNode.getMacroExpr() and child = getDesugared(astNode.getMacroCall()) and i = -1 and hasCfgNode(child) and @@ -3775,14 +3775,14 @@ module MakeCfgNodes Input> { cfgNode ) or - pred = "getExpr" and + pred = "getMacroCall" and parent = - any(Nodes::MacroStmtsCfgNode cfgNode, MacroStmts astNode | - astNode = cfgNode.getMacroStmts() and - child = getDesugared(astNode.getExpr()) and + any(Nodes::MacroPatCfgNode cfgNode, MacroPat astNode | + astNode = cfgNode.getMacroPat() and + child = getDesugared(astNode.getMacroCall()) and i = -1 and hasCfgNode(child) and - not child = cfgNode.getExpr().getAstNode() + not child = cfgNode.getMacroCall().getAstNode() | cfgNode ) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll index f750fed04555..8aa6c921eefc 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll @@ -203,7 +203,7 @@ private ExprCfgNode getALastEvalNode(ExprCfgNode e) { result = e.(ReturnExprCfgNode).getExpr() or result = e.(BreakExprCfgNode).getExpr() or result = e.(BlockExprCfgNode).getTailExpr() or - result = e.(MacroStmtsCfgNode).getExpr() or + result = e.(MacroBlockExprCfgNode).getTailExpr() or result = e.(MatchExprCfgNode).getArmExpr(_) or result = e.(MacroExprCfgNode).getMacroCall().(MacroCallCfgNode).getExpandedNode() or result.(BreakExprCfgNode).getTarget() = e diff --git a/rust/ql/lib/codeql/rust/elements.qll b/rust/ql/lib/codeql/rust/elements.qll index 21c254b5d676..4456cb4b44ae 100644 --- a/rust/ql/lib/codeql/rust/elements.qll +++ b/rust/ql/lib/codeql/rust/elements.qll @@ -94,13 +94,13 @@ import codeql.rust.elements.LiteralPat import codeql.rust.elements.Locatable import codeql.rust.elements.LoopExpr import codeql.rust.elements.LoopingExpr +import codeql.rust.elements.MacroBlockExpr import codeql.rust.elements.MacroCall import codeql.rust.elements.MacroDef import codeql.rust.elements.MacroExpr import codeql.rust.elements.MacroItems import codeql.rust.elements.MacroPat import codeql.rust.elements.MacroRules -import codeql.rust.elements.MacroStmts import codeql.rust.elements.MacroTypeRepr import codeql.rust.elements.MatchArm import codeql.rust.elements.MatchArmList diff --git a/rust/ql/lib/codeql/rust/elements/MacroStmts.qll b/rust/ql/lib/codeql/rust/elements/MacroBlockExpr.qll similarity index 66% rename from rust/ql/lib/codeql/rust/elements/MacroStmts.qll rename to rust/ql/lib/codeql/rust/elements/MacroBlockExpr.qll index 9ef0c12b35fd..8fcd2119a0ae 100644 --- a/rust/ql/lib/codeql/rust/elements/MacroStmts.qll +++ b/rust/ql/lib/codeql/rust/elements/MacroBlockExpr.qll @@ -1,9 +1,9 @@ // generated by codegen, do not edit /** - * This module provides the public class `MacroStmts`. + * This module provides the public class `MacroBlockExpr`. */ -private import internal.MacroStmtsImpl +private import internal.MacroBlockExprImpl import codeql.rust.elements.Expr import codeql.rust.elements.Stmt @@ -15,4 +15,4 @@ import codeql.rust.elements.Stmt * } * ``` */ -final class MacroStmts = Impl::MacroStmts; +final class MacroBlockExpr = Impl::MacroBlockExpr; diff --git a/rust/ql/lib/codeql/rust/elements/internal/MacroStmtsConstructor.qll b/rust/ql/lib/codeql/rust/elements/internal/MacroBlockExprConstructor.qll similarity index 60% rename from rust/ql/lib/codeql/rust/elements/internal/MacroStmtsConstructor.qll rename to rust/ql/lib/codeql/rust/elements/internal/MacroBlockExprConstructor.qll index 6f5889551252..0bb4936209a3 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/MacroStmtsConstructor.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/MacroBlockExprConstructor.qll @@ -1,14 +1,14 @@ // generated by codegen, remove this comment if you wish to edit this file /** * This module defines the hook used internally to tweak the characteristic predicate of - * `MacroStmts` synthesized instances. + * `MacroBlockExpr` synthesized instances. * INTERNAL: Do not use. */ private import codeql.rust.elements.internal.generated.Raw /** - * The characteristic predicate of `MacroStmts` synthesized instances. + * The characteristic predicate of `MacroBlockExpr` synthesized instances. * INTERNAL: Do not use. */ -predicate constructMacroStmts(Raw::MacroStmts id) { any() } +predicate constructMacroBlockExpr(Raw::MacroBlockExpr id) { any() } diff --git a/rust/ql/lib/codeql/rust/elements/internal/MacroStmtsImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/MacroBlockExprImpl.qll similarity index 72% rename from rust/ql/lib/codeql/rust/elements/internal/MacroStmtsImpl.qll rename to rust/ql/lib/codeql/rust/elements/internal/MacroBlockExprImpl.qll index 8ec38e3c5266..60030dd6f278 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/MacroStmtsImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/MacroBlockExprImpl.qll @@ -1,14 +1,14 @@ // generated by codegen, remove this comment if you wish to edit this file /** - * This module provides a hand-modifiable wrapper around the generated class `MacroStmts`. + * This module provides a hand-modifiable wrapper around the generated class `MacroBlockExpr`. * * INTERNAL: Do not use. */ -private import codeql.rust.elements.internal.generated.MacroStmts +private import codeql.rust.elements.internal.generated.MacroBlockExpr /** - * INTERNAL: This module contains the customizable definition of `MacroStmts` and should not + * INTERNAL: This module contains the customizable definition of `MacroBlockExpr` and should not * be referenced directly. */ module Impl { @@ -20,5 +20,5 @@ module Impl { * } * ``` */ - class MacroStmts extends Generated::MacroStmts { } + class MacroBlockExpr extends Generated::MacroBlockExpr { } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/MacroBlockExpr.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/MacroBlockExpr.qll new file mode 100644 index 000000000000..3dd6411e20e8 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/MacroBlockExpr.qll @@ -0,0 +1,66 @@ +// generated by codegen, do not edit +/** + * This module provides the generated definition of `MacroBlockExpr`. + * INTERNAL: Do not import directly. + */ + +private import codeql.rust.elements.internal.generated.Synth +private import codeql.rust.elements.internal.generated.Raw +import codeql.rust.elements.Expr +import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl +import codeql.rust.elements.Stmt + +/** + * INTERNAL: This module contains the fully generated definition of `MacroBlockExpr` and should not + * be referenced directly. + */ +module Generated { + /** + * A sequence of statements generated by a `MacroCall`. For example: + * ```rust + * fn main() { + * println!("Hello, world!"); // This macro expands into a list of statements + * } + * ``` + * INTERNAL: Do not reference the `Generated::MacroBlockExpr` class directly. + * Use the subclass `MacroBlockExpr`, where the following predicates are available. + */ + class MacroBlockExpr extends Synth::TMacroBlockExpr, ExprImpl::Expr { + override string getAPrimaryQlClass() { result = "MacroBlockExpr" } + + /** + * Gets the tail expression of this macro block expression, if it exists. + */ + Expr getTailExpr() { + result = + Synth::convertExprFromRaw(Synth::convertMacroBlockExprToRaw(this) + .(Raw::MacroBlockExpr) + .getTailExpr()) + } + + /** + * Holds if `getTailExpr()` exists. + */ + final predicate hasTailExpr() { exists(this.getTailExpr()) } + + /** + * Gets the `index`th statement of this macro block expression (0-based). + */ + Stmt getStatement(int index) { + result = + Synth::convertStmtFromRaw(Synth::convertMacroBlockExprToRaw(this) + .(Raw::MacroBlockExpr) + .getStatement(index)) + } + + /** + * Gets any of the statements of this macro block expression. + */ + final Stmt getAStatement() { result = this.getStatement(_) } + + /** + * Gets the number of statements of this macro block expression. + */ + final int getNumberOfStatements() { result = count(int i | exists(this.getStatement(i))) } + } +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/MacroStmts.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/MacroStmts.qll deleted file mode 100644 index 636e0d1ea091..000000000000 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/MacroStmts.qll +++ /dev/null @@ -1,64 +0,0 @@ -// generated by codegen, do not edit -/** - * This module provides the generated definition of `MacroStmts`. - * INTERNAL: Do not import directly. - */ - -private import codeql.rust.elements.internal.generated.Synth -private import codeql.rust.elements.internal.generated.Raw -import codeql.rust.elements.Expr -import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl -import codeql.rust.elements.Stmt - -/** - * INTERNAL: This module contains the fully generated definition of `MacroStmts` and should not - * be referenced directly. - */ -module Generated { - /** - * A sequence of statements generated by a `MacroCall`. For example: - * ```rust - * fn main() { - * println!("Hello, world!"); // This macro expands into a list of statements - * } - * ``` - * INTERNAL: Do not reference the `Generated::MacroStmts` class directly. - * Use the subclass `MacroStmts`, where the following predicates are available. - */ - class MacroStmts extends Synth::TMacroStmts, ExprImpl::Expr { - override string getAPrimaryQlClass() { result = "MacroStmts" } - - /** - * Gets the expression of this macro statements, if it exists. - */ - Expr getExpr() { - result = - Synth::convertExprFromRaw(Synth::convertMacroStmtsToRaw(this).(Raw::MacroStmts).getExpr()) - } - - /** - * Holds if `getExpr()` exists. - */ - final predicate hasExpr() { exists(this.getExpr()) } - - /** - * Gets the `index`th statement of this macro statements (0-based). - */ - Stmt getStatement(int index) { - result = - Synth::convertStmtFromRaw(Synth::convertMacroStmtsToRaw(this) - .(Raw::MacroStmts) - .getStatement(index)) - } - - /** - * Gets any of the statements of this macro statements. - */ - final Stmt getAStatement() { result = this.getStatement(_) } - - /** - * Gets the number of statements of this macro statements. - */ - final int getNumberOfStatements() { result = count(int i | exists(this.getStatement(i))) } - } -} diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll index 57e18e373b8a..6bea3762de1d 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll @@ -2368,54 +2368,56 @@ private module Impl { ) } - private Element getImmediateChildOfMacroExpr(MacroExpr e, int index, string partialPredicateCall) { - exists(int b, int bExpr, int n, int nMacroCall | + private Element getImmediateChildOfMacroBlockExpr( + MacroBlockExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nTailExpr, int nStatement | b = 0 and bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and n = bExpr and - nMacroCall = n + 1 and + nTailExpr = n + 1 and + nStatement = nTailExpr + 1 + max(int i | i = -1 or exists(e.getStatement(i)) | i) and ( none() or result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) or - index = n and result = e.getMacroCall() and partialPredicateCall = "MacroCall()" + index = n and result = e.getTailExpr() and partialPredicateCall = "TailExpr()" + or + result = e.getStatement(index - nTailExpr) and + partialPredicateCall = "Statement(" + (index - nTailExpr).toString() + ")" ) ) } - private Element getImmediateChildOfMacroPat(MacroPat e, int index, string partialPredicateCall) { - exists(int b, int bPat, int n, int nMacroCall | + private Element getImmediateChildOfMacroExpr(MacroExpr e, int index, string partialPredicateCall) { + exists(int b, int bExpr, int n, int nMacroCall | b = 0 and - bPat = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfPat(e, i, _)) | i) and - n = bPat and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and nMacroCall = n + 1 and ( none() or - result = getImmediateChildOfPat(e, index - b, partialPredicateCall) + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) or index = n and result = e.getMacroCall() and partialPredicateCall = "MacroCall()" ) ) } - private Element getImmediateChildOfMacroStmts(MacroStmts e, int index, string partialPredicateCall) { - exists(int b, int bExpr, int n, int nExpr, int nStatement | + private Element getImmediateChildOfMacroPat(MacroPat e, int index, string partialPredicateCall) { + exists(int b, int bPat, int n, int nMacroCall | b = 0 and - bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and - n = bExpr and - nExpr = n + 1 and - nStatement = nExpr + 1 + max(int i | i = -1 or exists(e.getStatement(i)) | i) and + bPat = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfPat(e, i, _)) | i) and + n = bPat and + nMacroCall = n + 1 and ( none() or - result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) - or - index = n and result = e.getExpr() and partialPredicateCall = "Expr()" + result = getImmediateChildOfPat(e, index - b, partialPredicateCall) or - result = e.getStatement(index - nExpr) and - partialPredicateCall = "Statement(" + (index - nExpr).toString() + ")" + index = n and result = e.getMacroCall() and partialPredicateCall = "MacroCall()" ) ) } @@ -4298,12 +4300,12 @@ private module Impl { or result = getImmediateChildOfLiteralPat(e, index, partialAccessor) or + result = getImmediateChildOfMacroBlockExpr(e, index, partialAccessor) + or result = getImmediateChildOfMacroExpr(e, index, partialAccessor) or result = getImmediateChildOfMacroPat(e, index, partialAccessor) or - result = getImmediateChildOfMacroStmts(e, index, partialAccessor) - or result = getImmediateChildOfMacroTypeRepr(e, index, partialAccessor) or result = getImmediateChildOfMatchExpr(e, index, partialAccessor) diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll index b1e26574de14..0869ec4de5ab 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll @@ -2346,6 +2346,29 @@ module Raw { LiteralExpr getLiteral() { literal_pat_literals(this, result) } } + /** + * INTERNAL: Do not use. + * A sequence of statements generated by a `MacroCall`. For example: + * ```rust + * fn main() { + * println!("Hello, world!"); // This macro expands into a list of statements + * } + * ``` + */ + class MacroBlockExpr extends @macro_block_expr, Expr { + override string toString() { result = "MacroBlockExpr" } + + /** + * Gets the tail expression of this macro block expression, if it exists. + */ + Expr getTailExpr() { macro_block_expr_tail_exprs(this, result) } + + /** + * Gets the `index`th statement of this macro block expression (0-based). + */ + Stmt getStatement(int index) { macro_block_expr_statements(this, index, result) } + } + /** * INTERNAL: Do not use. * A MacroExpr. For example: @@ -2378,29 +2401,6 @@ module Raw { MacroCall getMacroCall() { macro_pat_macro_calls(this, result) } } - /** - * INTERNAL: Do not use. - * A sequence of statements generated by a `MacroCall`. For example: - * ```rust - * fn main() { - * println!("Hello, world!"); // This macro expands into a list of statements - * } - * ``` - */ - class MacroStmts extends @macro_stmts, Expr { - override string toString() { result = "MacroStmts" } - - /** - * Gets the expression of this macro statements, if it exists. - */ - Expr getExpr() { macro_stmts_exprs(this, result) } - - /** - * Gets the `index`th statement of this macro statements (0-based). - */ - Stmt getStatement(int index) { macro_stmts_statements(this, index, result) } - } - /** * INTERNAL: Do not use. * A MacroTypeRepr. For example: diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll index abc696eb51e8..04588e2861e7 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll @@ -318,6 +318,10 @@ module Synth { * INTERNAL: Do not use. */ TLoopExpr(Raw::LoopExpr id) { constructLoopExpr(id) } or + /** + * INTERNAL: Do not use. + */ + TMacroBlockExpr(Raw::MacroBlockExpr id) { constructMacroBlockExpr(id) } or /** * INTERNAL: Do not use. */ @@ -342,10 +346,6 @@ module Synth { * INTERNAL: Do not use. */ TMacroRules(Raw::MacroRules id) { constructMacroRules(id) } or - /** - * INTERNAL: Do not use. - */ - TMacroStmts(Raw::MacroStmts id) { constructMacroStmts(id) } or /** * INTERNAL: Do not use. */ @@ -742,9 +742,9 @@ module Synth { TArrayExpr or TArrayExprInternal or TAsmExpr or TAwaitExpr or TBecomeExpr or TBinaryExpr or TBreakExpr or TCallExprBase or TCastExpr or TClosureExpr or TContinueExpr or TFieldExpr or TFormatArgsExpr or TIfExpr or TIndexExpr or TLabelableExpr or TLetExpr or TLiteralExpr or - TMacroExpr or TMacroStmts or TMatchExpr or TOffsetOfExpr or TParenExpr or TPathExprBase or - TPrefixExpr or TRangeExpr or TRefExpr or TReturnExpr or TStructExpr or TTryExpr or - TTupleExpr or TUnderscoreExpr or TYeetExpr or TYieldExpr; + TMacroBlockExpr or TMacroExpr or TMatchExpr or TOffsetOfExpr or TParenExpr or + TPathExprBase or TPrefixExpr or TRangeExpr or TRefExpr or TReturnExpr or TStructExpr or + TTryExpr or TTupleExpr or TUnderscoreExpr or TYeetExpr or TYieldExpr; /** * INTERNAL: Do not use. @@ -1300,6 +1300,12 @@ module Synth { */ TLoopExpr convertLoopExprFromRaw(Raw::Element e) { result = TLoopExpr(e) } + /** + * INTERNAL: Do not use. + * Converts a raw element to a synthesized `TMacroBlockExpr`, if possible. + */ + TMacroBlockExpr convertMacroBlockExprFromRaw(Raw::Element e) { result = TMacroBlockExpr(e) } + /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TMacroCall`, if possible. @@ -1336,12 +1342,6 @@ module Synth { */ TMacroRules convertMacroRulesFromRaw(Raw::Element e) { result = TMacroRules(e) } - /** - * INTERNAL: Do not use. - * Converts a raw element to a synthesized `TMacroStmts`, if possible. - */ - TMacroStmts convertMacroStmtsFromRaw(Raw::Element e) { result = TMacroStmts(e) } - /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TMacroTypeRepr`, if possible. @@ -2125,9 +2125,9 @@ module Synth { or result = convertLiteralExprFromRaw(e) or - result = convertMacroExprFromRaw(e) + result = convertMacroBlockExprFromRaw(e) or - result = convertMacroStmtsFromRaw(e) + result = convertMacroExprFromRaw(e) or result = convertMatchExprFromRaw(e) or @@ -2900,6 +2900,12 @@ module Synth { */ Raw::Element convertLoopExprToRaw(TLoopExpr e) { e = TLoopExpr(result) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TMacroBlockExpr` to a raw DB element, if possible. + */ + Raw::Element convertMacroBlockExprToRaw(TMacroBlockExpr e) { e = TMacroBlockExpr(result) } + /** * INTERNAL: Do not use. * Converts a synthesized `TMacroCall` to a raw DB element, if possible. @@ -2936,12 +2942,6 @@ module Synth { */ Raw::Element convertMacroRulesToRaw(TMacroRules e) { e = TMacroRules(result) } - /** - * INTERNAL: Do not use. - * Converts a synthesized `TMacroStmts` to a raw DB element, if possible. - */ - Raw::Element convertMacroStmtsToRaw(TMacroStmts e) { e = TMacroStmts(result) } - /** * INTERNAL: Do not use. * Converts a synthesized `TMacroTypeRepr` to a raw DB element, if possible. @@ -3725,9 +3725,9 @@ module Synth { or result = convertLiteralExprToRaw(e) or - result = convertMacroExprToRaw(e) + result = convertMacroBlockExprToRaw(e) or - result = convertMacroStmtsToRaw(e) + result = convertMacroExprToRaw(e) or result = convertMatchExprToRaw(e) or diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/SynthConstructors.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/SynthConstructors.qll index 9be635b767ed..e6ff3af47154 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/SynthConstructors.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/SynthConstructors.qll @@ -77,13 +77,13 @@ import codeql.rust.elements.internal.LifetimeParamConstructor import codeql.rust.elements.internal.LiteralExprConstructor import codeql.rust.elements.internal.LiteralPatConstructor import codeql.rust.elements.internal.LoopExprConstructor +import codeql.rust.elements.internal.MacroBlockExprConstructor import codeql.rust.elements.internal.MacroCallConstructor import codeql.rust.elements.internal.MacroDefConstructor import codeql.rust.elements.internal.MacroExprConstructor import codeql.rust.elements.internal.MacroItemsConstructor import codeql.rust.elements.internal.MacroPatConstructor import codeql.rust.elements.internal.MacroRulesConstructor -import codeql.rust.elements.internal.MacroStmtsConstructor import codeql.rust.elements.internal.MacroTypeReprConstructor import codeql.rust.elements.internal.MatchArmConstructor import codeql.rust.elements.internal.MatchArmListConstructor diff --git a/rust/ql/lib/rust.dbscheme b/rust/ql/lib/rust.dbscheme index 48a13c5eec36..58bc96172f5a 100644 --- a/rust/ql/lib/rust.dbscheme +++ b/rust/ql/lib/rust.dbscheme @@ -437,8 +437,8 @@ closure_binder_generic_param_lists( | @labelable_expr | @let_expr | @literal_expr +| @macro_block_expr | @macro_expr -| @macro_stmts | @match_expr | @offset_of_expr | @paren_expr @@ -2081,6 +2081,23 @@ literal_pat_literals( int literal: @literal_expr ref ); +macro_block_exprs( + unique int id: @macro_block_expr +); + +#keyset[id] +macro_block_expr_tail_exprs( + int id: @macro_block_expr ref, + int tail_expr: @expr ref +); + +#keyset[id, index] +macro_block_expr_statements( + int id: @macro_block_expr ref, + int index: int ref, + int statement: @stmt ref +); + macro_exprs( unique int id: @macro_expr ); @@ -2101,23 +2118,6 @@ macro_pat_macro_calls( int macro_call: @macro_call ref ); -macro_stmts( - unique int id: @macro_stmts -); - -#keyset[id] -macro_stmts_exprs( - int id: @macro_stmts ref, - int expr: @expr ref -); - -#keyset[id, index] -macro_stmts_statements( - int id: @macro_stmts ref, - int index: int ref, - int statement: @stmt ref -); - macro_type_reprs( unique int id: @macro_type_repr ); diff --git a/rust/ql/test/extractor-tests/generated/.generated_tests.list b/rust/ql/test/extractor-tests/generated/.generated_tests.list index 56cb7ed62e12..13778503766e 100644 --- a/rust/ql/test/extractor-tests/generated/.generated_tests.list +++ b/rust/ql/test/extractor-tests/generated/.generated_tests.list @@ -56,13 +56,13 @@ LifetimeParam/gen_lifetime_param.rs 2caed50ce48360681271e4e89fde0d6d9076ebb9cd9c LiteralExpr/gen_literal_expr.rs 2db01ad390e5c0c63a957c043230a462cb4cc25715eea6ede15d43c55d35976d 2db01ad390e5c0c63a957c043230a462cb4cc25715eea6ede15d43c55d35976d LiteralPat/gen_literal_pat.rs a471b481b6989001817a3988696f445d9a4dea784e543c346536dacbee1e96f3 a471b481b6989001817a3988696f445d9a4dea784e543c346536dacbee1e96f3 LoopExpr/gen_loop_expr.rs 35deaf35e765db4ae3124a11284266d8f341d1ce7b700030efada0dda8878619 35deaf35e765db4ae3124a11284266d8f341d1ce7b700030efada0dda8878619 +MacroBlockExpr/gen_macro_block_expr.rs 2e45dcf44bf2e8404b49ce9abeee4931572693174b5d96f3fd81eb40ea8e7b4b 2e45dcf44bf2e8404b49ce9abeee4931572693174b5d96f3fd81eb40ea8e7b4b MacroCall/gen_macro_call.rs 139ef2c69323eea1a901e260d4e2acdd00b26f013b90c9344f48c6503ce29d79 139ef2c69323eea1a901e260d4e2acdd00b26f013b90c9344f48c6503ce29d79 MacroDef/gen_macro_def.rs 17c5387fb464a60b4a4520d22b055ba35ff23e9fe431a18a33808ae02c4bbff5 17c5387fb464a60b4a4520d22b055ba35ff23e9fe431a18a33808ae02c4bbff5 MacroExpr/gen_macro_expr.rs 3c23dc88fcc4bc8f97d9364d2f367671a0a5a63d07e52237d28204b64756dcdb 3c23dc88fcc4bc8f97d9364d2f367671a0a5a63d07e52237d28204b64756dcdb MacroItems/gen_macro_items.rs 8ef3e16b73635dc97afa3ffa4db2bb21a8f1b435176861a594b0200cc5b9b931 8ef3e16b73635dc97afa3ffa4db2bb21a8f1b435176861a594b0200cc5b9b931 MacroPat/gen_macro_pat.rs b8041370598bd7fb26778d829a15c415c2078d69124f6af634ddeba13a114aa0 b8041370598bd7fb26778d829a15c415c2078d69124f6af634ddeba13a114aa0 MacroRules/gen_macro_rules.rs 7e03b410f4669e422d3b4328f7aafdca2e286e5d951495dd69cee0d44cb793a9 7e03b410f4669e422d3b4328f7aafdca2e286e5d951495dd69cee0d44cb793a9 -MacroStmts/gen_macro_stmts.rs 2e45dcf44bf2e8404b49ce9abeee4931572693174b5d96f3fd81eb40ea8e7b4b 2e45dcf44bf2e8404b49ce9abeee4931572693174b5d96f3fd81eb40ea8e7b4b MacroTypeRepr/gen_macro_type_repr.rs 03c15f1fd5af63821e49a125d236704c63889fe20a32f03f3ecf3e29b1cad9df 03c15f1fd5af63821e49a125d236704c63889fe20a32f03f3ecf3e29b1cad9df MatchArm/gen_match_arm.rs ac75b4836a103e2755bd47a1ee1b74af6eb8349adc4ebedaaa27b3ea3ae41aa5 ac75b4836a103e2755bd47a1ee1b74af6eb8349adc4ebedaaa27b3ea3ae41aa5 MatchArmList/gen_match_arm_list.rs dbf36444d371421a2b8768a188660dd45ed3b823fb1c56b90c1ba77f177d23d6 dbf36444d371421a2b8768a188660dd45ed3b823fb1c56b90c1ba77f177d23d6 diff --git a/rust/ql/test/extractor-tests/generated/.gitattributes b/rust/ql/test/extractor-tests/generated/.gitattributes index 133c01c05cd0..9452518fe36c 100644 --- a/rust/ql/test/extractor-tests/generated/.gitattributes +++ b/rust/ql/test/extractor-tests/generated/.gitattributes @@ -58,13 +58,13 @@ /LiteralExpr/gen_literal_expr.rs linguist-generated /LiteralPat/gen_literal_pat.rs linguist-generated /LoopExpr/gen_loop_expr.rs linguist-generated +/MacroBlockExpr/gen_macro_block_expr.rs linguist-generated /MacroCall/gen_macro_call.rs linguist-generated /MacroDef/gen_macro_def.rs linguist-generated /MacroExpr/gen_macro_expr.rs linguist-generated /MacroItems/gen_macro_items.rs linguist-generated /MacroPat/gen_macro_pat.rs linguist-generated /MacroRules/gen_macro_rules.rs linguist-generated -/MacroStmts/gen_macro_stmts.rs linguist-generated /MacroTypeRepr/gen_macro_type_repr.rs linguist-generated /MatchArm/gen_match_arm.rs linguist-generated /MatchArmList/gen_match_arm_list.rs linguist-generated diff --git a/rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr.expected b/rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr.expected new file mode 100644 index 000000000000..4bf0740b930f --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr.expected @@ -0,0 +1 @@ +| gen_macro_block_expr.rs:5:14:5:28 | MacroBlockExpr | hasTailExpr: | yes | getNumberOfStatements: | 0 | diff --git a/rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr.ql b/rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr.ql new file mode 100644 index 000000000000..c003ca232f1e --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr.ql @@ -0,0 +1,11 @@ +// generated by codegen, do not edit +import codeql.rust.elements +import TestUtils + +from MacroBlockExpr x, string hasTailExpr, int getNumberOfStatements +where + toBeTested(x) and + not x.isUnknown() and + (if x.hasTailExpr() then hasTailExpr = "yes" else hasTailExpr = "no") and + getNumberOfStatements = x.getNumberOfStatements() +select x, "hasTailExpr:", hasTailExpr, "getNumberOfStatements:", getNumberOfStatements diff --git a/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getStatement.expected b/rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getStatement.expected similarity index 100% rename from rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getStatement.expected rename to rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getStatement.expected diff --git a/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getStatement.ql b/rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getStatement.ql similarity index 83% rename from rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getStatement.ql rename to rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getStatement.ql index 0d0743de096e..a5d58c0e32d1 100644 --- a/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getStatement.ql +++ b/rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getStatement.ql @@ -2,6 +2,6 @@ import codeql.rust.elements import TestUtils -from MacroStmts x, int index +from MacroBlockExpr x, int index where toBeTested(x) and not x.isUnknown() select x, index, x.getStatement(index) diff --git a/rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getTailExpr.expected b/rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getTailExpr.expected new file mode 100644 index 000000000000..ed7fbf364cf0 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getTailExpr.expected @@ -0,0 +1 @@ +| gen_macro_block_expr.rs:5:14:5:28 | MacroBlockExpr | gen_macro_block_expr.rs:5:14:5:28 | { ... } | diff --git a/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getExpr.ql b/rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getTailExpr.ql similarity index 72% rename from rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getExpr.ql rename to rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getTailExpr.ql index f03854ddb147..4fdb10bc3513 100644 --- a/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getExpr.ql +++ b/rust/ql/test/extractor-tests/generated/MacroBlockExpr/MacroBlockExpr_getTailExpr.ql @@ -2,6 +2,6 @@ import codeql.rust.elements import TestUtils -from MacroStmts x +from MacroBlockExpr x where toBeTested(x) and not x.isUnknown() -select x, x.getExpr() +select x, x.getTailExpr() diff --git a/rust/ql/test/extractor-tests/generated/MacroStmts/gen_macro_stmts.rs b/rust/ql/test/extractor-tests/generated/MacroBlockExpr/gen_macro_block_expr.rs similarity index 100% rename from rust/ql/test/extractor-tests/generated/MacroStmts/gen_macro_stmts.rs rename to rust/ql/test/extractor-tests/generated/MacroBlockExpr/gen_macro_block_expr.rs diff --git a/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getExpanded.expected b/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getExpanded.expected index 1b60df41f797..f4bb40db46b8 100644 --- a/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getExpanded.expected +++ b/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getExpanded.expected @@ -1 +1 @@ -| gen_macro_call.rs:5:5:5:11 | todo!... | gen_macro_call.rs:5:5:5:11 | MacroStmts | +| gen_macro_call.rs:5:5:5:11 | todo!... | gen_macro_call.rs:5:5:5:11 | MacroBlockExpr | diff --git a/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts.expected b/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts.expected deleted file mode 100644 index e74a5e4e8575..000000000000 --- a/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts.expected +++ /dev/null @@ -1 +0,0 @@ -| gen_macro_stmts.rs:5:14:5:28 | MacroStmts | hasExpr: | yes | getNumberOfStatements: | 0 | diff --git a/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts.ql b/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts.ql deleted file mode 100644 index 189e280605ce..000000000000 --- a/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts.ql +++ /dev/null @@ -1,11 +0,0 @@ -// generated by codegen, do not edit -import codeql.rust.elements -import TestUtils - -from MacroStmts x, string hasExpr, int getNumberOfStatements -where - toBeTested(x) and - not x.isUnknown() and - (if x.hasExpr() then hasExpr = "yes" else hasExpr = "no") and - getNumberOfStatements = x.getNumberOfStatements() -select x, "hasExpr:", hasExpr, "getNumberOfStatements:", getNumberOfStatements diff --git a/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getExpr.expected b/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getExpr.expected deleted file mode 100644 index d1390595304e..000000000000 --- a/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getExpr.expected +++ /dev/null @@ -1 +0,0 @@ -| gen_macro_stmts.rs:5:14:5:28 | MacroStmts | gen_macro_stmts.rs:5:14:5:28 | { ... } | diff --git a/rust/ql/test/library-tests/controlflow/Cfg.expected b/rust/ql/test/library-tests/controlflow/Cfg.expected index 0b79e26e95a7..b51f42537d11 100644 --- a/rust/ql/test/library-tests/controlflow/Cfg.expected +++ b/rust/ql/test/library-tests/controlflow/Cfg.expected @@ -397,9 +397,9 @@ edges | test.rs:171:26:171:28 | ...::format_args_nl!... | test.rs:171:26:171:28 | MacroExpr | | | test.rs:171:26:171:28 | ExprStmt | test.rs:171:17:171:29 | ...::_print | | | test.rs:171:26:171:28 | FormatArgsExpr | test.rs:171:26:171:28 | ...::format_args_nl!... | | +| test.rs:171:26:171:28 | MacroBlockExpr | test.rs:171:17:171:29 | println!... | | | test.rs:171:26:171:28 | MacroExpr | test.rs:171:26:171:28 | ...::_print(...) | | -| test.rs:171:26:171:28 | MacroStmts | test.rs:171:17:171:29 | println!... | | -| test.rs:171:26:171:28 | { ... } | test.rs:171:26:171:28 | MacroStmts | | +| test.rs:171:26:171:28 | { ... } | test.rs:171:26:171:28 | MacroBlockExpr | | | test.rs:172:20:174:13 | { ... } | test.rs:170:13:174:13 | if cond2 {...} else {...} | | | test.rs:173:17:173:29 | ...::_print | test.rs:173:26:173:28 | "2\\n" | | | test.rs:173:17:173:29 | MacroExpr | test.rs:172:20:174:13 | { ... } | | @@ -410,9 +410,9 @@ edges | test.rs:173:26:173:28 | ...::format_args_nl!... | test.rs:173:26:173:28 | MacroExpr | | | test.rs:173:26:173:28 | ExprStmt | test.rs:173:17:173:29 | ...::_print | | | test.rs:173:26:173:28 | FormatArgsExpr | test.rs:173:26:173:28 | ...::format_args_nl!... | | +| test.rs:173:26:173:28 | MacroBlockExpr | test.rs:173:17:173:29 | println!... | | | test.rs:173:26:173:28 | MacroExpr | test.rs:173:26:173:28 | ...::_print(...) | | -| test.rs:173:26:173:28 | MacroStmts | test.rs:173:17:173:29 | println!... | | -| test.rs:173:26:173:28 | { ... } | test.rs:173:26:173:28 | MacroStmts | | +| test.rs:173:26:173:28 | { ... } | test.rs:173:26:173:28 | MacroBlockExpr | | | test.rs:175:13:175:25 | ...::_print | test.rs:175:22:175:24 | "3\\n" | | | test.rs:175:13:175:25 | MacroExpr | test.rs:169:18:176:9 | { ... } | | | test.rs:175:13:175:25 | println!... | test.rs:175:13:175:25 | MacroExpr | | @@ -422,9 +422,9 @@ edges | test.rs:175:22:175:24 | ...::format_args_nl!... | test.rs:175:22:175:24 | MacroExpr | | | test.rs:175:22:175:24 | ExprStmt | test.rs:175:13:175:25 | ...::_print | | | test.rs:175:22:175:24 | FormatArgsExpr | test.rs:175:22:175:24 | ...::format_args_nl!... | | +| test.rs:175:22:175:24 | MacroBlockExpr | test.rs:175:13:175:25 | println!... | | | test.rs:175:22:175:24 | MacroExpr | test.rs:175:22:175:24 | ...::_print(...) | | -| test.rs:175:22:175:24 | MacroStmts | test.rs:175:13:175:25 | println!... | | -| test.rs:175:22:175:24 | { ... } | test.rs:175:22:175:24 | MacroStmts | | +| test.rs:175:22:175:24 | { ... } | test.rs:175:22:175:24 | MacroBlockExpr | | | test.rs:179:5:188:5 | enter fn test_nested_if_match | test.rs:179:29:179:29 | a | | | test.rs:179:5:188:5 | exit fn test_nested_if_match (normal) | test.rs:179:5:188:5 | exit fn test_nested_if_match | | | test.rs:179:29:179:29 | a | test.rs:179:29:179:29 | a | | @@ -902,11 +902,11 @@ edges | test.rs:363:39:363:53 | ...::panic_fmt(...) | test.rs:363:39:363:53 | { ... } | | | test.rs:363:39:363:53 | ExprStmt | test.rs:363:32:363:54 | ...::panic_fmt | | | test.rs:363:39:363:53 | FormatArgsExpr | test.rs:363:39:363:53 | ...::const_format_args!... | | +| test.rs:363:39:363:53 | MacroBlockExpr | test.rs:363:32:363:54 | panic!... | | +| test.rs:363:39:363:53 | MacroBlockExpr | test.rs:363:39:363:53 | ...::panic_2021!... | | | test.rs:363:39:363:53 | MacroExpr | test.rs:363:39:363:53 | ...::panic_fmt(...) | | -| test.rs:363:39:363:53 | MacroExpr | test.rs:363:39:363:53 | MacroStmts | | -| test.rs:363:39:363:53 | MacroStmts | test.rs:363:32:363:54 | panic!... | | -| test.rs:363:39:363:53 | MacroStmts | test.rs:363:39:363:53 | ...::panic_2021!... | | -| test.rs:363:39:363:53 | { ... } | test.rs:363:39:363:53 | MacroStmts | | +| test.rs:363:39:363:53 | MacroExpr | test.rs:363:39:363:53 | MacroBlockExpr | | +| test.rs:363:39:363:53 | { ... } | test.rs:363:39:363:53 | MacroBlockExpr | | | test.rs:364:9:364:9 | n | test.rs:362:46:365:5 | { ... } | | | test.rs:367:5:373:5 | enter fn test_let_with_return | test.rs:367:29:367:29 | m | | | test.rs:367:5:373:5 | exit fn test_let_with_return (normal) | test.rs:367:5:373:5 | exit fn test_let_with_return | | @@ -1189,9 +1189,9 @@ edges | test.rs:495:18:495:32 | ...::format_args_nl!... | test.rs:495:18:495:32 | MacroExpr | | | test.rs:495:18:495:32 | ExprStmt | test.rs:495:9:495:33 | ...::_print | | | test.rs:495:18:495:32 | FormatArgsExpr | test.rs:495:18:495:32 | ...::format_args_nl!... | | +| test.rs:495:18:495:32 | MacroBlockExpr | test.rs:495:9:495:33 | println!... | | | test.rs:495:18:495:32 | MacroExpr | test.rs:495:18:495:32 | ...::_print(...) | | -| test.rs:495:18:495:32 | MacroStmts | test.rs:495:9:495:33 | println!... | | -| test.rs:495:18:495:32 | { ... } | test.rs:495:18:495:32 | MacroStmts | | +| test.rs:495:18:495:32 | { ... } | test.rs:495:18:495:32 | MacroBlockExpr | | | test.rs:498:5:517:5 | enter fn async_block | test.rs:498:26:498:26 | b | | | test.rs:498:5:517:5 | exit fn async_block (normal) | test.rs:498:5:517:5 | exit fn async_block | | | test.rs:498:26:498:26 | b | test.rs:498:26:498:26 | b | | @@ -1213,9 +1213,9 @@ edges | test.rs:500:22:500:40 | ...::format_args_nl!... | test.rs:500:22:500:40 | MacroExpr | | | test.rs:500:22:500:40 | ExprStmt | test.rs:500:13:500:41 | ...::_print | | | test.rs:500:22:500:40 | FormatArgsExpr | test.rs:500:22:500:40 | ...::format_args_nl!... | | +| test.rs:500:22:500:40 | MacroBlockExpr | test.rs:500:13:500:41 | println!... | | | test.rs:500:22:500:40 | MacroExpr | test.rs:500:22:500:40 | ...::_print(...) | | -| test.rs:500:22:500:40 | MacroStmts | test.rs:500:13:500:41 | println!... | | -| test.rs:500:22:500:40 | { ... } | test.rs:500:22:500:40 | MacroStmts | | +| test.rs:500:22:500:40 | { ... } | test.rs:500:22:500:40 | MacroBlockExpr | | | test.rs:502:9:504:10 | let ... = ... | test.rs:502:31:504:9 | { ... } | | | test.rs:502:13:502:27 | say_how_are_you | test.rs:502:13:502:27 | say_how_are_you | | | test.rs:502:13:502:27 | say_how_are_you | test.rs:505:9:505:28 | let ... = ... | match | @@ -1231,9 +1231,9 @@ edges | test.rs:503:22:503:35 | ...::format_args_nl!... | test.rs:503:22:503:35 | MacroExpr | | | test.rs:503:22:503:35 | ExprStmt | test.rs:503:13:503:36 | ...::_print | | | test.rs:503:22:503:35 | FormatArgsExpr | test.rs:503:22:503:35 | ...::format_args_nl!... | | +| test.rs:503:22:503:35 | MacroBlockExpr | test.rs:503:13:503:36 | println!... | | | test.rs:503:22:503:35 | MacroExpr | test.rs:503:22:503:35 | ...::_print(...) | | -| test.rs:503:22:503:35 | MacroStmts | test.rs:503:13:503:36 | println!... | | -| test.rs:503:22:503:35 | { ... } | test.rs:503:22:503:35 | MacroStmts | | +| test.rs:503:22:503:35 | { ... } | test.rs:503:22:503:35 | MacroBlockExpr | | | test.rs:505:9:505:28 | let ... = ... | test.rs:505:20:505:27 | { ... } | | | test.rs:505:13:505:16 | noop | test.rs:505:13:505:16 | noop | | | test.rs:505:13:505:16 | noop | test.rs:506:9:506:26 | ExprStmt | match | @@ -1292,16 +1292,16 @@ edges | test.rs:533:13:533:49 | ...::panic_explicit(...) | test.rs:533:13:533:49 | { ... } | | | test.rs:533:13:533:49 | ExprStmt | test.rs:533:13:533:49 | fn panic_cold_explicit | | | test.rs:533:13:533:49 | ExprStmt | test.rs:533:13:533:49 | panic_cold_explicit | | +| test.rs:533:13:533:49 | MacroBlockExpr | test.rs:533:13:533:49 | ...::panic_2021!... | | | test.rs:533:13:533:49 | MacroExpr | test.rs:532:9:534:9 | { ... } | | | test.rs:533:13:533:49 | MacroExpr | test.rs:533:13:533:49 | { ... } | | -| test.rs:533:13:533:49 | MacroStmts | test.rs:533:13:533:49 | ...::panic_2021!... | | | test.rs:533:13:533:49 | assert!... | test.rs:533:13:533:49 | MacroExpr | | | test.rs:533:13:533:49 | enter fn panic_cold_explicit | test.rs:533:13:533:49 | ...::panic_explicit | | | test.rs:533:13:533:49 | exit fn panic_cold_explicit (normal) | test.rs:533:13:533:49 | exit fn panic_cold_explicit | | | test.rs:533:13:533:49 | fn panic_cold_explicit | test.rs:533:13:533:49 | ExprStmt | | | test.rs:533:13:533:49 | panic_cold_explicit | test.rs:533:13:533:49 | panic_cold_explicit(...) | | | test.rs:533:13:533:49 | panic_cold_explicit(...) | test.rs:533:13:533:49 | { ... } | | -| test.rs:533:13:533:49 | { ... } | test.rs:533:13:533:49 | MacroStmts | | +| test.rs:533:13:533:49 | { ... } | test.rs:533:13:533:49 | MacroBlockExpr | | | test.rs:533:13:533:49 | { ... } | test.rs:533:13:533:49 | exit fn panic_cold_explicit (normal) | | | test.rs:533:13:533:49 | { ... } | test.rs:533:21:533:48 | if ... {...} | | | test.rs:533:13:533:50 | ExprStmt | test.rs:533:21:533:42 | ...::size_of::<...> | | @@ -1309,11 +1309,11 @@ edges | test.rs:533:21:533:44 | ...::size_of::<...>(...) | test.rs:533:48:533:48 | 0 | | | test.rs:533:21:533:48 | ... > ... | test.rs:533:21:533:48 | [boolean(false)] ! ... | true | | test.rs:533:21:533:48 | ... > ... | test.rs:533:21:533:48 | [boolean(true)] ! ... | false | -| test.rs:533:21:533:48 | MacroStmts | test.rs:533:13:533:49 | assert!... | | +| test.rs:533:21:533:48 | MacroBlockExpr | test.rs:533:13:533:49 | assert!... | | | test.rs:533:21:533:48 | [boolean(false)] ! ... | test.rs:533:21:533:48 | if ... {...} | false | | test.rs:533:21:533:48 | [boolean(true)] ! ... | test.rs:533:13:533:49 | ExprStmt | true | | test.rs:533:21:533:48 | if ... {...} | test.rs:533:21:533:48 | { ... } | | -| test.rs:533:21:533:48 | { ... } | test.rs:533:21:533:48 | MacroStmts | | +| test.rs:533:21:533:48 | { ... } | test.rs:533:21:533:48 | MacroBlockExpr | | | test.rs:533:48:533:48 | 0 | test.rs:533:21:533:48 | ... > ... | | | test.rs:536:9:536:10 | 42 | test.rs:529:41:537:5 | { ... } | | | test.rs:539:5:548:5 | enter fn const_block_panic | test.rs:540:9:540:30 | Const | | diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index 123e8801649f..0cd59e281153 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -10,17 +10,17 @@ localStep | main.rs:6:9:6:9 | s | main.rs:6:9:6:9 | s | | main.rs:6:9:6:14 | ...: i64 | main.rs:6:9:6:9 | s | | main.rs:7:14:7:20 | FormatArgsExpr | main.rs:7:14:7:20 | MacroExpr | -| main.rs:7:14:7:20 | MacroStmts | main.rs:7:5:7:21 | MacroExpr | +| main.rs:7:14:7:20 | MacroBlockExpr | main.rs:7:5:7:21 | MacroExpr | | main.rs:7:14:7:20 | [post] MacroExpr | main.rs:7:14:7:20 | [post] FormatArgsExpr | -| main.rs:7:14:7:20 | { ... } | main.rs:7:14:7:20 | MacroStmts | +| main.rs:7:14:7:20 | { ... } | main.rs:7:14:7:20 | MacroBlockExpr | | main.rs:10:13:10:14 | [SSA] sr | main.rs:11:20:11:21 | sr | | main.rs:10:13:10:14 | sr | main.rs:10:13:10:14 | [SSA] sr | | main.rs:10:13:10:14 | sr | main.rs:10:13:10:14 | sr | | main.rs:10:13:10:20 | ...: ... | main.rs:10:13:10:14 | sr | | main.rs:11:14:11:21 | FormatArgsExpr | main.rs:11:14:11:21 | MacroExpr | -| main.rs:11:14:11:21 | MacroStmts | main.rs:11:5:11:22 | MacroExpr | +| main.rs:11:14:11:21 | MacroBlockExpr | main.rs:11:5:11:22 | MacroExpr | | main.rs:11:14:11:21 | [post] MacroExpr | main.rs:11:14:11:21 | [post] FormatArgsExpr | -| main.rs:11:14:11:21 | { ... } | main.rs:11:14:11:21 | MacroStmts | +| main.rs:11:14:11:21 | { ... } | main.rs:11:14:11:21 | MacroBlockExpr | | main.rs:22:9:22:9 | [SSA] s | main.rs:23:10:23:10 | s | | main.rs:22:9:22:9 | s | main.rs:22:9:22:9 | [SSA] s | | main.rs:22:9:22:9 | s | main.rs:22:9:22:9 | s | @@ -684,9 +684,9 @@ localStep | main.rs:462:16:462:16 | s | main.rs:462:16:462:16 | s | | main.rs:462:16:462:24 | ...: String | main.rs:462:16:462:16 | s | | main.rs:463:14:463:20 | FormatArgsExpr | main.rs:463:14:463:20 | MacroExpr | -| main.rs:463:14:463:20 | MacroStmts | main.rs:463:5:463:21 | MacroExpr | +| main.rs:463:14:463:20 | MacroBlockExpr | main.rs:463:5:463:21 | MacroExpr | | main.rs:463:14:463:20 | [post] MacroExpr | main.rs:463:14:463:20 | [post] FormatArgsExpr | -| main.rs:463:14:463:20 | { ... } | main.rs:463:14:463:20 | MacroStmts | +| main.rs:463:14:463:20 | { ... } | main.rs:463:14:463:20 | MacroBlockExpr | | main.rs:467:9:467:9 | [SSA] a | main.rs:468:13:468:13 | a | | main.rs:467:9:467:9 | a | main.rs:467:9:467:9 | [SSA] a | | main.rs:467:9:467:9 | a | main.rs:467:9:467:9 | a | diff --git a/rust/ql/test/library-tests/variables/Cfg.expected b/rust/ql/test/library-tests/variables/Cfg.expected index 2c04ca30410a..f2a80077bfc7 100644 --- a/rust/ql/test/library-tests/variables/Cfg.expected +++ b/rust/ql/test/library-tests/variables/Cfg.expected @@ -14,9 +14,9 @@ edges | main.rs:4:14:4:20 | ...::format_args_nl!... | main.rs:4:14:4:20 | MacroExpr | | | main.rs:4:14:4:20 | ExprStmt | main.rs:4:5:4:21 | ...::_print | | | main.rs:4:14:4:20 | FormatArgsExpr | main.rs:4:14:4:20 | ...::format_args_nl!... | | +| main.rs:4:14:4:20 | MacroBlockExpr | main.rs:4:5:4:21 | println!... | | | main.rs:4:14:4:20 | MacroExpr | main.rs:4:14:4:20 | ...::_print(...) | | -| main.rs:4:14:4:20 | MacroStmts | main.rs:4:5:4:21 | println!... | | -| main.rs:4:14:4:20 | { ... } | main.rs:4:14:4:20 | MacroStmts | | +| main.rs:4:14:4:20 | { ... } | main.rs:4:14:4:20 | MacroBlockExpr | | | main.rs:4:20:4:20 | s | main.rs:4:14:4:20 | FormatArgsExpr | | | main.rs:7:1:9:1 | enter fn print_i64 | main.rs:7:14:7:14 | i | | | main.rs:7:1:9:1 | exit fn print_i64 (normal) | main.rs:7:1:9:1 | exit fn print_i64 | | @@ -33,9 +33,9 @@ edges | main.rs:8:14:8:20 | ...::format_args_nl!... | main.rs:8:14:8:20 | MacroExpr | | | main.rs:8:14:8:20 | ExprStmt | main.rs:8:5:8:21 | ...::_print | | | main.rs:8:14:8:20 | FormatArgsExpr | main.rs:8:14:8:20 | ...::format_args_nl!... | | +| main.rs:8:14:8:20 | MacroBlockExpr | main.rs:8:5:8:21 | println!... | | | main.rs:8:14:8:20 | MacroExpr | main.rs:8:14:8:20 | ...::_print(...) | | -| main.rs:8:14:8:20 | MacroStmts | main.rs:8:5:8:21 | println!... | | -| main.rs:8:14:8:20 | { ... } | main.rs:8:14:8:20 | MacroStmts | | +| main.rs:8:14:8:20 | { ... } | main.rs:8:14:8:20 | MacroBlockExpr | | | main.rs:8:20:8:20 | i | main.rs:8:14:8:20 | FormatArgsExpr | | | main.rs:11:1:13:1 | enter fn print_i64_ref | main.rs:11:18:11:18 | i | | | main.rs:11:1:13:1 | exit fn print_i64_ref (normal) | main.rs:11:1:13:1 | exit fn print_i64_ref | | @@ -242,9 +242,9 @@ edges | main.rs:94:39:94:42 | "x5" | main.rs:94:34:94:43 | Some(...) | | | main.rs:96:13:96:19 | "not yet implemented" | main.rs:96:13:96:19 | ...::panic(...) | | | main.rs:96:13:96:19 | ...::panic | main.rs:96:13:96:19 | "not yet implemented" | | -| main.rs:96:13:96:19 | ...::panic(...) | main.rs:96:13:96:19 | MacroStmts | | +| main.rs:96:13:96:19 | ...::panic(...) | main.rs:96:13:96:19 | MacroBlockExpr | | +| main.rs:96:13:96:19 | MacroBlockExpr | main.rs:96:13:96:19 | todo!... | | | main.rs:96:13:96:19 | MacroExpr | main.rs:95:14:97:9 | { ... } | | -| main.rs:96:13:96:19 | MacroStmts | main.rs:96:13:96:19 | todo!... | | | main.rs:96:13:96:19 | todo!... | main.rs:96:13:96:19 | MacroExpr | | | main.rs:98:5:98:13 | print_str | main.rs:98:15:98:16 | x5 | | | main.rs:98:5:98:17 | print_str(...) | main.rs:93:19:99:1 | { ... } | | @@ -428,9 +428,9 @@ edges | main.rs:176:22:176:51 | ...::format_args_nl!... | main.rs:176:22:176:51 | MacroExpr | | | main.rs:176:22:176:51 | ExprStmt | main.rs:176:13:176:52 | ...::_print | | | main.rs:176:22:176:51 | FormatArgsExpr | main.rs:176:22:176:51 | ...::format_args_nl!... | | +| main.rs:176:22:176:51 | MacroBlockExpr | main.rs:176:13:176:52 | println!... | | | main.rs:176:22:176:51 | MacroExpr | main.rs:176:22:176:51 | ...::_print(...) | | -| main.rs:176:22:176:51 | MacroStmts | main.rs:176:13:176:52 | println!... | | -| main.rs:176:22:176:51 | { ... } | main.rs:176:22:176:51 | MacroStmts | | +| main.rs:176:22:176:51 | { ... } | main.rs:176:22:176:51 | MacroBlockExpr | | | main.rs:178:9:178:29 | ...::Hello {...} | main.rs:178:26:178:27 | id | match | | main.rs:178:26:178:27 | id | main.rs:178:26:178:27 | id | | | main.rs:178:26:178:27 | id | main.rs:179:13:179:21 | print_i64 | match | diff --git a/rust/schema/annotations.py b/rust/schema/annotations.py index f783e72e6199..6eb463746ec9 100644 --- a/rust/schema/annotations.py +++ b/rust/schema/annotations.py @@ -1289,7 +1289,7 @@ class _: """ -@annotate(MacroStmts, replace_bases={AstNode: Expr}, cfg=True) +@annotate(MacroBlockExpr, replace_bases={AstNode: Expr}, cfg=True) @rust.doc_test_signature(None) class _: """ diff --git a/rust/schema/ast.py b/rust/schema/ast.py index dabe1be807ae..17fb872bb8ec 100644 --- a/rust/schema/ast.py +++ b/rust/schema/ast.py @@ -397,8 +397,8 @@ class MacroRules(Item, ): token_tree: optional["TokenTree"] | child visibility: optional["Visibility"] | child -class MacroStmts(AstNode, ): - expr: optional["Expr"] | child +class MacroBlockExpr(AstNode, ): + tail_expr: optional["Expr"] | child statements: list["Stmt"] | child class MacroTypeRepr(TypeRepr, ): From 5c4ca64264239e34f737f9622f3ca1b4affe29a1 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 2 May 2025 16:29:42 +0200 Subject: [PATCH 238/336] Swift: Add change note --- swift/ql/lib/change-notes/2025-05-02-new-entities.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 swift/ql/lib/change-notes/2025-05-02-new-entities.md diff --git a/swift/ql/lib/change-notes/2025-05-02-new-entities.md b/swift/ql/lib/change-notes/2025-05-02-new-entities.md new file mode 100644 index 000000000000..55472b08ff8f --- /dev/null +++ b/swift/ql/lib/change-notes/2025-05-02-new-entities.md @@ -0,0 +1,4 @@ +--- +category: feature +--- +* Added AST nodes `UnsafeCastExpr`, `TypeValueExpr`, `IntegerType`, and `BuiltinFixedArrayType` that correspond to new nodes added by Swift 6.1. From 6bf50d8f86df8621c8f33cac110e167ac9b2f95c Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Fri, 2 May 2025 15:09:06 +0200 Subject: [PATCH 239/336] Rust: add upgrade/downgrade scripts --- .../old.dbscheme | 3606 +++++++++++++++++ .../rust.dbscheme | 3606 +++++++++++++++++ .../upgrade.properties | 9 + .../old.dbscheme | 3606 +++++++++++++++++ .../rust.dbscheme | 3606 +++++++++++++++++ .../upgrade.properties | 9 + 6 files changed, 14442 insertions(+) create mode 100644 rust/downgrades/58bc96172f5a76faffc04004933865aa3c3b3e62/old.dbscheme create mode 100644 rust/downgrades/58bc96172f5a76faffc04004933865aa3c3b3e62/rust.dbscheme create mode 100644 rust/downgrades/58bc96172f5a76faffc04004933865aa3c3b3e62/upgrade.properties create mode 100644 rust/ql/lib/upgrades/e8707b675dc574aca9863eabcc09ac76f15bb9c2/old.dbscheme create mode 100644 rust/ql/lib/upgrades/e8707b675dc574aca9863eabcc09ac76f15bb9c2/rust.dbscheme create mode 100644 rust/ql/lib/upgrades/e8707b675dc574aca9863eabcc09ac76f15bb9c2/upgrade.properties diff --git a/rust/downgrades/58bc96172f5a76faffc04004933865aa3c3b3e62/old.dbscheme b/rust/downgrades/58bc96172f5a76faffc04004933865aa3c3b3e62/old.dbscheme new file mode 100644 index 000000000000..58bc96172f5a --- /dev/null +++ b/rust/downgrades/58bc96172f5a76faffc04004933865aa3c3b3e62/old.dbscheme @@ -0,0 +1,3606 @@ +// generated by codegen, do not edit + +// from ../shared/tree-sitter-extractor/src/generator/prefix.dbscheme +/*- Files and folders -*/ + +/** + * The location of an element. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @file | @folder + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/*- Empty location -*/ + +empty_location( + int location: @location_default ref +); + +/*- Source location prefix -*/ + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/*- Diagnostic messages -*/ + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/*- Diagnostic messages: severity -*/ + +case @diagnostic.severity of + 10 = @diagnostic_debug +| 20 = @diagnostic_info +| 30 = @diagnostic_warning +| 40 = @diagnostic_error +; + +/*- YAML -*/ + +#keyset[parent, idx] +yaml (unique int id: @yaml_node, + int kind: int ref, + int parent: @yaml_node_parent ref, + int idx: int ref, + string tag: string ref, + string tostring: string ref); + +case @yaml_node.kind of + 0 = @yaml_scalar_node +| 1 = @yaml_mapping_node +| 2 = @yaml_sequence_node +| 3 = @yaml_alias_node +; + +@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node; + +@yaml_node_parent = @yaml_collection_node | @file; + +yaml_anchors (unique int node: @yaml_node ref, + string anchor: string ref); + +yaml_aliases (unique int alias: @yaml_alias_node ref, + string target: string ref); + +yaml_scalars (unique int scalar: @yaml_scalar_node ref, + int style: int ref, + string value: string ref); + +yaml_errors (unique int id: @yaml_error, + string message: string ref); + +yaml_locations(unique int locatable: @yaml_locatable ref, + int location: @location_default ref); + +@yaml_locatable = @yaml_node | @yaml_error; + + +// from prefix.dbscheme +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_default ref +); + + +// from schema + +@element = + @extractor_step +| @locatable +| @named_crate +| @unextracted +; + +extractor_steps( + unique int id: @extractor_step, + string action: string ref, + int duration_ms: int ref +); + +#keyset[id] +extractor_step_files( + int id: @extractor_step ref, + int file: @file ref +); + +@locatable = + @ast_node +| @crate +; + +named_crates( + unique int id: @named_crate, + string name: string ref, + int crate: @crate ref +); + +@unextracted = + @missing +| @unimplemented +; + +@ast_node = + @abi +| @addressable +| @arg_list +| @asm_dir_spec +| @asm_operand +| @asm_operand_expr +| @asm_option +| @asm_piece +| @asm_reg_spec +| @assoc_item +| @assoc_item_list +| @attr +| @callable +| @closure_binder +| @expr +| @extern_item +| @extern_item_list +| @field_list +| @format_args_arg +| @generic_arg +| @generic_arg_list +| @generic_param +| @generic_param_list +| @item_list +| @label +| @let_else +| @macro_items +| @match_arm +| @match_arm_list +| @match_guard +| @meta +| @name +| @param_base +| @param_list +| @parenthesized_arg_list +| @pat +| @path +| @path_segment +| @rename +| @resolvable +| @ret_type_repr +| @return_type_syntax +| @source_file +| @stmt +| @stmt_list +| @struct_expr_field +| @struct_expr_field_list +| @struct_field +| @struct_pat_field +| @struct_pat_field_list +| @token +| @token_tree +| @tuple_field +| @type_bound +| @type_bound_list +| @type_repr +| @use_bound_generic_arg +| @use_bound_generic_args +| @use_tree +| @use_tree_list +| @variant_def +| @variant_list +| @visibility +| @where_clause +| @where_pred +; + +crates( + unique int id: @crate +); + +#keyset[id] +crate_names( + int id: @crate ref, + string name: string ref +); + +#keyset[id] +crate_versions( + int id: @crate ref, + string version: string ref +); + +#keyset[id] +crate_modules( + int id: @crate ref, + int module: @module ref +); + +#keyset[id, index] +crate_cfg_options( + int id: @crate ref, + int index: int ref, + string cfg_option: string ref +); + +#keyset[id, index] +crate_named_dependencies( + int id: @crate ref, + int index: int ref, + int named_dependency: @named_crate ref +); + +missings( + unique int id: @missing +); + +unimplementeds( + unique int id: @unimplemented +); + +abis( + unique int id: @abi +); + +#keyset[id] +abi_abi_strings( + int id: @abi ref, + string abi_string: string ref +); + +@addressable = + @item +| @variant +; + +#keyset[id] +addressable_extended_canonical_paths( + int id: @addressable ref, + string extended_canonical_path: string ref +); + +#keyset[id] +addressable_crate_origins( + int id: @addressable ref, + string crate_origin: string ref +); + +arg_lists( + unique int id: @arg_list +); + +#keyset[id, index] +arg_list_args( + int id: @arg_list ref, + int index: int ref, + int arg: @expr ref +); + +asm_dir_specs( + unique int id: @asm_dir_spec +); + +@asm_operand = + @asm_const +| @asm_label +| @asm_reg_operand +| @asm_sym +; + +asm_operand_exprs( + unique int id: @asm_operand_expr +); + +#keyset[id] +asm_operand_expr_in_exprs( + int id: @asm_operand_expr ref, + int in_expr: @expr ref +); + +#keyset[id] +asm_operand_expr_out_exprs( + int id: @asm_operand_expr ref, + int out_expr: @expr ref +); + +asm_options( + unique int id: @asm_option +); + +#keyset[id] +asm_option_is_raw( + int id: @asm_option ref +); + +@asm_piece = + @asm_clobber_abi +| @asm_operand_named +| @asm_options_list +; + +asm_reg_specs( + unique int id: @asm_reg_spec +); + +#keyset[id] +asm_reg_spec_identifiers( + int id: @asm_reg_spec ref, + int identifier: @name_ref ref +); + +@assoc_item = + @const +| @function +| @macro_call +| @type_alias +; + +assoc_item_lists( + unique int id: @assoc_item_list +); + +#keyset[id, index] +assoc_item_list_assoc_items( + int id: @assoc_item_list ref, + int index: int ref, + int assoc_item: @assoc_item ref +); + +#keyset[id, index] +assoc_item_list_attrs( + int id: @assoc_item_list ref, + int index: int ref, + int attr: @attr ref +); + +attrs( + unique int id: @attr +); + +#keyset[id] +attr_meta( + int id: @attr ref, + int meta: @meta ref +); + +@callable = + @closure_expr +| @function +; + +#keyset[id] +callable_param_lists( + int id: @callable ref, + int param_list: @param_list ref +); + +#keyset[id, index] +callable_attrs( + int id: @callable ref, + int index: int ref, + int attr: @attr ref +); + +closure_binders( + unique int id: @closure_binder +); + +#keyset[id] +closure_binder_generic_param_lists( + int id: @closure_binder ref, + int generic_param_list: @generic_param_list ref +); + +@expr = + @array_expr_internal +| @asm_expr +| @await_expr +| @become_expr +| @binary_expr +| @break_expr +| @call_expr_base +| @cast_expr +| @closure_expr +| @continue_expr +| @field_expr +| @format_args_expr +| @if_expr +| @index_expr +| @labelable_expr +| @let_expr +| @literal_expr +| @macro_block_expr +| @macro_expr +| @match_expr +| @offset_of_expr +| @paren_expr +| @path_expr_base +| @prefix_expr +| @range_expr +| @ref_expr +| @return_expr +| @struct_expr +| @try_expr +| @tuple_expr +| @underscore_expr +| @yeet_expr +| @yield_expr +; + +@extern_item = + @function +| @macro_call +| @static +| @type_alias +; + +extern_item_lists( + unique int id: @extern_item_list +); + +#keyset[id, index] +extern_item_list_attrs( + int id: @extern_item_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +extern_item_list_extern_items( + int id: @extern_item_list ref, + int index: int ref, + int extern_item: @extern_item ref +); + +@field_list = + @struct_field_list +| @tuple_field_list +; + +format_args_args( + unique int id: @format_args_arg +); + +#keyset[id] +format_args_arg_exprs( + int id: @format_args_arg ref, + int expr: @expr ref +); + +#keyset[id] +format_args_arg_names( + int id: @format_args_arg ref, + int name: @name ref +); + +@generic_arg = + @assoc_type_arg +| @const_arg +| @lifetime_arg +| @type_arg +; + +generic_arg_lists( + unique int id: @generic_arg_list +); + +#keyset[id, index] +generic_arg_list_generic_args( + int id: @generic_arg_list ref, + int index: int ref, + int generic_arg: @generic_arg ref +); + +@generic_param = + @const_param +| @lifetime_param +| @type_param +; + +generic_param_lists( + unique int id: @generic_param_list +); + +#keyset[id, index] +generic_param_list_generic_params( + int id: @generic_param_list ref, + int index: int ref, + int generic_param: @generic_param ref +); + +item_lists( + unique int id: @item_list +); + +#keyset[id, index] +item_list_attrs( + int id: @item_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +item_list_items( + int id: @item_list ref, + int index: int ref, + int item: @item ref +); + +labels( + unique int id: @label +); + +#keyset[id] +label_lifetimes( + int id: @label ref, + int lifetime: @lifetime ref +); + +let_elses( + unique int id: @let_else +); + +#keyset[id] +let_else_block_exprs( + int id: @let_else ref, + int block_expr: @block_expr ref +); + +macro_items( + unique int id: @macro_items +); + +#keyset[id, index] +macro_items_items( + int id: @macro_items ref, + int index: int ref, + int item: @item ref +); + +match_arms( + unique int id: @match_arm +); + +#keyset[id, index] +match_arm_attrs( + int id: @match_arm ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +match_arm_exprs( + int id: @match_arm ref, + int expr: @expr ref +); + +#keyset[id] +match_arm_guards( + int id: @match_arm ref, + int guard: @match_guard ref +); + +#keyset[id] +match_arm_pats( + int id: @match_arm ref, + int pat: @pat ref +); + +match_arm_lists( + unique int id: @match_arm_list +); + +#keyset[id, index] +match_arm_list_arms( + int id: @match_arm_list ref, + int index: int ref, + int arm: @match_arm ref +); + +#keyset[id, index] +match_arm_list_attrs( + int id: @match_arm_list ref, + int index: int ref, + int attr: @attr ref +); + +match_guards( + unique int id: @match_guard +); + +#keyset[id] +match_guard_conditions( + int id: @match_guard ref, + int condition: @expr ref +); + +meta( + unique int id: @meta +); + +#keyset[id] +meta_exprs( + int id: @meta ref, + int expr: @expr ref +); + +#keyset[id] +meta_is_unsafe( + int id: @meta ref +); + +#keyset[id] +meta_paths( + int id: @meta ref, + int path: @path ref +); + +#keyset[id] +meta_token_trees( + int id: @meta ref, + int token_tree: @token_tree ref +); + +names( + unique int id: @name +); + +#keyset[id] +name_texts( + int id: @name ref, + string text: string ref +); + +@param_base = + @param +| @self_param +; + +#keyset[id, index] +param_base_attrs( + int id: @param_base ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +param_base_type_reprs( + int id: @param_base ref, + int type_repr: @type_repr ref +); + +param_lists( + unique int id: @param_list +); + +#keyset[id, index] +param_list_params( + int id: @param_list ref, + int index: int ref, + int param: @param ref +); + +#keyset[id] +param_list_self_params( + int id: @param_list ref, + int self_param: @self_param ref +); + +parenthesized_arg_lists( + unique int id: @parenthesized_arg_list +); + +#keyset[id, index] +parenthesized_arg_list_type_args( + int id: @parenthesized_arg_list ref, + int index: int ref, + int type_arg: @type_arg ref +); + +@pat = + @box_pat +| @const_block_pat +| @ident_pat +| @literal_pat +| @macro_pat +| @or_pat +| @paren_pat +| @path_pat +| @range_pat +| @ref_pat +| @rest_pat +| @slice_pat +| @struct_pat +| @tuple_pat +| @tuple_struct_pat +| @wildcard_pat +; + +paths( + unique int id: @path +); + +#keyset[id] +path_qualifiers( + int id: @path ref, + int qualifier: @path ref +); + +#keyset[id] +path_segments_( + int id: @path ref, + int segment: @path_segment ref +); + +path_segments( + unique int id: @path_segment +); + +#keyset[id] +path_segment_generic_arg_lists( + int id: @path_segment ref, + int generic_arg_list: @generic_arg_list ref +); + +#keyset[id] +path_segment_identifiers( + int id: @path_segment ref, + int identifier: @name_ref ref +); + +#keyset[id] +path_segment_parenthesized_arg_lists( + int id: @path_segment ref, + int parenthesized_arg_list: @parenthesized_arg_list ref +); + +#keyset[id] +path_segment_ret_types( + int id: @path_segment ref, + int ret_type: @ret_type_repr ref +); + +#keyset[id] +path_segment_return_type_syntaxes( + int id: @path_segment ref, + int return_type_syntax: @return_type_syntax ref +); + +#keyset[id] +path_segment_type_reprs( + int id: @path_segment ref, + int type_repr: @type_repr ref +); + +#keyset[id] +path_segment_trait_type_reprs( + int id: @path_segment ref, + int trait_type_repr: @path_type_repr ref +); + +renames( + unique int id: @rename +); + +#keyset[id] +rename_names( + int id: @rename ref, + int name: @name ref +); + +@resolvable = + @method_call_expr +| @path_ast_node +; + +#keyset[id] +resolvable_resolved_paths( + int id: @resolvable ref, + string resolved_path: string ref +); + +#keyset[id] +resolvable_resolved_crate_origins( + int id: @resolvable ref, + string resolved_crate_origin: string ref +); + +ret_type_reprs( + unique int id: @ret_type_repr +); + +#keyset[id] +ret_type_repr_type_reprs( + int id: @ret_type_repr ref, + int type_repr: @type_repr ref +); + +return_type_syntaxes( + unique int id: @return_type_syntax +); + +source_files( + unique int id: @source_file +); + +#keyset[id, index] +source_file_attrs( + int id: @source_file ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +source_file_items( + int id: @source_file ref, + int index: int ref, + int item: @item ref +); + +@stmt = + @expr_stmt +| @item +| @let_stmt +; + +stmt_lists( + unique int id: @stmt_list +); + +#keyset[id, index] +stmt_list_attrs( + int id: @stmt_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +stmt_list_statements( + int id: @stmt_list ref, + int index: int ref, + int statement: @stmt ref +); + +#keyset[id] +stmt_list_tail_exprs( + int id: @stmt_list ref, + int tail_expr: @expr ref +); + +struct_expr_fields( + unique int id: @struct_expr_field +); + +#keyset[id, index] +struct_expr_field_attrs( + int id: @struct_expr_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_expr_field_exprs( + int id: @struct_expr_field ref, + int expr: @expr ref +); + +#keyset[id] +struct_expr_field_identifiers( + int id: @struct_expr_field ref, + int identifier: @name_ref ref +); + +struct_expr_field_lists( + unique int id: @struct_expr_field_list +); + +#keyset[id, index] +struct_expr_field_list_attrs( + int id: @struct_expr_field_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +struct_expr_field_list_fields( + int id: @struct_expr_field_list ref, + int index: int ref, + int field: @struct_expr_field ref +); + +#keyset[id] +struct_expr_field_list_spreads( + int id: @struct_expr_field_list ref, + int spread: @expr ref +); + +struct_fields( + unique int id: @struct_field +); + +#keyset[id, index] +struct_field_attrs( + int id: @struct_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_field_defaults( + int id: @struct_field ref, + int default: @expr ref +); + +#keyset[id] +struct_field_is_unsafe( + int id: @struct_field ref +); + +#keyset[id] +struct_field_names( + int id: @struct_field ref, + int name: @name ref +); + +#keyset[id] +struct_field_type_reprs( + int id: @struct_field ref, + int type_repr: @type_repr ref +); + +#keyset[id] +struct_field_visibilities( + int id: @struct_field ref, + int visibility: @visibility ref +); + +struct_pat_fields( + unique int id: @struct_pat_field +); + +#keyset[id, index] +struct_pat_field_attrs( + int id: @struct_pat_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_pat_field_identifiers( + int id: @struct_pat_field ref, + int identifier: @name_ref ref +); + +#keyset[id] +struct_pat_field_pats( + int id: @struct_pat_field ref, + int pat: @pat ref +); + +struct_pat_field_lists( + unique int id: @struct_pat_field_list +); + +#keyset[id, index] +struct_pat_field_list_fields( + int id: @struct_pat_field_list ref, + int index: int ref, + int field: @struct_pat_field ref +); + +#keyset[id] +struct_pat_field_list_rest_pats( + int id: @struct_pat_field_list ref, + int rest_pat: @rest_pat ref +); + +@token = + @comment +; + +token_trees( + unique int id: @token_tree +); + +tuple_fields( + unique int id: @tuple_field +); + +#keyset[id, index] +tuple_field_attrs( + int id: @tuple_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +tuple_field_type_reprs( + int id: @tuple_field ref, + int type_repr: @type_repr ref +); + +#keyset[id] +tuple_field_visibilities( + int id: @tuple_field ref, + int visibility: @visibility ref +); + +type_bounds( + unique int id: @type_bound +); + +#keyset[id] +type_bound_is_async( + int id: @type_bound ref +); + +#keyset[id] +type_bound_is_const( + int id: @type_bound ref +); + +#keyset[id] +type_bound_lifetimes( + int id: @type_bound ref, + int lifetime: @lifetime ref +); + +#keyset[id] +type_bound_type_reprs( + int id: @type_bound ref, + int type_repr: @type_repr ref +); + +#keyset[id] +type_bound_use_bound_generic_args( + int id: @type_bound ref, + int use_bound_generic_args: @use_bound_generic_args ref +); + +type_bound_lists( + unique int id: @type_bound_list +); + +#keyset[id, index] +type_bound_list_bounds( + int id: @type_bound_list ref, + int index: int ref, + int bound: @type_bound ref +); + +@type_repr = + @array_type_repr +| @dyn_trait_type_repr +| @fn_ptr_type_repr +| @for_type_repr +| @impl_trait_type_repr +| @infer_type_repr +| @macro_type_repr +| @never_type_repr +| @paren_type_repr +| @path_type_repr +| @ptr_type_repr +| @ref_type_repr +| @slice_type_repr +| @tuple_type_repr +; + +@use_bound_generic_arg = + @lifetime +| @name_ref +; + +use_bound_generic_args( + unique int id: @use_bound_generic_args +); + +#keyset[id, index] +use_bound_generic_args_use_bound_generic_args( + int id: @use_bound_generic_args ref, + int index: int ref, + int use_bound_generic_arg: @use_bound_generic_arg ref +); + +use_trees( + unique int id: @use_tree +); + +#keyset[id] +use_tree_is_glob( + int id: @use_tree ref +); + +#keyset[id] +use_tree_paths( + int id: @use_tree ref, + int path: @path ref +); + +#keyset[id] +use_tree_renames( + int id: @use_tree ref, + int rename: @rename ref +); + +#keyset[id] +use_tree_use_tree_lists( + int id: @use_tree ref, + int use_tree_list: @use_tree_list ref +); + +use_tree_lists( + unique int id: @use_tree_list +); + +#keyset[id, index] +use_tree_list_use_trees( + int id: @use_tree_list ref, + int index: int ref, + int use_tree: @use_tree ref +); + +@variant_def = + @struct +| @union +| @variant +; + +variant_lists( + unique int id: @variant_list +); + +#keyset[id, index] +variant_list_variants( + int id: @variant_list ref, + int index: int ref, + int variant: @variant ref +); + +visibilities( + unique int id: @visibility +); + +#keyset[id] +visibility_paths( + int id: @visibility ref, + int path: @path ref +); + +where_clauses( + unique int id: @where_clause +); + +#keyset[id, index] +where_clause_predicates( + int id: @where_clause ref, + int index: int ref, + int predicate: @where_pred ref +); + +where_preds( + unique int id: @where_pred +); + +#keyset[id] +where_pred_generic_param_lists( + int id: @where_pred ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +where_pred_lifetimes( + int id: @where_pred ref, + int lifetime: @lifetime ref +); + +#keyset[id] +where_pred_type_reprs( + int id: @where_pred ref, + int type_repr: @type_repr ref +); + +#keyset[id] +where_pred_type_bound_lists( + int id: @where_pred ref, + int type_bound_list: @type_bound_list ref +); + +array_expr_internals( + unique int id: @array_expr_internal +); + +#keyset[id, index] +array_expr_internal_attrs( + int id: @array_expr_internal ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +array_expr_internal_exprs( + int id: @array_expr_internal ref, + int index: int ref, + int expr: @expr ref +); + +#keyset[id] +array_expr_internal_is_semicolon( + int id: @array_expr_internal ref +); + +array_type_reprs( + unique int id: @array_type_repr +); + +#keyset[id] +array_type_repr_const_args( + int id: @array_type_repr ref, + int const_arg: @const_arg ref +); + +#keyset[id] +array_type_repr_element_type_reprs( + int id: @array_type_repr ref, + int element_type_repr: @type_repr ref +); + +asm_clobber_abis( + unique int id: @asm_clobber_abi +); + +asm_consts( + unique int id: @asm_const +); + +#keyset[id] +asm_const_exprs( + int id: @asm_const ref, + int expr: @expr ref +); + +#keyset[id] +asm_const_is_const( + int id: @asm_const ref +); + +asm_exprs( + unique int id: @asm_expr +); + +#keyset[id, index] +asm_expr_asm_pieces( + int id: @asm_expr ref, + int index: int ref, + int asm_piece: @asm_piece ref +); + +#keyset[id, index] +asm_expr_attrs( + int id: @asm_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +asm_expr_templates( + int id: @asm_expr ref, + int index: int ref, + int template: @expr ref +); + +asm_labels( + unique int id: @asm_label +); + +#keyset[id] +asm_label_block_exprs( + int id: @asm_label ref, + int block_expr: @block_expr ref +); + +asm_operand_nameds( + unique int id: @asm_operand_named +); + +#keyset[id] +asm_operand_named_asm_operands( + int id: @asm_operand_named ref, + int asm_operand: @asm_operand ref +); + +#keyset[id] +asm_operand_named_names( + int id: @asm_operand_named ref, + int name: @name ref +); + +asm_options_lists( + unique int id: @asm_options_list +); + +#keyset[id, index] +asm_options_list_asm_options( + int id: @asm_options_list ref, + int index: int ref, + int asm_option: @asm_option ref +); + +asm_reg_operands( + unique int id: @asm_reg_operand +); + +#keyset[id] +asm_reg_operand_asm_dir_specs( + int id: @asm_reg_operand ref, + int asm_dir_spec: @asm_dir_spec ref +); + +#keyset[id] +asm_reg_operand_asm_operand_exprs( + int id: @asm_reg_operand ref, + int asm_operand_expr: @asm_operand_expr ref +); + +#keyset[id] +asm_reg_operand_asm_reg_specs( + int id: @asm_reg_operand ref, + int asm_reg_spec: @asm_reg_spec ref +); + +asm_syms( + unique int id: @asm_sym +); + +#keyset[id] +asm_sym_paths( + int id: @asm_sym ref, + int path: @path ref +); + +assoc_type_args( + unique int id: @assoc_type_arg +); + +#keyset[id] +assoc_type_arg_const_args( + int id: @assoc_type_arg ref, + int const_arg: @const_arg ref +); + +#keyset[id] +assoc_type_arg_generic_arg_lists( + int id: @assoc_type_arg ref, + int generic_arg_list: @generic_arg_list ref +); + +#keyset[id] +assoc_type_arg_identifiers( + int id: @assoc_type_arg ref, + int identifier: @name_ref ref +); + +#keyset[id] +assoc_type_arg_param_lists( + int id: @assoc_type_arg ref, + int param_list: @param_list ref +); + +#keyset[id] +assoc_type_arg_ret_types( + int id: @assoc_type_arg ref, + int ret_type: @ret_type_repr ref +); + +#keyset[id] +assoc_type_arg_return_type_syntaxes( + int id: @assoc_type_arg ref, + int return_type_syntax: @return_type_syntax ref +); + +#keyset[id] +assoc_type_arg_type_reprs( + int id: @assoc_type_arg ref, + int type_repr: @type_repr ref +); + +#keyset[id] +assoc_type_arg_type_bound_lists( + int id: @assoc_type_arg ref, + int type_bound_list: @type_bound_list ref +); + +await_exprs( + unique int id: @await_expr +); + +#keyset[id, index] +await_expr_attrs( + int id: @await_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +await_expr_exprs( + int id: @await_expr ref, + int expr: @expr ref +); + +become_exprs( + unique int id: @become_expr +); + +#keyset[id, index] +become_expr_attrs( + int id: @become_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +become_expr_exprs( + int id: @become_expr ref, + int expr: @expr ref +); + +binary_exprs( + unique int id: @binary_expr +); + +#keyset[id, index] +binary_expr_attrs( + int id: @binary_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +binary_expr_lhs( + int id: @binary_expr ref, + int lhs: @expr ref +); + +#keyset[id] +binary_expr_operator_names( + int id: @binary_expr ref, + string operator_name: string ref +); + +#keyset[id] +binary_expr_rhs( + int id: @binary_expr ref, + int rhs: @expr ref +); + +box_pats( + unique int id: @box_pat +); + +#keyset[id] +box_pat_pats( + int id: @box_pat ref, + int pat: @pat ref +); + +break_exprs( + unique int id: @break_expr +); + +#keyset[id, index] +break_expr_attrs( + int id: @break_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +break_expr_exprs( + int id: @break_expr ref, + int expr: @expr ref +); + +#keyset[id] +break_expr_lifetimes( + int id: @break_expr ref, + int lifetime: @lifetime ref +); + +@call_expr_base = + @call_expr +| @method_call_expr +; + +#keyset[id] +call_expr_base_arg_lists( + int id: @call_expr_base ref, + int arg_list: @arg_list ref +); + +#keyset[id, index] +call_expr_base_attrs( + int id: @call_expr_base ref, + int index: int ref, + int attr: @attr ref +); + +cast_exprs( + unique int id: @cast_expr +); + +#keyset[id, index] +cast_expr_attrs( + int id: @cast_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +cast_expr_exprs( + int id: @cast_expr ref, + int expr: @expr ref +); + +#keyset[id] +cast_expr_type_reprs( + int id: @cast_expr ref, + int type_repr: @type_repr ref +); + +closure_exprs( + unique int id: @closure_expr +); + +#keyset[id] +closure_expr_bodies( + int id: @closure_expr ref, + int body: @expr ref +); + +#keyset[id] +closure_expr_closure_binders( + int id: @closure_expr ref, + int closure_binder: @closure_binder ref +); + +#keyset[id] +closure_expr_is_async( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_const( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_gen( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_move( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_static( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_ret_types( + int id: @closure_expr ref, + int ret_type: @ret_type_repr ref +); + +comments( + unique int id: @comment, + int parent: @ast_node ref, + string text: string ref +); + +const_args( + unique int id: @const_arg +); + +#keyset[id] +const_arg_exprs( + int id: @const_arg ref, + int expr: @expr ref +); + +const_block_pats( + unique int id: @const_block_pat +); + +#keyset[id] +const_block_pat_block_exprs( + int id: @const_block_pat ref, + int block_expr: @block_expr ref +); + +#keyset[id] +const_block_pat_is_const( + int id: @const_block_pat ref +); + +const_params( + unique int id: @const_param +); + +#keyset[id, index] +const_param_attrs( + int id: @const_param ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +const_param_default_vals( + int id: @const_param ref, + int default_val: @const_arg ref +); + +#keyset[id] +const_param_is_const( + int id: @const_param ref +); + +#keyset[id] +const_param_names( + int id: @const_param ref, + int name: @name ref +); + +#keyset[id] +const_param_type_reprs( + int id: @const_param ref, + int type_repr: @type_repr ref +); + +continue_exprs( + unique int id: @continue_expr +); + +#keyset[id, index] +continue_expr_attrs( + int id: @continue_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +continue_expr_lifetimes( + int id: @continue_expr ref, + int lifetime: @lifetime ref +); + +dyn_trait_type_reprs( + unique int id: @dyn_trait_type_repr +); + +#keyset[id] +dyn_trait_type_repr_type_bound_lists( + int id: @dyn_trait_type_repr ref, + int type_bound_list: @type_bound_list ref +); + +expr_stmts( + unique int id: @expr_stmt +); + +#keyset[id] +expr_stmt_exprs( + int id: @expr_stmt ref, + int expr: @expr ref +); + +field_exprs( + unique int id: @field_expr +); + +#keyset[id, index] +field_expr_attrs( + int id: @field_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +field_expr_containers( + int id: @field_expr ref, + int container: @expr ref +); + +#keyset[id] +field_expr_identifiers( + int id: @field_expr ref, + int identifier: @name_ref ref +); + +fn_ptr_type_reprs( + unique int id: @fn_ptr_type_repr +); + +#keyset[id] +fn_ptr_type_repr_abis( + int id: @fn_ptr_type_repr ref, + int abi: @abi ref +); + +#keyset[id] +fn_ptr_type_repr_is_async( + int id: @fn_ptr_type_repr ref +); + +#keyset[id] +fn_ptr_type_repr_is_const( + int id: @fn_ptr_type_repr ref +); + +#keyset[id] +fn_ptr_type_repr_is_unsafe( + int id: @fn_ptr_type_repr ref +); + +#keyset[id] +fn_ptr_type_repr_param_lists( + int id: @fn_ptr_type_repr ref, + int param_list: @param_list ref +); + +#keyset[id] +fn_ptr_type_repr_ret_types( + int id: @fn_ptr_type_repr ref, + int ret_type: @ret_type_repr ref +); + +for_type_reprs( + unique int id: @for_type_repr +); + +#keyset[id] +for_type_repr_generic_param_lists( + int id: @for_type_repr ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +for_type_repr_type_reprs( + int id: @for_type_repr ref, + int type_repr: @type_repr ref +); + +format_args_exprs( + unique int id: @format_args_expr +); + +#keyset[id, index] +format_args_expr_args( + int id: @format_args_expr ref, + int index: int ref, + int arg: @format_args_arg ref +); + +#keyset[id, index] +format_args_expr_attrs( + int id: @format_args_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +format_args_expr_templates( + int id: @format_args_expr ref, + int template: @expr ref +); + +ident_pats( + unique int id: @ident_pat +); + +#keyset[id, index] +ident_pat_attrs( + int id: @ident_pat ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +ident_pat_is_mut( + int id: @ident_pat ref +); + +#keyset[id] +ident_pat_is_ref( + int id: @ident_pat ref +); + +#keyset[id] +ident_pat_names( + int id: @ident_pat ref, + int name: @name ref +); + +#keyset[id] +ident_pat_pats( + int id: @ident_pat ref, + int pat: @pat ref +); + +if_exprs( + unique int id: @if_expr +); + +#keyset[id, index] +if_expr_attrs( + int id: @if_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +if_expr_conditions( + int id: @if_expr ref, + int condition: @expr ref +); + +#keyset[id] +if_expr_elses( + int id: @if_expr ref, + int else: @expr ref +); + +#keyset[id] +if_expr_thens( + int id: @if_expr ref, + int then: @block_expr ref +); + +impl_trait_type_reprs( + unique int id: @impl_trait_type_repr +); + +#keyset[id] +impl_trait_type_repr_type_bound_lists( + int id: @impl_trait_type_repr ref, + int type_bound_list: @type_bound_list ref +); + +index_exprs( + unique int id: @index_expr +); + +#keyset[id, index] +index_expr_attrs( + int id: @index_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +index_expr_bases( + int id: @index_expr ref, + int base: @expr ref +); + +#keyset[id] +index_expr_indices( + int id: @index_expr ref, + int index: @expr ref +); + +infer_type_reprs( + unique int id: @infer_type_repr +); + +@item = + @const +| @enum +| @extern_block +| @extern_crate +| @function +| @impl +| @macro_call +| @macro_def +| @macro_rules +| @module +| @static +| @struct +| @trait +| @trait_alias +| @type_alias +| @union +| @use +; + +@labelable_expr = + @block_expr +| @looping_expr +; + +#keyset[id] +labelable_expr_labels( + int id: @labelable_expr ref, + int label: @label ref +); + +let_exprs( + unique int id: @let_expr +); + +#keyset[id, index] +let_expr_attrs( + int id: @let_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +let_expr_scrutinees( + int id: @let_expr ref, + int scrutinee: @expr ref +); + +#keyset[id] +let_expr_pats( + int id: @let_expr ref, + int pat: @pat ref +); + +let_stmts( + unique int id: @let_stmt +); + +#keyset[id, index] +let_stmt_attrs( + int id: @let_stmt ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +let_stmt_initializers( + int id: @let_stmt ref, + int initializer: @expr ref +); + +#keyset[id] +let_stmt_let_elses( + int id: @let_stmt ref, + int let_else: @let_else ref +); + +#keyset[id] +let_stmt_pats( + int id: @let_stmt ref, + int pat: @pat ref +); + +#keyset[id] +let_stmt_type_reprs( + int id: @let_stmt ref, + int type_repr: @type_repr ref +); + +lifetimes( + unique int id: @lifetime +); + +#keyset[id] +lifetime_texts( + int id: @lifetime ref, + string text: string ref +); + +lifetime_args( + unique int id: @lifetime_arg +); + +#keyset[id] +lifetime_arg_lifetimes( + int id: @lifetime_arg ref, + int lifetime: @lifetime ref +); + +lifetime_params( + unique int id: @lifetime_param +); + +#keyset[id, index] +lifetime_param_attrs( + int id: @lifetime_param ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +lifetime_param_lifetimes( + int id: @lifetime_param ref, + int lifetime: @lifetime ref +); + +#keyset[id] +lifetime_param_type_bound_lists( + int id: @lifetime_param ref, + int type_bound_list: @type_bound_list ref +); + +literal_exprs( + unique int id: @literal_expr +); + +#keyset[id, index] +literal_expr_attrs( + int id: @literal_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +literal_expr_text_values( + int id: @literal_expr ref, + string text_value: string ref +); + +literal_pats( + unique int id: @literal_pat +); + +#keyset[id] +literal_pat_literals( + int id: @literal_pat ref, + int literal: @literal_expr ref +); + +macro_block_exprs( + unique int id: @macro_block_expr +); + +#keyset[id] +macro_block_expr_tail_exprs( + int id: @macro_block_expr ref, + int tail_expr: @expr ref +); + +#keyset[id, index] +macro_block_expr_statements( + int id: @macro_block_expr ref, + int index: int ref, + int statement: @stmt ref +); + +macro_exprs( + unique int id: @macro_expr +); + +#keyset[id] +macro_expr_macro_calls( + int id: @macro_expr ref, + int macro_call: @macro_call ref +); + +macro_pats( + unique int id: @macro_pat +); + +#keyset[id] +macro_pat_macro_calls( + int id: @macro_pat ref, + int macro_call: @macro_call ref +); + +macro_type_reprs( + unique int id: @macro_type_repr +); + +#keyset[id] +macro_type_repr_macro_calls( + int id: @macro_type_repr ref, + int macro_call: @macro_call ref +); + +match_exprs( + unique int id: @match_expr +); + +#keyset[id, index] +match_expr_attrs( + int id: @match_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +match_expr_scrutinees( + int id: @match_expr ref, + int scrutinee: @expr ref +); + +#keyset[id] +match_expr_match_arm_lists( + int id: @match_expr ref, + int match_arm_list: @match_arm_list ref +); + +name_refs( + unique int id: @name_ref +); + +#keyset[id] +name_ref_texts( + int id: @name_ref ref, + string text: string ref +); + +never_type_reprs( + unique int id: @never_type_repr +); + +offset_of_exprs( + unique int id: @offset_of_expr +); + +#keyset[id, index] +offset_of_expr_attrs( + int id: @offset_of_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +offset_of_expr_fields( + int id: @offset_of_expr ref, + int index: int ref, + int field: @name_ref ref +); + +#keyset[id] +offset_of_expr_type_reprs( + int id: @offset_of_expr ref, + int type_repr: @type_repr ref +); + +or_pats( + unique int id: @or_pat +); + +#keyset[id, index] +or_pat_pats( + int id: @or_pat ref, + int index: int ref, + int pat: @pat ref +); + +params( + unique int id: @param +); + +#keyset[id] +param_pats( + int id: @param ref, + int pat: @pat ref +); + +paren_exprs( + unique int id: @paren_expr +); + +#keyset[id, index] +paren_expr_attrs( + int id: @paren_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +paren_expr_exprs( + int id: @paren_expr ref, + int expr: @expr ref +); + +paren_pats( + unique int id: @paren_pat +); + +#keyset[id] +paren_pat_pats( + int id: @paren_pat ref, + int pat: @pat ref +); + +paren_type_reprs( + unique int id: @paren_type_repr +); + +#keyset[id] +paren_type_repr_type_reprs( + int id: @paren_type_repr ref, + int type_repr: @type_repr ref +); + +@path_ast_node = + @path_expr +| @path_pat +| @struct_expr +| @struct_pat +| @tuple_struct_pat +; + +#keyset[id] +path_ast_node_paths( + int id: @path_ast_node ref, + int path: @path ref +); + +@path_expr_base = + @path_expr +; + +path_type_reprs( + unique int id: @path_type_repr +); + +#keyset[id] +path_type_repr_paths( + int id: @path_type_repr ref, + int path: @path ref +); + +prefix_exprs( + unique int id: @prefix_expr +); + +#keyset[id, index] +prefix_expr_attrs( + int id: @prefix_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +prefix_expr_exprs( + int id: @prefix_expr ref, + int expr: @expr ref +); + +#keyset[id] +prefix_expr_operator_names( + int id: @prefix_expr ref, + string operator_name: string ref +); + +ptr_type_reprs( + unique int id: @ptr_type_repr +); + +#keyset[id] +ptr_type_repr_is_const( + int id: @ptr_type_repr ref +); + +#keyset[id] +ptr_type_repr_is_mut( + int id: @ptr_type_repr ref +); + +#keyset[id] +ptr_type_repr_type_reprs( + int id: @ptr_type_repr ref, + int type_repr: @type_repr ref +); + +range_exprs( + unique int id: @range_expr +); + +#keyset[id, index] +range_expr_attrs( + int id: @range_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +range_expr_ends( + int id: @range_expr ref, + int end: @expr ref +); + +#keyset[id] +range_expr_operator_names( + int id: @range_expr ref, + string operator_name: string ref +); + +#keyset[id] +range_expr_starts( + int id: @range_expr ref, + int start: @expr ref +); + +range_pats( + unique int id: @range_pat +); + +#keyset[id] +range_pat_ends( + int id: @range_pat ref, + int end: @pat ref +); + +#keyset[id] +range_pat_operator_names( + int id: @range_pat ref, + string operator_name: string ref +); + +#keyset[id] +range_pat_starts( + int id: @range_pat ref, + int start: @pat ref +); + +ref_exprs( + unique int id: @ref_expr +); + +#keyset[id, index] +ref_expr_attrs( + int id: @ref_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +ref_expr_exprs( + int id: @ref_expr ref, + int expr: @expr ref +); + +#keyset[id] +ref_expr_is_const( + int id: @ref_expr ref +); + +#keyset[id] +ref_expr_is_mut( + int id: @ref_expr ref +); + +#keyset[id] +ref_expr_is_raw( + int id: @ref_expr ref +); + +ref_pats( + unique int id: @ref_pat +); + +#keyset[id] +ref_pat_is_mut( + int id: @ref_pat ref +); + +#keyset[id] +ref_pat_pats( + int id: @ref_pat ref, + int pat: @pat ref +); + +ref_type_reprs( + unique int id: @ref_type_repr +); + +#keyset[id] +ref_type_repr_is_mut( + int id: @ref_type_repr ref +); + +#keyset[id] +ref_type_repr_lifetimes( + int id: @ref_type_repr ref, + int lifetime: @lifetime ref +); + +#keyset[id] +ref_type_repr_type_reprs( + int id: @ref_type_repr ref, + int type_repr: @type_repr ref +); + +rest_pats( + unique int id: @rest_pat +); + +#keyset[id, index] +rest_pat_attrs( + int id: @rest_pat ref, + int index: int ref, + int attr: @attr ref +); + +return_exprs( + unique int id: @return_expr +); + +#keyset[id, index] +return_expr_attrs( + int id: @return_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +return_expr_exprs( + int id: @return_expr ref, + int expr: @expr ref +); + +self_params( + unique int id: @self_param +); + +#keyset[id] +self_param_is_ref( + int id: @self_param ref +); + +#keyset[id] +self_param_is_mut( + int id: @self_param ref +); + +#keyset[id] +self_param_lifetimes( + int id: @self_param ref, + int lifetime: @lifetime ref +); + +#keyset[id] +self_param_names( + int id: @self_param ref, + int name: @name ref +); + +slice_pats( + unique int id: @slice_pat +); + +#keyset[id, index] +slice_pat_pats( + int id: @slice_pat ref, + int index: int ref, + int pat: @pat ref +); + +slice_type_reprs( + unique int id: @slice_type_repr +); + +#keyset[id] +slice_type_repr_type_reprs( + int id: @slice_type_repr ref, + int type_repr: @type_repr ref +); + +struct_field_lists( + unique int id: @struct_field_list +); + +#keyset[id, index] +struct_field_list_fields( + int id: @struct_field_list ref, + int index: int ref, + int field: @struct_field ref +); + +try_exprs( + unique int id: @try_expr +); + +#keyset[id, index] +try_expr_attrs( + int id: @try_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +try_expr_exprs( + int id: @try_expr ref, + int expr: @expr ref +); + +tuple_exprs( + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_attrs( + int id: @tuple_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +tuple_expr_fields( + int id: @tuple_expr ref, + int index: int ref, + int field: @expr ref +); + +tuple_field_lists( + unique int id: @tuple_field_list +); + +#keyset[id, index] +tuple_field_list_fields( + int id: @tuple_field_list ref, + int index: int ref, + int field: @tuple_field ref +); + +tuple_pats( + unique int id: @tuple_pat +); + +#keyset[id, index] +tuple_pat_fields( + int id: @tuple_pat ref, + int index: int ref, + int field: @pat ref +); + +tuple_type_reprs( + unique int id: @tuple_type_repr +); + +#keyset[id, index] +tuple_type_repr_fields( + int id: @tuple_type_repr ref, + int index: int ref, + int field: @type_repr ref +); + +type_args( + unique int id: @type_arg +); + +#keyset[id] +type_arg_type_reprs( + int id: @type_arg ref, + int type_repr: @type_repr ref +); + +type_params( + unique int id: @type_param +); + +#keyset[id, index] +type_param_attrs( + int id: @type_param ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +type_param_default_types( + int id: @type_param ref, + int default_type: @type_repr ref +); + +#keyset[id] +type_param_names( + int id: @type_param ref, + int name: @name ref +); + +#keyset[id] +type_param_type_bound_lists( + int id: @type_param ref, + int type_bound_list: @type_bound_list ref +); + +underscore_exprs( + unique int id: @underscore_expr +); + +#keyset[id, index] +underscore_expr_attrs( + int id: @underscore_expr ref, + int index: int ref, + int attr: @attr ref +); + +variants( + unique int id: @variant +); + +#keyset[id, index] +variant_attrs( + int id: @variant ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +variant_discriminants( + int id: @variant ref, + int discriminant: @expr ref +); + +#keyset[id] +variant_field_lists( + int id: @variant ref, + int field_list: @field_list ref +); + +#keyset[id] +variant_names( + int id: @variant ref, + int name: @name ref +); + +#keyset[id] +variant_visibilities( + int id: @variant ref, + int visibility: @visibility ref +); + +wildcard_pats( + unique int id: @wildcard_pat +); + +yeet_exprs( + unique int id: @yeet_expr +); + +#keyset[id, index] +yeet_expr_attrs( + int id: @yeet_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +yeet_expr_exprs( + int id: @yeet_expr ref, + int expr: @expr ref +); + +yield_exprs( + unique int id: @yield_expr +); + +#keyset[id, index] +yield_expr_attrs( + int id: @yield_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +yield_expr_exprs( + int id: @yield_expr ref, + int expr: @expr ref +); + +block_exprs( + unique int id: @block_expr +); + +#keyset[id, index] +block_expr_attrs( + int id: @block_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +block_expr_is_async( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_const( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_gen( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_move( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_try( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_unsafe( + int id: @block_expr ref +); + +#keyset[id] +block_expr_stmt_lists( + int id: @block_expr ref, + int stmt_list: @stmt_list ref +); + +call_exprs( + unique int id: @call_expr +); + +#keyset[id] +call_expr_functions( + int id: @call_expr ref, + int function: @expr ref +); + +consts( + unique int id: @const +); + +#keyset[id, index] +const_attrs( + int id: @const ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +const_bodies( + int id: @const ref, + int body: @expr ref +); + +#keyset[id] +const_is_const( + int id: @const ref +); + +#keyset[id] +const_is_default( + int id: @const ref +); + +#keyset[id] +const_names( + int id: @const ref, + int name: @name ref +); + +#keyset[id] +const_type_reprs( + int id: @const ref, + int type_repr: @type_repr ref +); + +#keyset[id] +const_visibilities( + int id: @const ref, + int visibility: @visibility ref +); + +enums( + unique int id: @enum +); + +#keyset[id, index] +enum_attrs( + int id: @enum ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +enum_generic_param_lists( + int id: @enum ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +enum_names( + int id: @enum ref, + int name: @name ref +); + +#keyset[id] +enum_variant_lists( + int id: @enum ref, + int variant_list: @variant_list ref +); + +#keyset[id] +enum_visibilities( + int id: @enum ref, + int visibility: @visibility ref +); + +#keyset[id] +enum_where_clauses( + int id: @enum ref, + int where_clause: @where_clause ref +); + +extern_blocks( + unique int id: @extern_block +); + +#keyset[id] +extern_block_abis( + int id: @extern_block ref, + int abi: @abi ref +); + +#keyset[id, index] +extern_block_attrs( + int id: @extern_block ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +extern_block_extern_item_lists( + int id: @extern_block ref, + int extern_item_list: @extern_item_list ref +); + +#keyset[id] +extern_block_is_unsafe( + int id: @extern_block ref +); + +extern_crates( + unique int id: @extern_crate +); + +#keyset[id, index] +extern_crate_attrs( + int id: @extern_crate ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +extern_crate_identifiers( + int id: @extern_crate ref, + int identifier: @name_ref ref +); + +#keyset[id] +extern_crate_renames( + int id: @extern_crate ref, + int rename: @rename ref +); + +#keyset[id] +extern_crate_visibilities( + int id: @extern_crate ref, + int visibility: @visibility ref +); + +functions( + unique int id: @function +); + +#keyset[id] +function_abis( + int id: @function ref, + int abi: @abi ref +); + +#keyset[id] +function_bodies( + int id: @function ref, + int body: @block_expr ref +); + +#keyset[id] +function_generic_param_lists( + int id: @function ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +function_is_async( + int id: @function ref +); + +#keyset[id] +function_is_const( + int id: @function ref +); + +#keyset[id] +function_is_default( + int id: @function ref +); + +#keyset[id] +function_is_gen( + int id: @function ref +); + +#keyset[id] +function_is_unsafe( + int id: @function ref +); + +#keyset[id] +function_names( + int id: @function ref, + int name: @name ref +); + +#keyset[id] +function_ret_types( + int id: @function ref, + int ret_type: @ret_type_repr ref +); + +#keyset[id] +function_visibilities( + int id: @function ref, + int visibility: @visibility ref +); + +#keyset[id] +function_where_clauses( + int id: @function ref, + int where_clause: @where_clause ref +); + +impls( + unique int id: @impl +); + +#keyset[id] +impl_assoc_item_lists( + int id: @impl ref, + int assoc_item_list: @assoc_item_list ref +); + +#keyset[id, index] +impl_attrs( + int id: @impl ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +impl_generic_param_lists( + int id: @impl ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +impl_is_const( + int id: @impl ref +); + +#keyset[id] +impl_is_default( + int id: @impl ref +); + +#keyset[id] +impl_is_unsafe( + int id: @impl ref +); + +#keyset[id] +impl_self_ties( + int id: @impl ref, + int self_ty: @type_repr ref +); + +#keyset[id] +impl_traits( + int id: @impl ref, + int trait: @type_repr ref +); + +#keyset[id] +impl_visibilities( + int id: @impl ref, + int visibility: @visibility ref +); + +#keyset[id] +impl_where_clauses( + int id: @impl ref, + int where_clause: @where_clause ref +); + +@looping_expr = + @for_expr +| @loop_expr +| @while_expr +; + +#keyset[id] +looping_expr_loop_bodies( + int id: @looping_expr ref, + int loop_body: @block_expr ref +); + +macro_calls( + unique int id: @macro_call +); + +#keyset[id, index] +macro_call_attrs( + int id: @macro_call ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +macro_call_paths( + int id: @macro_call ref, + int path: @path ref +); + +#keyset[id] +macro_call_token_trees( + int id: @macro_call ref, + int token_tree: @token_tree ref +); + +#keyset[id] +macro_call_expandeds( + int id: @macro_call ref, + int expanded: @ast_node ref +); + +macro_defs( + unique int id: @macro_def +); + +#keyset[id] +macro_def_args( + int id: @macro_def ref, + int args: @token_tree ref +); + +#keyset[id, index] +macro_def_attrs( + int id: @macro_def ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +macro_def_bodies( + int id: @macro_def ref, + int body: @token_tree ref +); + +#keyset[id] +macro_def_names( + int id: @macro_def ref, + int name: @name ref +); + +#keyset[id] +macro_def_visibilities( + int id: @macro_def ref, + int visibility: @visibility ref +); + +macro_rules( + unique int id: @macro_rules +); + +#keyset[id, index] +macro_rules_attrs( + int id: @macro_rules ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +macro_rules_names( + int id: @macro_rules ref, + int name: @name ref +); + +#keyset[id] +macro_rules_token_trees( + int id: @macro_rules ref, + int token_tree: @token_tree ref +); + +#keyset[id] +macro_rules_visibilities( + int id: @macro_rules ref, + int visibility: @visibility ref +); + +method_call_exprs( + unique int id: @method_call_expr +); + +#keyset[id] +method_call_expr_generic_arg_lists( + int id: @method_call_expr ref, + int generic_arg_list: @generic_arg_list ref +); + +#keyset[id] +method_call_expr_identifiers( + int id: @method_call_expr ref, + int identifier: @name_ref ref +); + +#keyset[id] +method_call_expr_receivers( + int id: @method_call_expr ref, + int receiver: @expr ref +); + +modules( + unique int id: @module +); + +#keyset[id, index] +module_attrs( + int id: @module ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +module_item_lists( + int id: @module ref, + int item_list: @item_list ref +); + +#keyset[id] +module_names( + int id: @module ref, + int name: @name ref +); + +#keyset[id] +module_visibilities( + int id: @module ref, + int visibility: @visibility ref +); + +path_exprs( + unique int id: @path_expr +); + +#keyset[id, index] +path_expr_attrs( + int id: @path_expr ref, + int index: int ref, + int attr: @attr ref +); + +path_pats( + unique int id: @path_pat +); + +statics( + unique int id: @static +); + +#keyset[id, index] +static_attrs( + int id: @static ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +static_bodies( + int id: @static ref, + int body: @expr ref +); + +#keyset[id] +static_is_mut( + int id: @static ref +); + +#keyset[id] +static_is_static( + int id: @static ref +); + +#keyset[id] +static_is_unsafe( + int id: @static ref +); + +#keyset[id] +static_names( + int id: @static ref, + int name: @name ref +); + +#keyset[id] +static_type_reprs( + int id: @static ref, + int type_repr: @type_repr ref +); + +#keyset[id] +static_visibilities( + int id: @static ref, + int visibility: @visibility ref +); + +structs( + unique int id: @struct +); + +#keyset[id, index] +struct_attrs( + int id: @struct ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_field_lists_( + int id: @struct ref, + int field_list: @field_list ref +); + +#keyset[id] +struct_generic_param_lists( + int id: @struct ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +struct_names( + int id: @struct ref, + int name: @name ref +); + +#keyset[id] +struct_visibilities( + int id: @struct ref, + int visibility: @visibility ref +); + +#keyset[id] +struct_where_clauses( + int id: @struct ref, + int where_clause: @where_clause ref +); + +struct_exprs( + unique int id: @struct_expr +); + +#keyset[id] +struct_expr_struct_expr_field_lists( + int id: @struct_expr ref, + int struct_expr_field_list: @struct_expr_field_list ref +); + +struct_pats( + unique int id: @struct_pat +); + +#keyset[id] +struct_pat_struct_pat_field_lists( + int id: @struct_pat ref, + int struct_pat_field_list: @struct_pat_field_list ref +); + +traits( + unique int id: @trait +); + +#keyset[id] +trait_assoc_item_lists( + int id: @trait ref, + int assoc_item_list: @assoc_item_list ref +); + +#keyset[id, index] +trait_attrs( + int id: @trait ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +trait_generic_param_lists( + int id: @trait ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +trait_is_auto( + int id: @trait ref +); + +#keyset[id] +trait_is_unsafe( + int id: @trait ref +); + +#keyset[id] +trait_names( + int id: @trait ref, + int name: @name ref +); + +#keyset[id] +trait_type_bound_lists( + int id: @trait ref, + int type_bound_list: @type_bound_list ref +); + +#keyset[id] +trait_visibilities( + int id: @trait ref, + int visibility: @visibility ref +); + +#keyset[id] +trait_where_clauses( + int id: @trait ref, + int where_clause: @where_clause ref +); + +trait_aliases( + unique int id: @trait_alias +); + +#keyset[id, index] +trait_alias_attrs( + int id: @trait_alias ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +trait_alias_generic_param_lists( + int id: @trait_alias ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +trait_alias_names( + int id: @trait_alias ref, + int name: @name ref +); + +#keyset[id] +trait_alias_type_bound_lists( + int id: @trait_alias ref, + int type_bound_list: @type_bound_list ref +); + +#keyset[id] +trait_alias_visibilities( + int id: @trait_alias ref, + int visibility: @visibility ref +); + +#keyset[id] +trait_alias_where_clauses( + int id: @trait_alias ref, + int where_clause: @where_clause ref +); + +tuple_struct_pats( + unique int id: @tuple_struct_pat +); + +#keyset[id, index] +tuple_struct_pat_fields( + int id: @tuple_struct_pat ref, + int index: int ref, + int field: @pat ref +); + +type_aliases( + unique int id: @type_alias +); + +#keyset[id, index] +type_alias_attrs( + int id: @type_alias ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +type_alias_generic_param_lists( + int id: @type_alias ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +type_alias_is_default( + int id: @type_alias ref +); + +#keyset[id] +type_alias_names( + int id: @type_alias ref, + int name: @name ref +); + +#keyset[id] +type_alias_type_reprs( + int id: @type_alias ref, + int type_repr: @type_repr ref +); + +#keyset[id] +type_alias_type_bound_lists( + int id: @type_alias ref, + int type_bound_list: @type_bound_list ref +); + +#keyset[id] +type_alias_visibilities( + int id: @type_alias ref, + int visibility: @visibility ref +); + +#keyset[id] +type_alias_where_clauses( + int id: @type_alias ref, + int where_clause: @where_clause ref +); + +unions( + unique int id: @union +); + +#keyset[id, index] +union_attrs( + int id: @union ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +union_generic_param_lists( + int id: @union ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +union_names( + int id: @union ref, + int name: @name ref +); + +#keyset[id] +union_struct_field_lists( + int id: @union ref, + int struct_field_list: @struct_field_list ref +); + +#keyset[id] +union_visibilities( + int id: @union ref, + int visibility: @visibility ref +); + +#keyset[id] +union_where_clauses( + int id: @union ref, + int where_clause: @where_clause ref +); + +uses( + unique int id: @use +); + +#keyset[id, index] +use_attrs( + int id: @use ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +use_use_trees( + int id: @use ref, + int use_tree: @use_tree ref +); + +#keyset[id] +use_visibilities( + int id: @use ref, + int visibility: @visibility ref +); + +for_exprs( + unique int id: @for_expr +); + +#keyset[id, index] +for_expr_attrs( + int id: @for_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +for_expr_iterables( + int id: @for_expr ref, + int iterable: @expr ref +); + +#keyset[id] +for_expr_pats( + int id: @for_expr ref, + int pat: @pat ref +); + +loop_exprs( + unique int id: @loop_expr +); + +#keyset[id, index] +loop_expr_attrs( + int id: @loop_expr ref, + int index: int ref, + int attr: @attr ref +); + +while_exprs( + unique int id: @while_expr +); + +#keyset[id, index] +while_expr_attrs( + int id: @while_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +while_expr_conditions( + int id: @while_expr ref, + int condition: @expr ref +); diff --git a/rust/downgrades/58bc96172f5a76faffc04004933865aa3c3b3e62/rust.dbscheme b/rust/downgrades/58bc96172f5a76faffc04004933865aa3c3b3e62/rust.dbscheme new file mode 100644 index 000000000000..e8707b675dc5 --- /dev/null +++ b/rust/downgrades/58bc96172f5a76faffc04004933865aa3c3b3e62/rust.dbscheme @@ -0,0 +1,3606 @@ +// generated by codegen, do not edit + +// from ../shared/tree-sitter-extractor/src/generator/prefix.dbscheme +/*- Files and folders -*/ + +/** + * The location of an element. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @file | @folder + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/*- Empty location -*/ + +empty_location( + int location: @location_default ref +); + +/*- Source location prefix -*/ + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/*- Diagnostic messages -*/ + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/*- Diagnostic messages: severity -*/ + +case @diagnostic.severity of + 10 = @diagnostic_debug +| 20 = @diagnostic_info +| 30 = @diagnostic_warning +| 40 = @diagnostic_error +; + +/*- YAML -*/ + +#keyset[parent, idx] +yaml (unique int id: @yaml_node, + int kind: int ref, + int parent: @yaml_node_parent ref, + int idx: int ref, + string tag: string ref, + string tostring: string ref); + +case @yaml_node.kind of + 0 = @yaml_scalar_node +| 1 = @yaml_mapping_node +| 2 = @yaml_sequence_node +| 3 = @yaml_alias_node +; + +@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node; + +@yaml_node_parent = @yaml_collection_node | @file; + +yaml_anchors (unique int node: @yaml_node ref, + string anchor: string ref); + +yaml_aliases (unique int alias: @yaml_alias_node ref, + string target: string ref); + +yaml_scalars (unique int scalar: @yaml_scalar_node ref, + int style: int ref, + string value: string ref); + +yaml_errors (unique int id: @yaml_error, + string message: string ref); + +yaml_locations(unique int locatable: @yaml_locatable ref, + int location: @location_default ref); + +@yaml_locatable = @yaml_node | @yaml_error; + + +// from prefix.dbscheme +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_default ref +); + + +// from schema + +@element = + @extractor_step +| @locatable +| @named_crate +| @unextracted +; + +extractor_steps( + unique int id: @extractor_step, + string action: string ref, + int duration_ms: int ref +); + +#keyset[id] +extractor_step_files( + int id: @extractor_step ref, + int file: @file ref +); + +@locatable = + @ast_node +| @crate +; + +named_crates( + unique int id: @named_crate, + string name: string ref, + int crate: @crate ref +); + +@unextracted = + @missing +| @unimplemented +; + +@ast_node = + @abi +| @addressable +| @arg_list +| @asm_dir_spec +| @asm_operand +| @asm_operand_expr +| @asm_option +| @asm_piece +| @asm_reg_spec +| @assoc_item +| @assoc_item_list +| @attr +| @callable +| @closure_binder +| @expr +| @extern_item +| @extern_item_list +| @field_list +| @format_args_arg +| @generic_arg +| @generic_arg_list +| @generic_param +| @generic_param_list +| @item_list +| @label +| @let_else +| @macro_items +| @macro_stmts +| @match_arm +| @match_arm_list +| @match_guard +| @meta +| @name +| @param_base +| @param_list +| @parenthesized_arg_list +| @pat +| @path +| @path_segment +| @rename +| @resolvable +| @ret_type_repr +| @return_type_syntax +| @source_file +| @stmt +| @stmt_list +| @struct_expr_field +| @struct_expr_field_list +| @struct_field +| @struct_pat_field +| @struct_pat_field_list +| @token +| @token_tree +| @tuple_field +| @type_bound +| @type_bound_list +| @type_repr +| @use_bound_generic_arg +| @use_bound_generic_args +| @use_tree +| @use_tree_list +| @variant_def +| @variant_list +| @visibility +| @where_clause +| @where_pred +; + +crates( + unique int id: @crate +); + +#keyset[id] +crate_names( + int id: @crate ref, + string name: string ref +); + +#keyset[id] +crate_versions( + int id: @crate ref, + string version: string ref +); + +#keyset[id] +crate_modules( + int id: @crate ref, + int module: @module ref +); + +#keyset[id, index] +crate_cfg_options( + int id: @crate ref, + int index: int ref, + string cfg_option: string ref +); + +#keyset[id, index] +crate_named_dependencies( + int id: @crate ref, + int index: int ref, + int named_dependency: @named_crate ref +); + +missings( + unique int id: @missing +); + +unimplementeds( + unique int id: @unimplemented +); + +abis( + unique int id: @abi +); + +#keyset[id] +abi_abi_strings( + int id: @abi ref, + string abi_string: string ref +); + +@addressable = + @item +| @variant +; + +#keyset[id] +addressable_extended_canonical_paths( + int id: @addressable ref, + string extended_canonical_path: string ref +); + +#keyset[id] +addressable_crate_origins( + int id: @addressable ref, + string crate_origin: string ref +); + +arg_lists( + unique int id: @arg_list +); + +#keyset[id, index] +arg_list_args( + int id: @arg_list ref, + int index: int ref, + int arg: @expr ref +); + +asm_dir_specs( + unique int id: @asm_dir_spec +); + +@asm_operand = + @asm_const +| @asm_label +| @asm_reg_operand +| @asm_sym +; + +asm_operand_exprs( + unique int id: @asm_operand_expr +); + +#keyset[id] +asm_operand_expr_in_exprs( + int id: @asm_operand_expr ref, + int in_expr: @expr ref +); + +#keyset[id] +asm_operand_expr_out_exprs( + int id: @asm_operand_expr ref, + int out_expr: @expr ref +); + +asm_options( + unique int id: @asm_option +); + +#keyset[id] +asm_option_is_raw( + int id: @asm_option ref +); + +@asm_piece = + @asm_clobber_abi +| @asm_operand_named +| @asm_options_list +; + +asm_reg_specs( + unique int id: @asm_reg_spec +); + +#keyset[id] +asm_reg_spec_identifiers( + int id: @asm_reg_spec ref, + int identifier: @name_ref ref +); + +@assoc_item = + @const +| @function +| @macro_call +| @type_alias +; + +assoc_item_lists( + unique int id: @assoc_item_list +); + +#keyset[id, index] +assoc_item_list_assoc_items( + int id: @assoc_item_list ref, + int index: int ref, + int assoc_item: @assoc_item ref +); + +#keyset[id, index] +assoc_item_list_attrs( + int id: @assoc_item_list ref, + int index: int ref, + int attr: @attr ref +); + +attrs( + unique int id: @attr +); + +#keyset[id] +attr_meta( + int id: @attr ref, + int meta: @meta ref +); + +@callable = + @closure_expr +| @function +; + +#keyset[id] +callable_param_lists( + int id: @callable ref, + int param_list: @param_list ref +); + +#keyset[id, index] +callable_attrs( + int id: @callable ref, + int index: int ref, + int attr: @attr ref +); + +closure_binders( + unique int id: @closure_binder +); + +#keyset[id] +closure_binder_generic_param_lists( + int id: @closure_binder ref, + int generic_param_list: @generic_param_list ref +); + +@expr = + @array_expr_internal +| @asm_expr +| @await_expr +| @become_expr +| @binary_expr +| @break_expr +| @call_expr_base +| @cast_expr +| @closure_expr +| @continue_expr +| @field_expr +| @format_args_expr +| @if_expr +| @index_expr +| @labelable_expr +| @let_expr +| @literal_expr +| @macro_expr +| @match_expr +| @offset_of_expr +| @paren_expr +| @path_expr_base +| @prefix_expr +| @range_expr +| @ref_expr +| @return_expr +| @struct_expr +| @try_expr +| @tuple_expr +| @underscore_expr +| @yeet_expr +| @yield_expr +; + +@extern_item = + @function +| @macro_call +| @static +| @type_alias +; + +extern_item_lists( + unique int id: @extern_item_list +); + +#keyset[id, index] +extern_item_list_attrs( + int id: @extern_item_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +extern_item_list_extern_items( + int id: @extern_item_list ref, + int index: int ref, + int extern_item: @extern_item ref +); + +@field_list = + @struct_field_list +| @tuple_field_list +; + +format_args_args( + unique int id: @format_args_arg +); + +#keyset[id] +format_args_arg_exprs( + int id: @format_args_arg ref, + int expr: @expr ref +); + +#keyset[id] +format_args_arg_names( + int id: @format_args_arg ref, + int name: @name ref +); + +@generic_arg = + @assoc_type_arg +| @const_arg +| @lifetime_arg +| @type_arg +; + +generic_arg_lists( + unique int id: @generic_arg_list +); + +#keyset[id, index] +generic_arg_list_generic_args( + int id: @generic_arg_list ref, + int index: int ref, + int generic_arg: @generic_arg ref +); + +@generic_param = + @const_param +| @lifetime_param +| @type_param +; + +generic_param_lists( + unique int id: @generic_param_list +); + +#keyset[id, index] +generic_param_list_generic_params( + int id: @generic_param_list ref, + int index: int ref, + int generic_param: @generic_param ref +); + +item_lists( + unique int id: @item_list +); + +#keyset[id, index] +item_list_attrs( + int id: @item_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +item_list_items( + int id: @item_list ref, + int index: int ref, + int item: @item ref +); + +labels( + unique int id: @label +); + +#keyset[id] +label_lifetimes( + int id: @label ref, + int lifetime: @lifetime ref +); + +let_elses( + unique int id: @let_else +); + +#keyset[id] +let_else_block_exprs( + int id: @let_else ref, + int block_expr: @block_expr ref +); + +macro_items( + unique int id: @macro_items +); + +#keyset[id, index] +macro_items_items( + int id: @macro_items ref, + int index: int ref, + int item: @item ref +); + +macro_stmts( + unique int id: @macro_stmts +); + +#keyset[id] +macro_stmts_exprs( + int id: @macro_stmts ref, + int expr: @expr ref +); + +#keyset[id, index] +macro_stmts_statements( + int id: @macro_stmts ref, + int index: int ref, + int statement: @stmt ref +); + +match_arms( + unique int id: @match_arm +); + +#keyset[id, index] +match_arm_attrs( + int id: @match_arm ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +match_arm_exprs( + int id: @match_arm ref, + int expr: @expr ref +); + +#keyset[id] +match_arm_guards( + int id: @match_arm ref, + int guard: @match_guard ref +); + +#keyset[id] +match_arm_pats( + int id: @match_arm ref, + int pat: @pat ref +); + +match_arm_lists( + unique int id: @match_arm_list +); + +#keyset[id, index] +match_arm_list_arms( + int id: @match_arm_list ref, + int index: int ref, + int arm: @match_arm ref +); + +#keyset[id, index] +match_arm_list_attrs( + int id: @match_arm_list ref, + int index: int ref, + int attr: @attr ref +); + +match_guards( + unique int id: @match_guard +); + +#keyset[id] +match_guard_conditions( + int id: @match_guard ref, + int condition: @expr ref +); + +meta( + unique int id: @meta +); + +#keyset[id] +meta_exprs( + int id: @meta ref, + int expr: @expr ref +); + +#keyset[id] +meta_is_unsafe( + int id: @meta ref +); + +#keyset[id] +meta_paths( + int id: @meta ref, + int path: @path ref +); + +#keyset[id] +meta_token_trees( + int id: @meta ref, + int token_tree: @token_tree ref +); + +names( + unique int id: @name +); + +#keyset[id] +name_texts( + int id: @name ref, + string text: string ref +); + +@param_base = + @param +| @self_param +; + +#keyset[id, index] +param_base_attrs( + int id: @param_base ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +param_base_type_reprs( + int id: @param_base ref, + int type_repr: @type_repr ref +); + +param_lists( + unique int id: @param_list +); + +#keyset[id, index] +param_list_params( + int id: @param_list ref, + int index: int ref, + int param: @param ref +); + +#keyset[id] +param_list_self_params( + int id: @param_list ref, + int self_param: @self_param ref +); + +parenthesized_arg_lists( + unique int id: @parenthesized_arg_list +); + +#keyset[id, index] +parenthesized_arg_list_type_args( + int id: @parenthesized_arg_list ref, + int index: int ref, + int type_arg: @type_arg ref +); + +@pat = + @box_pat +| @const_block_pat +| @ident_pat +| @literal_pat +| @macro_pat +| @or_pat +| @paren_pat +| @path_pat +| @range_pat +| @ref_pat +| @rest_pat +| @slice_pat +| @struct_pat +| @tuple_pat +| @tuple_struct_pat +| @wildcard_pat +; + +paths( + unique int id: @path +); + +#keyset[id] +path_qualifiers( + int id: @path ref, + int qualifier: @path ref +); + +#keyset[id] +path_segments_( + int id: @path ref, + int segment: @path_segment ref +); + +path_segments( + unique int id: @path_segment +); + +#keyset[id] +path_segment_generic_arg_lists( + int id: @path_segment ref, + int generic_arg_list: @generic_arg_list ref +); + +#keyset[id] +path_segment_identifiers( + int id: @path_segment ref, + int identifier: @name_ref ref +); + +#keyset[id] +path_segment_parenthesized_arg_lists( + int id: @path_segment ref, + int parenthesized_arg_list: @parenthesized_arg_list ref +); + +#keyset[id] +path_segment_ret_types( + int id: @path_segment ref, + int ret_type: @ret_type_repr ref +); + +#keyset[id] +path_segment_return_type_syntaxes( + int id: @path_segment ref, + int return_type_syntax: @return_type_syntax ref +); + +#keyset[id] +path_segment_type_reprs( + int id: @path_segment ref, + int type_repr: @type_repr ref +); + +#keyset[id] +path_segment_trait_type_reprs( + int id: @path_segment ref, + int trait_type_repr: @path_type_repr ref +); + +renames( + unique int id: @rename +); + +#keyset[id] +rename_names( + int id: @rename ref, + int name: @name ref +); + +@resolvable = + @method_call_expr +| @path_ast_node +; + +#keyset[id] +resolvable_resolved_paths( + int id: @resolvable ref, + string resolved_path: string ref +); + +#keyset[id] +resolvable_resolved_crate_origins( + int id: @resolvable ref, + string resolved_crate_origin: string ref +); + +ret_type_reprs( + unique int id: @ret_type_repr +); + +#keyset[id] +ret_type_repr_type_reprs( + int id: @ret_type_repr ref, + int type_repr: @type_repr ref +); + +return_type_syntaxes( + unique int id: @return_type_syntax +); + +source_files( + unique int id: @source_file +); + +#keyset[id, index] +source_file_attrs( + int id: @source_file ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +source_file_items( + int id: @source_file ref, + int index: int ref, + int item: @item ref +); + +@stmt = + @expr_stmt +| @item +| @let_stmt +; + +stmt_lists( + unique int id: @stmt_list +); + +#keyset[id, index] +stmt_list_attrs( + int id: @stmt_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +stmt_list_statements( + int id: @stmt_list ref, + int index: int ref, + int statement: @stmt ref +); + +#keyset[id] +stmt_list_tail_exprs( + int id: @stmt_list ref, + int tail_expr: @expr ref +); + +struct_expr_fields( + unique int id: @struct_expr_field +); + +#keyset[id, index] +struct_expr_field_attrs( + int id: @struct_expr_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_expr_field_exprs( + int id: @struct_expr_field ref, + int expr: @expr ref +); + +#keyset[id] +struct_expr_field_identifiers( + int id: @struct_expr_field ref, + int identifier: @name_ref ref +); + +struct_expr_field_lists( + unique int id: @struct_expr_field_list +); + +#keyset[id, index] +struct_expr_field_list_attrs( + int id: @struct_expr_field_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +struct_expr_field_list_fields( + int id: @struct_expr_field_list ref, + int index: int ref, + int field: @struct_expr_field ref +); + +#keyset[id] +struct_expr_field_list_spreads( + int id: @struct_expr_field_list ref, + int spread: @expr ref +); + +struct_fields( + unique int id: @struct_field +); + +#keyset[id, index] +struct_field_attrs( + int id: @struct_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_field_defaults( + int id: @struct_field ref, + int default: @expr ref +); + +#keyset[id] +struct_field_is_unsafe( + int id: @struct_field ref +); + +#keyset[id] +struct_field_names( + int id: @struct_field ref, + int name: @name ref +); + +#keyset[id] +struct_field_type_reprs( + int id: @struct_field ref, + int type_repr: @type_repr ref +); + +#keyset[id] +struct_field_visibilities( + int id: @struct_field ref, + int visibility: @visibility ref +); + +struct_pat_fields( + unique int id: @struct_pat_field +); + +#keyset[id, index] +struct_pat_field_attrs( + int id: @struct_pat_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_pat_field_identifiers( + int id: @struct_pat_field ref, + int identifier: @name_ref ref +); + +#keyset[id] +struct_pat_field_pats( + int id: @struct_pat_field ref, + int pat: @pat ref +); + +struct_pat_field_lists( + unique int id: @struct_pat_field_list +); + +#keyset[id, index] +struct_pat_field_list_fields( + int id: @struct_pat_field_list ref, + int index: int ref, + int field: @struct_pat_field ref +); + +#keyset[id] +struct_pat_field_list_rest_pats( + int id: @struct_pat_field_list ref, + int rest_pat: @rest_pat ref +); + +@token = + @comment +; + +token_trees( + unique int id: @token_tree +); + +tuple_fields( + unique int id: @tuple_field +); + +#keyset[id, index] +tuple_field_attrs( + int id: @tuple_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +tuple_field_type_reprs( + int id: @tuple_field ref, + int type_repr: @type_repr ref +); + +#keyset[id] +tuple_field_visibilities( + int id: @tuple_field ref, + int visibility: @visibility ref +); + +type_bounds( + unique int id: @type_bound +); + +#keyset[id] +type_bound_is_async( + int id: @type_bound ref +); + +#keyset[id] +type_bound_is_const( + int id: @type_bound ref +); + +#keyset[id] +type_bound_lifetimes( + int id: @type_bound ref, + int lifetime: @lifetime ref +); + +#keyset[id] +type_bound_type_reprs( + int id: @type_bound ref, + int type_repr: @type_repr ref +); + +#keyset[id] +type_bound_use_bound_generic_args( + int id: @type_bound ref, + int use_bound_generic_args: @use_bound_generic_args ref +); + +type_bound_lists( + unique int id: @type_bound_list +); + +#keyset[id, index] +type_bound_list_bounds( + int id: @type_bound_list ref, + int index: int ref, + int bound: @type_bound ref +); + +@type_repr = + @array_type_repr +| @dyn_trait_type_repr +| @fn_ptr_type_repr +| @for_type_repr +| @impl_trait_type_repr +| @infer_type_repr +| @macro_type_repr +| @never_type_repr +| @paren_type_repr +| @path_type_repr +| @ptr_type_repr +| @ref_type_repr +| @slice_type_repr +| @tuple_type_repr +; + +@use_bound_generic_arg = + @lifetime +| @name_ref +; + +use_bound_generic_args( + unique int id: @use_bound_generic_args +); + +#keyset[id, index] +use_bound_generic_args_use_bound_generic_args( + int id: @use_bound_generic_args ref, + int index: int ref, + int use_bound_generic_arg: @use_bound_generic_arg ref +); + +use_trees( + unique int id: @use_tree +); + +#keyset[id] +use_tree_is_glob( + int id: @use_tree ref +); + +#keyset[id] +use_tree_paths( + int id: @use_tree ref, + int path: @path ref +); + +#keyset[id] +use_tree_renames( + int id: @use_tree ref, + int rename: @rename ref +); + +#keyset[id] +use_tree_use_tree_lists( + int id: @use_tree ref, + int use_tree_list: @use_tree_list ref +); + +use_tree_lists( + unique int id: @use_tree_list +); + +#keyset[id, index] +use_tree_list_use_trees( + int id: @use_tree_list ref, + int index: int ref, + int use_tree: @use_tree ref +); + +@variant_def = + @struct +| @union +| @variant +; + +variant_lists( + unique int id: @variant_list +); + +#keyset[id, index] +variant_list_variants( + int id: @variant_list ref, + int index: int ref, + int variant: @variant ref +); + +visibilities( + unique int id: @visibility +); + +#keyset[id] +visibility_paths( + int id: @visibility ref, + int path: @path ref +); + +where_clauses( + unique int id: @where_clause +); + +#keyset[id, index] +where_clause_predicates( + int id: @where_clause ref, + int index: int ref, + int predicate: @where_pred ref +); + +where_preds( + unique int id: @where_pred +); + +#keyset[id] +where_pred_generic_param_lists( + int id: @where_pred ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +where_pred_lifetimes( + int id: @where_pred ref, + int lifetime: @lifetime ref +); + +#keyset[id] +where_pred_type_reprs( + int id: @where_pred ref, + int type_repr: @type_repr ref +); + +#keyset[id] +where_pred_type_bound_lists( + int id: @where_pred ref, + int type_bound_list: @type_bound_list ref +); + +array_expr_internals( + unique int id: @array_expr_internal +); + +#keyset[id, index] +array_expr_internal_attrs( + int id: @array_expr_internal ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +array_expr_internal_exprs( + int id: @array_expr_internal ref, + int index: int ref, + int expr: @expr ref +); + +#keyset[id] +array_expr_internal_is_semicolon( + int id: @array_expr_internal ref +); + +array_type_reprs( + unique int id: @array_type_repr +); + +#keyset[id] +array_type_repr_const_args( + int id: @array_type_repr ref, + int const_arg: @const_arg ref +); + +#keyset[id] +array_type_repr_element_type_reprs( + int id: @array_type_repr ref, + int element_type_repr: @type_repr ref +); + +asm_clobber_abis( + unique int id: @asm_clobber_abi +); + +asm_consts( + unique int id: @asm_const +); + +#keyset[id] +asm_const_exprs( + int id: @asm_const ref, + int expr: @expr ref +); + +#keyset[id] +asm_const_is_const( + int id: @asm_const ref +); + +asm_exprs( + unique int id: @asm_expr +); + +#keyset[id, index] +asm_expr_asm_pieces( + int id: @asm_expr ref, + int index: int ref, + int asm_piece: @asm_piece ref +); + +#keyset[id, index] +asm_expr_attrs( + int id: @asm_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +asm_expr_templates( + int id: @asm_expr ref, + int index: int ref, + int template: @expr ref +); + +asm_labels( + unique int id: @asm_label +); + +#keyset[id] +asm_label_block_exprs( + int id: @asm_label ref, + int block_expr: @block_expr ref +); + +asm_operand_nameds( + unique int id: @asm_operand_named +); + +#keyset[id] +asm_operand_named_asm_operands( + int id: @asm_operand_named ref, + int asm_operand: @asm_operand ref +); + +#keyset[id] +asm_operand_named_names( + int id: @asm_operand_named ref, + int name: @name ref +); + +asm_options_lists( + unique int id: @asm_options_list +); + +#keyset[id, index] +asm_options_list_asm_options( + int id: @asm_options_list ref, + int index: int ref, + int asm_option: @asm_option ref +); + +asm_reg_operands( + unique int id: @asm_reg_operand +); + +#keyset[id] +asm_reg_operand_asm_dir_specs( + int id: @asm_reg_operand ref, + int asm_dir_spec: @asm_dir_spec ref +); + +#keyset[id] +asm_reg_operand_asm_operand_exprs( + int id: @asm_reg_operand ref, + int asm_operand_expr: @asm_operand_expr ref +); + +#keyset[id] +asm_reg_operand_asm_reg_specs( + int id: @asm_reg_operand ref, + int asm_reg_spec: @asm_reg_spec ref +); + +asm_syms( + unique int id: @asm_sym +); + +#keyset[id] +asm_sym_paths( + int id: @asm_sym ref, + int path: @path ref +); + +assoc_type_args( + unique int id: @assoc_type_arg +); + +#keyset[id] +assoc_type_arg_const_args( + int id: @assoc_type_arg ref, + int const_arg: @const_arg ref +); + +#keyset[id] +assoc_type_arg_generic_arg_lists( + int id: @assoc_type_arg ref, + int generic_arg_list: @generic_arg_list ref +); + +#keyset[id] +assoc_type_arg_identifiers( + int id: @assoc_type_arg ref, + int identifier: @name_ref ref +); + +#keyset[id] +assoc_type_arg_param_lists( + int id: @assoc_type_arg ref, + int param_list: @param_list ref +); + +#keyset[id] +assoc_type_arg_ret_types( + int id: @assoc_type_arg ref, + int ret_type: @ret_type_repr ref +); + +#keyset[id] +assoc_type_arg_return_type_syntaxes( + int id: @assoc_type_arg ref, + int return_type_syntax: @return_type_syntax ref +); + +#keyset[id] +assoc_type_arg_type_reprs( + int id: @assoc_type_arg ref, + int type_repr: @type_repr ref +); + +#keyset[id] +assoc_type_arg_type_bound_lists( + int id: @assoc_type_arg ref, + int type_bound_list: @type_bound_list ref +); + +await_exprs( + unique int id: @await_expr +); + +#keyset[id, index] +await_expr_attrs( + int id: @await_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +await_expr_exprs( + int id: @await_expr ref, + int expr: @expr ref +); + +become_exprs( + unique int id: @become_expr +); + +#keyset[id, index] +become_expr_attrs( + int id: @become_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +become_expr_exprs( + int id: @become_expr ref, + int expr: @expr ref +); + +binary_exprs( + unique int id: @binary_expr +); + +#keyset[id, index] +binary_expr_attrs( + int id: @binary_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +binary_expr_lhs( + int id: @binary_expr ref, + int lhs: @expr ref +); + +#keyset[id] +binary_expr_operator_names( + int id: @binary_expr ref, + string operator_name: string ref +); + +#keyset[id] +binary_expr_rhs( + int id: @binary_expr ref, + int rhs: @expr ref +); + +box_pats( + unique int id: @box_pat +); + +#keyset[id] +box_pat_pats( + int id: @box_pat ref, + int pat: @pat ref +); + +break_exprs( + unique int id: @break_expr +); + +#keyset[id, index] +break_expr_attrs( + int id: @break_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +break_expr_exprs( + int id: @break_expr ref, + int expr: @expr ref +); + +#keyset[id] +break_expr_lifetimes( + int id: @break_expr ref, + int lifetime: @lifetime ref +); + +@call_expr_base = + @call_expr +| @method_call_expr +; + +#keyset[id] +call_expr_base_arg_lists( + int id: @call_expr_base ref, + int arg_list: @arg_list ref +); + +#keyset[id, index] +call_expr_base_attrs( + int id: @call_expr_base ref, + int index: int ref, + int attr: @attr ref +); + +cast_exprs( + unique int id: @cast_expr +); + +#keyset[id, index] +cast_expr_attrs( + int id: @cast_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +cast_expr_exprs( + int id: @cast_expr ref, + int expr: @expr ref +); + +#keyset[id] +cast_expr_type_reprs( + int id: @cast_expr ref, + int type_repr: @type_repr ref +); + +closure_exprs( + unique int id: @closure_expr +); + +#keyset[id] +closure_expr_bodies( + int id: @closure_expr ref, + int body: @expr ref +); + +#keyset[id] +closure_expr_closure_binders( + int id: @closure_expr ref, + int closure_binder: @closure_binder ref +); + +#keyset[id] +closure_expr_is_async( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_const( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_gen( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_move( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_static( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_ret_types( + int id: @closure_expr ref, + int ret_type: @ret_type_repr ref +); + +comments( + unique int id: @comment, + int parent: @ast_node ref, + string text: string ref +); + +const_args( + unique int id: @const_arg +); + +#keyset[id] +const_arg_exprs( + int id: @const_arg ref, + int expr: @expr ref +); + +const_block_pats( + unique int id: @const_block_pat +); + +#keyset[id] +const_block_pat_block_exprs( + int id: @const_block_pat ref, + int block_expr: @block_expr ref +); + +#keyset[id] +const_block_pat_is_const( + int id: @const_block_pat ref +); + +const_params( + unique int id: @const_param +); + +#keyset[id, index] +const_param_attrs( + int id: @const_param ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +const_param_default_vals( + int id: @const_param ref, + int default_val: @const_arg ref +); + +#keyset[id] +const_param_is_const( + int id: @const_param ref +); + +#keyset[id] +const_param_names( + int id: @const_param ref, + int name: @name ref +); + +#keyset[id] +const_param_type_reprs( + int id: @const_param ref, + int type_repr: @type_repr ref +); + +continue_exprs( + unique int id: @continue_expr +); + +#keyset[id, index] +continue_expr_attrs( + int id: @continue_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +continue_expr_lifetimes( + int id: @continue_expr ref, + int lifetime: @lifetime ref +); + +dyn_trait_type_reprs( + unique int id: @dyn_trait_type_repr +); + +#keyset[id] +dyn_trait_type_repr_type_bound_lists( + int id: @dyn_trait_type_repr ref, + int type_bound_list: @type_bound_list ref +); + +expr_stmts( + unique int id: @expr_stmt +); + +#keyset[id] +expr_stmt_exprs( + int id: @expr_stmt ref, + int expr: @expr ref +); + +field_exprs( + unique int id: @field_expr +); + +#keyset[id, index] +field_expr_attrs( + int id: @field_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +field_expr_containers( + int id: @field_expr ref, + int container: @expr ref +); + +#keyset[id] +field_expr_identifiers( + int id: @field_expr ref, + int identifier: @name_ref ref +); + +fn_ptr_type_reprs( + unique int id: @fn_ptr_type_repr +); + +#keyset[id] +fn_ptr_type_repr_abis( + int id: @fn_ptr_type_repr ref, + int abi: @abi ref +); + +#keyset[id] +fn_ptr_type_repr_is_async( + int id: @fn_ptr_type_repr ref +); + +#keyset[id] +fn_ptr_type_repr_is_const( + int id: @fn_ptr_type_repr ref +); + +#keyset[id] +fn_ptr_type_repr_is_unsafe( + int id: @fn_ptr_type_repr ref +); + +#keyset[id] +fn_ptr_type_repr_param_lists( + int id: @fn_ptr_type_repr ref, + int param_list: @param_list ref +); + +#keyset[id] +fn_ptr_type_repr_ret_types( + int id: @fn_ptr_type_repr ref, + int ret_type: @ret_type_repr ref +); + +for_type_reprs( + unique int id: @for_type_repr +); + +#keyset[id] +for_type_repr_generic_param_lists( + int id: @for_type_repr ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +for_type_repr_type_reprs( + int id: @for_type_repr ref, + int type_repr: @type_repr ref +); + +format_args_exprs( + unique int id: @format_args_expr +); + +#keyset[id, index] +format_args_expr_args( + int id: @format_args_expr ref, + int index: int ref, + int arg: @format_args_arg ref +); + +#keyset[id, index] +format_args_expr_attrs( + int id: @format_args_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +format_args_expr_templates( + int id: @format_args_expr ref, + int template: @expr ref +); + +ident_pats( + unique int id: @ident_pat +); + +#keyset[id, index] +ident_pat_attrs( + int id: @ident_pat ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +ident_pat_is_mut( + int id: @ident_pat ref +); + +#keyset[id] +ident_pat_is_ref( + int id: @ident_pat ref +); + +#keyset[id] +ident_pat_names( + int id: @ident_pat ref, + int name: @name ref +); + +#keyset[id] +ident_pat_pats( + int id: @ident_pat ref, + int pat: @pat ref +); + +if_exprs( + unique int id: @if_expr +); + +#keyset[id, index] +if_expr_attrs( + int id: @if_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +if_expr_conditions( + int id: @if_expr ref, + int condition: @expr ref +); + +#keyset[id] +if_expr_elses( + int id: @if_expr ref, + int else: @expr ref +); + +#keyset[id] +if_expr_thens( + int id: @if_expr ref, + int then: @block_expr ref +); + +impl_trait_type_reprs( + unique int id: @impl_trait_type_repr +); + +#keyset[id] +impl_trait_type_repr_type_bound_lists( + int id: @impl_trait_type_repr ref, + int type_bound_list: @type_bound_list ref +); + +index_exprs( + unique int id: @index_expr +); + +#keyset[id, index] +index_expr_attrs( + int id: @index_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +index_expr_bases( + int id: @index_expr ref, + int base: @expr ref +); + +#keyset[id] +index_expr_indices( + int id: @index_expr ref, + int index: @expr ref +); + +infer_type_reprs( + unique int id: @infer_type_repr +); + +@item = + @const +| @enum +| @extern_block +| @extern_crate +| @function +| @impl +| @macro_call +| @macro_def +| @macro_rules +| @module +| @static +| @struct +| @trait +| @trait_alias +| @type_alias +| @union +| @use +; + +@labelable_expr = + @block_expr +| @looping_expr +; + +#keyset[id] +labelable_expr_labels( + int id: @labelable_expr ref, + int label: @label ref +); + +let_exprs( + unique int id: @let_expr +); + +#keyset[id, index] +let_expr_attrs( + int id: @let_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +let_expr_scrutinees( + int id: @let_expr ref, + int scrutinee: @expr ref +); + +#keyset[id] +let_expr_pats( + int id: @let_expr ref, + int pat: @pat ref +); + +let_stmts( + unique int id: @let_stmt +); + +#keyset[id, index] +let_stmt_attrs( + int id: @let_stmt ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +let_stmt_initializers( + int id: @let_stmt ref, + int initializer: @expr ref +); + +#keyset[id] +let_stmt_let_elses( + int id: @let_stmt ref, + int let_else: @let_else ref +); + +#keyset[id] +let_stmt_pats( + int id: @let_stmt ref, + int pat: @pat ref +); + +#keyset[id] +let_stmt_type_reprs( + int id: @let_stmt ref, + int type_repr: @type_repr ref +); + +lifetimes( + unique int id: @lifetime +); + +#keyset[id] +lifetime_texts( + int id: @lifetime ref, + string text: string ref +); + +lifetime_args( + unique int id: @lifetime_arg +); + +#keyset[id] +lifetime_arg_lifetimes( + int id: @lifetime_arg ref, + int lifetime: @lifetime ref +); + +lifetime_params( + unique int id: @lifetime_param +); + +#keyset[id, index] +lifetime_param_attrs( + int id: @lifetime_param ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +lifetime_param_lifetimes( + int id: @lifetime_param ref, + int lifetime: @lifetime ref +); + +#keyset[id] +lifetime_param_type_bound_lists( + int id: @lifetime_param ref, + int type_bound_list: @type_bound_list ref +); + +literal_exprs( + unique int id: @literal_expr +); + +#keyset[id, index] +literal_expr_attrs( + int id: @literal_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +literal_expr_text_values( + int id: @literal_expr ref, + string text_value: string ref +); + +literal_pats( + unique int id: @literal_pat +); + +#keyset[id] +literal_pat_literals( + int id: @literal_pat ref, + int literal: @literal_expr ref +); + +macro_exprs( + unique int id: @macro_expr +); + +#keyset[id] +macro_expr_macro_calls( + int id: @macro_expr ref, + int macro_call: @macro_call ref +); + +macro_pats( + unique int id: @macro_pat +); + +#keyset[id] +macro_pat_macro_calls( + int id: @macro_pat ref, + int macro_call: @macro_call ref +); + +macro_type_reprs( + unique int id: @macro_type_repr +); + +#keyset[id] +macro_type_repr_macro_calls( + int id: @macro_type_repr ref, + int macro_call: @macro_call ref +); + +match_exprs( + unique int id: @match_expr +); + +#keyset[id, index] +match_expr_attrs( + int id: @match_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +match_expr_scrutinees( + int id: @match_expr ref, + int scrutinee: @expr ref +); + +#keyset[id] +match_expr_match_arm_lists( + int id: @match_expr ref, + int match_arm_list: @match_arm_list ref +); + +name_refs( + unique int id: @name_ref +); + +#keyset[id] +name_ref_texts( + int id: @name_ref ref, + string text: string ref +); + +never_type_reprs( + unique int id: @never_type_repr +); + +offset_of_exprs( + unique int id: @offset_of_expr +); + +#keyset[id, index] +offset_of_expr_attrs( + int id: @offset_of_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +offset_of_expr_fields( + int id: @offset_of_expr ref, + int index: int ref, + int field: @name_ref ref +); + +#keyset[id] +offset_of_expr_type_reprs( + int id: @offset_of_expr ref, + int type_repr: @type_repr ref +); + +or_pats( + unique int id: @or_pat +); + +#keyset[id, index] +or_pat_pats( + int id: @or_pat ref, + int index: int ref, + int pat: @pat ref +); + +params( + unique int id: @param +); + +#keyset[id] +param_pats( + int id: @param ref, + int pat: @pat ref +); + +paren_exprs( + unique int id: @paren_expr +); + +#keyset[id, index] +paren_expr_attrs( + int id: @paren_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +paren_expr_exprs( + int id: @paren_expr ref, + int expr: @expr ref +); + +paren_pats( + unique int id: @paren_pat +); + +#keyset[id] +paren_pat_pats( + int id: @paren_pat ref, + int pat: @pat ref +); + +paren_type_reprs( + unique int id: @paren_type_repr +); + +#keyset[id] +paren_type_repr_type_reprs( + int id: @paren_type_repr ref, + int type_repr: @type_repr ref +); + +@path_ast_node = + @path_expr +| @path_pat +| @struct_expr +| @struct_pat +| @tuple_struct_pat +; + +#keyset[id] +path_ast_node_paths( + int id: @path_ast_node ref, + int path: @path ref +); + +@path_expr_base = + @path_expr +; + +path_type_reprs( + unique int id: @path_type_repr +); + +#keyset[id] +path_type_repr_paths( + int id: @path_type_repr ref, + int path: @path ref +); + +prefix_exprs( + unique int id: @prefix_expr +); + +#keyset[id, index] +prefix_expr_attrs( + int id: @prefix_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +prefix_expr_exprs( + int id: @prefix_expr ref, + int expr: @expr ref +); + +#keyset[id] +prefix_expr_operator_names( + int id: @prefix_expr ref, + string operator_name: string ref +); + +ptr_type_reprs( + unique int id: @ptr_type_repr +); + +#keyset[id] +ptr_type_repr_is_const( + int id: @ptr_type_repr ref +); + +#keyset[id] +ptr_type_repr_is_mut( + int id: @ptr_type_repr ref +); + +#keyset[id] +ptr_type_repr_type_reprs( + int id: @ptr_type_repr ref, + int type_repr: @type_repr ref +); + +range_exprs( + unique int id: @range_expr +); + +#keyset[id, index] +range_expr_attrs( + int id: @range_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +range_expr_ends( + int id: @range_expr ref, + int end: @expr ref +); + +#keyset[id] +range_expr_operator_names( + int id: @range_expr ref, + string operator_name: string ref +); + +#keyset[id] +range_expr_starts( + int id: @range_expr ref, + int start: @expr ref +); + +range_pats( + unique int id: @range_pat +); + +#keyset[id] +range_pat_ends( + int id: @range_pat ref, + int end: @pat ref +); + +#keyset[id] +range_pat_operator_names( + int id: @range_pat ref, + string operator_name: string ref +); + +#keyset[id] +range_pat_starts( + int id: @range_pat ref, + int start: @pat ref +); + +ref_exprs( + unique int id: @ref_expr +); + +#keyset[id, index] +ref_expr_attrs( + int id: @ref_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +ref_expr_exprs( + int id: @ref_expr ref, + int expr: @expr ref +); + +#keyset[id] +ref_expr_is_const( + int id: @ref_expr ref +); + +#keyset[id] +ref_expr_is_mut( + int id: @ref_expr ref +); + +#keyset[id] +ref_expr_is_raw( + int id: @ref_expr ref +); + +ref_pats( + unique int id: @ref_pat +); + +#keyset[id] +ref_pat_is_mut( + int id: @ref_pat ref +); + +#keyset[id] +ref_pat_pats( + int id: @ref_pat ref, + int pat: @pat ref +); + +ref_type_reprs( + unique int id: @ref_type_repr +); + +#keyset[id] +ref_type_repr_is_mut( + int id: @ref_type_repr ref +); + +#keyset[id] +ref_type_repr_lifetimes( + int id: @ref_type_repr ref, + int lifetime: @lifetime ref +); + +#keyset[id] +ref_type_repr_type_reprs( + int id: @ref_type_repr ref, + int type_repr: @type_repr ref +); + +rest_pats( + unique int id: @rest_pat +); + +#keyset[id, index] +rest_pat_attrs( + int id: @rest_pat ref, + int index: int ref, + int attr: @attr ref +); + +return_exprs( + unique int id: @return_expr +); + +#keyset[id, index] +return_expr_attrs( + int id: @return_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +return_expr_exprs( + int id: @return_expr ref, + int expr: @expr ref +); + +self_params( + unique int id: @self_param +); + +#keyset[id] +self_param_is_ref( + int id: @self_param ref +); + +#keyset[id] +self_param_is_mut( + int id: @self_param ref +); + +#keyset[id] +self_param_lifetimes( + int id: @self_param ref, + int lifetime: @lifetime ref +); + +#keyset[id] +self_param_names( + int id: @self_param ref, + int name: @name ref +); + +slice_pats( + unique int id: @slice_pat +); + +#keyset[id, index] +slice_pat_pats( + int id: @slice_pat ref, + int index: int ref, + int pat: @pat ref +); + +slice_type_reprs( + unique int id: @slice_type_repr +); + +#keyset[id] +slice_type_repr_type_reprs( + int id: @slice_type_repr ref, + int type_repr: @type_repr ref +); + +struct_field_lists( + unique int id: @struct_field_list +); + +#keyset[id, index] +struct_field_list_fields( + int id: @struct_field_list ref, + int index: int ref, + int field: @struct_field ref +); + +try_exprs( + unique int id: @try_expr +); + +#keyset[id, index] +try_expr_attrs( + int id: @try_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +try_expr_exprs( + int id: @try_expr ref, + int expr: @expr ref +); + +tuple_exprs( + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_attrs( + int id: @tuple_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +tuple_expr_fields( + int id: @tuple_expr ref, + int index: int ref, + int field: @expr ref +); + +tuple_field_lists( + unique int id: @tuple_field_list +); + +#keyset[id, index] +tuple_field_list_fields( + int id: @tuple_field_list ref, + int index: int ref, + int field: @tuple_field ref +); + +tuple_pats( + unique int id: @tuple_pat +); + +#keyset[id, index] +tuple_pat_fields( + int id: @tuple_pat ref, + int index: int ref, + int field: @pat ref +); + +tuple_type_reprs( + unique int id: @tuple_type_repr +); + +#keyset[id, index] +tuple_type_repr_fields( + int id: @tuple_type_repr ref, + int index: int ref, + int field: @type_repr ref +); + +type_args( + unique int id: @type_arg +); + +#keyset[id] +type_arg_type_reprs( + int id: @type_arg ref, + int type_repr: @type_repr ref +); + +type_params( + unique int id: @type_param +); + +#keyset[id, index] +type_param_attrs( + int id: @type_param ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +type_param_default_types( + int id: @type_param ref, + int default_type: @type_repr ref +); + +#keyset[id] +type_param_names( + int id: @type_param ref, + int name: @name ref +); + +#keyset[id] +type_param_type_bound_lists( + int id: @type_param ref, + int type_bound_list: @type_bound_list ref +); + +underscore_exprs( + unique int id: @underscore_expr +); + +#keyset[id, index] +underscore_expr_attrs( + int id: @underscore_expr ref, + int index: int ref, + int attr: @attr ref +); + +variants( + unique int id: @variant +); + +#keyset[id, index] +variant_attrs( + int id: @variant ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +variant_discriminants( + int id: @variant ref, + int discriminant: @expr ref +); + +#keyset[id] +variant_field_lists( + int id: @variant ref, + int field_list: @field_list ref +); + +#keyset[id] +variant_names( + int id: @variant ref, + int name: @name ref +); + +#keyset[id] +variant_visibilities( + int id: @variant ref, + int visibility: @visibility ref +); + +wildcard_pats( + unique int id: @wildcard_pat +); + +yeet_exprs( + unique int id: @yeet_expr +); + +#keyset[id, index] +yeet_expr_attrs( + int id: @yeet_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +yeet_expr_exprs( + int id: @yeet_expr ref, + int expr: @expr ref +); + +yield_exprs( + unique int id: @yield_expr +); + +#keyset[id, index] +yield_expr_attrs( + int id: @yield_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +yield_expr_exprs( + int id: @yield_expr ref, + int expr: @expr ref +); + +block_exprs( + unique int id: @block_expr +); + +#keyset[id, index] +block_expr_attrs( + int id: @block_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +block_expr_is_async( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_const( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_gen( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_move( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_try( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_unsafe( + int id: @block_expr ref +); + +#keyset[id] +block_expr_stmt_lists( + int id: @block_expr ref, + int stmt_list: @stmt_list ref +); + +call_exprs( + unique int id: @call_expr +); + +#keyset[id] +call_expr_functions( + int id: @call_expr ref, + int function: @expr ref +); + +consts( + unique int id: @const +); + +#keyset[id, index] +const_attrs( + int id: @const ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +const_bodies( + int id: @const ref, + int body: @expr ref +); + +#keyset[id] +const_is_const( + int id: @const ref +); + +#keyset[id] +const_is_default( + int id: @const ref +); + +#keyset[id] +const_names( + int id: @const ref, + int name: @name ref +); + +#keyset[id] +const_type_reprs( + int id: @const ref, + int type_repr: @type_repr ref +); + +#keyset[id] +const_visibilities( + int id: @const ref, + int visibility: @visibility ref +); + +enums( + unique int id: @enum +); + +#keyset[id, index] +enum_attrs( + int id: @enum ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +enum_generic_param_lists( + int id: @enum ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +enum_names( + int id: @enum ref, + int name: @name ref +); + +#keyset[id] +enum_variant_lists( + int id: @enum ref, + int variant_list: @variant_list ref +); + +#keyset[id] +enum_visibilities( + int id: @enum ref, + int visibility: @visibility ref +); + +#keyset[id] +enum_where_clauses( + int id: @enum ref, + int where_clause: @where_clause ref +); + +extern_blocks( + unique int id: @extern_block +); + +#keyset[id] +extern_block_abis( + int id: @extern_block ref, + int abi: @abi ref +); + +#keyset[id, index] +extern_block_attrs( + int id: @extern_block ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +extern_block_extern_item_lists( + int id: @extern_block ref, + int extern_item_list: @extern_item_list ref +); + +#keyset[id] +extern_block_is_unsafe( + int id: @extern_block ref +); + +extern_crates( + unique int id: @extern_crate +); + +#keyset[id, index] +extern_crate_attrs( + int id: @extern_crate ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +extern_crate_identifiers( + int id: @extern_crate ref, + int identifier: @name_ref ref +); + +#keyset[id] +extern_crate_renames( + int id: @extern_crate ref, + int rename: @rename ref +); + +#keyset[id] +extern_crate_visibilities( + int id: @extern_crate ref, + int visibility: @visibility ref +); + +functions( + unique int id: @function +); + +#keyset[id] +function_abis( + int id: @function ref, + int abi: @abi ref +); + +#keyset[id] +function_bodies( + int id: @function ref, + int body: @block_expr ref +); + +#keyset[id] +function_generic_param_lists( + int id: @function ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +function_is_async( + int id: @function ref +); + +#keyset[id] +function_is_const( + int id: @function ref +); + +#keyset[id] +function_is_default( + int id: @function ref +); + +#keyset[id] +function_is_gen( + int id: @function ref +); + +#keyset[id] +function_is_unsafe( + int id: @function ref +); + +#keyset[id] +function_names( + int id: @function ref, + int name: @name ref +); + +#keyset[id] +function_ret_types( + int id: @function ref, + int ret_type: @ret_type_repr ref +); + +#keyset[id] +function_visibilities( + int id: @function ref, + int visibility: @visibility ref +); + +#keyset[id] +function_where_clauses( + int id: @function ref, + int where_clause: @where_clause ref +); + +impls( + unique int id: @impl +); + +#keyset[id] +impl_assoc_item_lists( + int id: @impl ref, + int assoc_item_list: @assoc_item_list ref +); + +#keyset[id, index] +impl_attrs( + int id: @impl ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +impl_generic_param_lists( + int id: @impl ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +impl_is_const( + int id: @impl ref +); + +#keyset[id] +impl_is_default( + int id: @impl ref +); + +#keyset[id] +impl_is_unsafe( + int id: @impl ref +); + +#keyset[id] +impl_self_ties( + int id: @impl ref, + int self_ty: @type_repr ref +); + +#keyset[id] +impl_traits( + int id: @impl ref, + int trait: @type_repr ref +); + +#keyset[id] +impl_visibilities( + int id: @impl ref, + int visibility: @visibility ref +); + +#keyset[id] +impl_where_clauses( + int id: @impl ref, + int where_clause: @where_clause ref +); + +@looping_expr = + @for_expr +| @loop_expr +| @while_expr +; + +#keyset[id] +looping_expr_loop_bodies( + int id: @looping_expr ref, + int loop_body: @block_expr ref +); + +macro_calls( + unique int id: @macro_call +); + +#keyset[id, index] +macro_call_attrs( + int id: @macro_call ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +macro_call_paths( + int id: @macro_call ref, + int path: @path ref +); + +#keyset[id] +macro_call_token_trees( + int id: @macro_call ref, + int token_tree: @token_tree ref +); + +#keyset[id] +macro_call_expandeds( + int id: @macro_call ref, + int expanded: @ast_node ref +); + +macro_defs( + unique int id: @macro_def +); + +#keyset[id] +macro_def_args( + int id: @macro_def ref, + int args: @token_tree ref +); + +#keyset[id, index] +macro_def_attrs( + int id: @macro_def ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +macro_def_bodies( + int id: @macro_def ref, + int body: @token_tree ref +); + +#keyset[id] +macro_def_names( + int id: @macro_def ref, + int name: @name ref +); + +#keyset[id] +macro_def_visibilities( + int id: @macro_def ref, + int visibility: @visibility ref +); + +macro_rules( + unique int id: @macro_rules +); + +#keyset[id, index] +macro_rules_attrs( + int id: @macro_rules ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +macro_rules_names( + int id: @macro_rules ref, + int name: @name ref +); + +#keyset[id] +macro_rules_token_trees( + int id: @macro_rules ref, + int token_tree: @token_tree ref +); + +#keyset[id] +macro_rules_visibilities( + int id: @macro_rules ref, + int visibility: @visibility ref +); + +method_call_exprs( + unique int id: @method_call_expr +); + +#keyset[id] +method_call_expr_generic_arg_lists( + int id: @method_call_expr ref, + int generic_arg_list: @generic_arg_list ref +); + +#keyset[id] +method_call_expr_identifiers( + int id: @method_call_expr ref, + int identifier: @name_ref ref +); + +#keyset[id] +method_call_expr_receivers( + int id: @method_call_expr ref, + int receiver: @expr ref +); + +modules( + unique int id: @module +); + +#keyset[id, index] +module_attrs( + int id: @module ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +module_item_lists( + int id: @module ref, + int item_list: @item_list ref +); + +#keyset[id] +module_names( + int id: @module ref, + int name: @name ref +); + +#keyset[id] +module_visibilities( + int id: @module ref, + int visibility: @visibility ref +); + +path_exprs( + unique int id: @path_expr +); + +#keyset[id, index] +path_expr_attrs( + int id: @path_expr ref, + int index: int ref, + int attr: @attr ref +); + +path_pats( + unique int id: @path_pat +); + +statics( + unique int id: @static +); + +#keyset[id, index] +static_attrs( + int id: @static ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +static_bodies( + int id: @static ref, + int body: @expr ref +); + +#keyset[id] +static_is_mut( + int id: @static ref +); + +#keyset[id] +static_is_static( + int id: @static ref +); + +#keyset[id] +static_is_unsafe( + int id: @static ref +); + +#keyset[id] +static_names( + int id: @static ref, + int name: @name ref +); + +#keyset[id] +static_type_reprs( + int id: @static ref, + int type_repr: @type_repr ref +); + +#keyset[id] +static_visibilities( + int id: @static ref, + int visibility: @visibility ref +); + +structs( + unique int id: @struct +); + +#keyset[id, index] +struct_attrs( + int id: @struct ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_field_lists_( + int id: @struct ref, + int field_list: @field_list ref +); + +#keyset[id] +struct_generic_param_lists( + int id: @struct ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +struct_names( + int id: @struct ref, + int name: @name ref +); + +#keyset[id] +struct_visibilities( + int id: @struct ref, + int visibility: @visibility ref +); + +#keyset[id] +struct_where_clauses( + int id: @struct ref, + int where_clause: @where_clause ref +); + +struct_exprs( + unique int id: @struct_expr +); + +#keyset[id] +struct_expr_struct_expr_field_lists( + int id: @struct_expr ref, + int struct_expr_field_list: @struct_expr_field_list ref +); + +struct_pats( + unique int id: @struct_pat +); + +#keyset[id] +struct_pat_struct_pat_field_lists( + int id: @struct_pat ref, + int struct_pat_field_list: @struct_pat_field_list ref +); + +traits( + unique int id: @trait +); + +#keyset[id] +trait_assoc_item_lists( + int id: @trait ref, + int assoc_item_list: @assoc_item_list ref +); + +#keyset[id, index] +trait_attrs( + int id: @trait ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +trait_generic_param_lists( + int id: @trait ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +trait_is_auto( + int id: @trait ref +); + +#keyset[id] +trait_is_unsafe( + int id: @trait ref +); + +#keyset[id] +trait_names( + int id: @trait ref, + int name: @name ref +); + +#keyset[id] +trait_type_bound_lists( + int id: @trait ref, + int type_bound_list: @type_bound_list ref +); + +#keyset[id] +trait_visibilities( + int id: @trait ref, + int visibility: @visibility ref +); + +#keyset[id] +trait_where_clauses( + int id: @trait ref, + int where_clause: @where_clause ref +); + +trait_aliases( + unique int id: @trait_alias +); + +#keyset[id, index] +trait_alias_attrs( + int id: @trait_alias ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +trait_alias_generic_param_lists( + int id: @trait_alias ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +trait_alias_names( + int id: @trait_alias ref, + int name: @name ref +); + +#keyset[id] +trait_alias_type_bound_lists( + int id: @trait_alias ref, + int type_bound_list: @type_bound_list ref +); + +#keyset[id] +trait_alias_visibilities( + int id: @trait_alias ref, + int visibility: @visibility ref +); + +#keyset[id] +trait_alias_where_clauses( + int id: @trait_alias ref, + int where_clause: @where_clause ref +); + +tuple_struct_pats( + unique int id: @tuple_struct_pat +); + +#keyset[id, index] +tuple_struct_pat_fields( + int id: @tuple_struct_pat ref, + int index: int ref, + int field: @pat ref +); + +type_aliases( + unique int id: @type_alias +); + +#keyset[id, index] +type_alias_attrs( + int id: @type_alias ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +type_alias_generic_param_lists( + int id: @type_alias ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +type_alias_is_default( + int id: @type_alias ref +); + +#keyset[id] +type_alias_names( + int id: @type_alias ref, + int name: @name ref +); + +#keyset[id] +type_alias_type_reprs( + int id: @type_alias ref, + int type_repr: @type_repr ref +); + +#keyset[id] +type_alias_type_bound_lists( + int id: @type_alias ref, + int type_bound_list: @type_bound_list ref +); + +#keyset[id] +type_alias_visibilities( + int id: @type_alias ref, + int visibility: @visibility ref +); + +#keyset[id] +type_alias_where_clauses( + int id: @type_alias ref, + int where_clause: @where_clause ref +); + +unions( + unique int id: @union +); + +#keyset[id, index] +union_attrs( + int id: @union ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +union_generic_param_lists( + int id: @union ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +union_names( + int id: @union ref, + int name: @name ref +); + +#keyset[id] +union_struct_field_lists( + int id: @union ref, + int struct_field_list: @struct_field_list ref +); + +#keyset[id] +union_visibilities( + int id: @union ref, + int visibility: @visibility ref +); + +#keyset[id] +union_where_clauses( + int id: @union ref, + int where_clause: @where_clause ref +); + +uses( + unique int id: @use +); + +#keyset[id, index] +use_attrs( + int id: @use ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +use_use_trees( + int id: @use ref, + int use_tree: @use_tree ref +); + +#keyset[id] +use_visibilities( + int id: @use ref, + int visibility: @visibility ref +); + +for_exprs( + unique int id: @for_expr +); + +#keyset[id, index] +for_expr_attrs( + int id: @for_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +for_expr_iterables( + int id: @for_expr ref, + int iterable: @expr ref +); + +#keyset[id] +for_expr_pats( + int id: @for_expr ref, + int pat: @pat ref +); + +loop_exprs( + unique int id: @loop_expr +); + +#keyset[id, index] +loop_expr_attrs( + int id: @loop_expr ref, + int index: int ref, + int attr: @attr ref +); + +while_exprs( + unique int id: @while_expr +); + +#keyset[id, index] +while_expr_attrs( + int id: @while_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +while_expr_conditions( + int id: @while_expr ref, + int condition: @expr ref +); diff --git a/rust/downgrades/58bc96172f5a76faffc04004933865aa3c3b3e62/upgrade.properties b/rust/downgrades/58bc96172f5a76faffc04004933865aa3c3b3e62/upgrade.properties new file mode 100644 index 000000000000..61d3e02cd8a0 --- /dev/null +++ b/rust/downgrades/58bc96172f5a76faffc04004933865aa3c3b3e62/upgrade.properties @@ -0,0 +1,9 @@ +description: Rename MacroBlockExpr to MacroStmts +compatibility: full + +macro_stmts.rel: reorder macro_block_exprs(@macro_block_expr id) id +macro_stmts_exprs.rel: reorder macro_block_expr_tail_exprs(@macro_block_expr id, @expr tail_expr) id tail_expr +macro_stmts_statements.rel: reorder macro_block_expr_statements(@macro_block_expr id, int index, @stmt statement) id index statement +macro_block_exprs.rel: delete +macro_block_expr_tail_exprs.rel: delete +macro_block_expr_statements.rel: delete \ No newline at end of file diff --git a/rust/ql/lib/upgrades/e8707b675dc574aca9863eabcc09ac76f15bb9c2/old.dbscheme b/rust/ql/lib/upgrades/e8707b675dc574aca9863eabcc09ac76f15bb9c2/old.dbscheme new file mode 100644 index 000000000000..e8707b675dc5 --- /dev/null +++ b/rust/ql/lib/upgrades/e8707b675dc574aca9863eabcc09ac76f15bb9c2/old.dbscheme @@ -0,0 +1,3606 @@ +// generated by codegen, do not edit + +// from ../shared/tree-sitter-extractor/src/generator/prefix.dbscheme +/*- Files and folders -*/ + +/** + * The location of an element. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @file | @folder + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/*- Empty location -*/ + +empty_location( + int location: @location_default ref +); + +/*- Source location prefix -*/ + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/*- Diagnostic messages -*/ + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/*- Diagnostic messages: severity -*/ + +case @diagnostic.severity of + 10 = @diagnostic_debug +| 20 = @diagnostic_info +| 30 = @diagnostic_warning +| 40 = @diagnostic_error +; + +/*- YAML -*/ + +#keyset[parent, idx] +yaml (unique int id: @yaml_node, + int kind: int ref, + int parent: @yaml_node_parent ref, + int idx: int ref, + string tag: string ref, + string tostring: string ref); + +case @yaml_node.kind of + 0 = @yaml_scalar_node +| 1 = @yaml_mapping_node +| 2 = @yaml_sequence_node +| 3 = @yaml_alias_node +; + +@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node; + +@yaml_node_parent = @yaml_collection_node | @file; + +yaml_anchors (unique int node: @yaml_node ref, + string anchor: string ref); + +yaml_aliases (unique int alias: @yaml_alias_node ref, + string target: string ref); + +yaml_scalars (unique int scalar: @yaml_scalar_node ref, + int style: int ref, + string value: string ref); + +yaml_errors (unique int id: @yaml_error, + string message: string ref); + +yaml_locations(unique int locatable: @yaml_locatable ref, + int location: @location_default ref); + +@yaml_locatable = @yaml_node | @yaml_error; + + +// from prefix.dbscheme +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_default ref +); + + +// from schema + +@element = + @extractor_step +| @locatable +| @named_crate +| @unextracted +; + +extractor_steps( + unique int id: @extractor_step, + string action: string ref, + int duration_ms: int ref +); + +#keyset[id] +extractor_step_files( + int id: @extractor_step ref, + int file: @file ref +); + +@locatable = + @ast_node +| @crate +; + +named_crates( + unique int id: @named_crate, + string name: string ref, + int crate: @crate ref +); + +@unextracted = + @missing +| @unimplemented +; + +@ast_node = + @abi +| @addressable +| @arg_list +| @asm_dir_spec +| @asm_operand +| @asm_operand_expr +| @asm_option +| @asm_piece +| @asm_reg_spec +| @assoc_item +| @assoc_item_list +| @attr +| @callable +| @closure_binder +| @expr +| @extern_item +| @extern_item_list +| @field_list +| @format_args_arg +| @generic_arg +| @generic_arg_list +| @generic_param +| @generic_param_list +| @item_list +| @label +| @let_else +| @macro_items +| @macro_stmts +| @match_arm +| @match_arm_list +| @match_guard +| @meta +| @name +| @param_base +| @param_list +| @parenthesized_arg_list +| @pat +| @path +| @path_segment +| @rename +| @resolvable +| @ret_type_repr +| @return_type_syntax +| @source_file +| @stmt +| @stmt_list +| @struct_expr_field +| @struct_expr_field_list +| @struct_field +| @struct_pat_field +| @struct_pat_field_list +| @token +| @token_tree +| @tuple_field +| @type_bound +| @type_bound_list +| @type_repr +| @use_bound_generic_arg +| @use_bound_generic_args +| @use_tree +| @use_tree_list +| @variant_def +| @variant_list +| @visibility +| @where_clause +| @where_pred +; + +crates( + unique int id: @crate +); + +#keyset[id] +crate_names( + int id: @crate ref, + string name: string ref +); + +#keyset[id] +crate_versions( + int id: @crate ref, + string version: string ref +); + +#keyset[id] +crate_modules( + int id: @crate ref, + int module: @module ref +); + +#keyset[id, index] +crate_cfg_options( + int id: @crate ref, + int index: int ref, + string cfg_option: string ref +); + +#keyset[id, index] +crate_named_dependencies( + int id: @crate ref, + int index: int ref, + int named_dependency: @named_crate ref +); + +missings( + unique int id: @missing +); + +unimplementeds( + unique int id: @unimplemented +); + +abis( + unique int id: @abi +); + +#keyset[id] +abi_abi_strings( + int id: @abi ref, + string abi_string: string ref +); + +@addressable = + @item +| @variant +; + +#keyset[id] +addressable_extended_canonical_paths( + int id: @addressable ref, + string extended_canonical_path: string ref +); + +#keyset[id] +addressable_crate_origins( + int id: @addressable ref, + string crate_origin: string ref +); + +arg_lists( + unique int id: @arg_list +); + +#keyset[id, index] +arg_list_args( + int id: @arg_list ref, + int index: int ref, + int arg: @expr ref +); + +asm_dir_specs( + unique int id: @asm_dir_spec +); + +@asm_operand = + @asm_const +| @asm_label +| @asm_reg_operand +| @asm_sym +; + +asm_operand_exprs( + unique int id: @asm_operand_expr +); + +#keyset[id] +asm_operand_expr_in_exprs( + int id: @asm_operand_expr ref, + int in_expr: @expr ref +); + +#keyset[id] +asm_operand_expr_out_exprs( + int id: @asm_operand_expr ref, + int out_expr: @expr ref +); + +asm_options( + unique int id: @asm_option +); + +#keyset[id] +asm_option_is_raw( + int id: @asm_option ref +); + +@asm_piece = + @asm_clobber_abi +| @asm_operand_named +| @asm_options_list +; + +asm_reg_specs( + unique int id: @asm_reg_spec +); + +#keyset[id] +asm_reg_spec_identifiers( + int id: @asm_reg_spec ref, + int identifier: @name_ref ref +); + +@assoc_item = + @const +| @function +| @macro_call +| @type_alias +; + +assoc_item_lists( + unique int id: @assoc_item_list +); + +#keyset[id, index] +assoc_item_list_assoc_items( + int id: @assoc_item_list ref, + int index: int ref, + int assoc_item: @assoc_item ref +); + +#keyset[id, index] +assoc_item_list_attrs( + int id: @assoc_item_list ref, + int index: int ref, + int attr: @attr ref +); + +attrs( + unique int id: @attr +); + +#keyset[id] +attr_meta( + int id: @attr ref, + int meta: @meta ref +); + +@callable = + @closure_expr +| @function +; + +#keyset[id] +callable_param_lists( + int id: @callable ref, + int param_list: @param_list ref +); + +#keyset[id, index] +callable_attrs( + int id: @callable ref, + int index: int ref, + int attr: @attr ref +); + +closure_binders( + unique int id: @closure_binder +); + +#keyset[id] +closure_binder_generic_param_lists( + int id: @closure_binder ref, + int generic_param_list: @generic_param_list ref +); + +@expr = + @array_expr_internal +| @asm_expr +| @await_expr +| @become_expr +| @binary_expr +| @break_expr +| @call_expr_base +| @cast_expr +| @closure_expr +| @continue_expr +| @field_expr +| @format_args_expr +| @if_expr +| @index_expr +| @labelable_expr +| @let_expr +| @literal_expr +| @macro_expr +| @match_expr +| @offset_of_expr +| @paren_expr +| @path_expr_base +| @prefix_expr +| @range_expr +| @ref_expr +| @return_expr +| @struct_expr +| @try_expr +| @tuple_expr +| @underscore_expr +| @yeet_expr +| @yield_expr +; + +@extern_item = + @function +| @macro_call +| @static +| @type_alias +; + +extern_item_lists( + unique int id: @extern_item_list +); + +#keyset[id, index] +extern_item_list_attrs( + int id: @extern_item_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +extern_item_list_extern_items( + int id: @extern_item_list ref, + int index: int ref, + int extern_item: @extern_item ref +); + +@field_list = + @struct_field_list +| @tuple_field_list +; + +format_args_args( + unique int id: @format_args_arg +); + +#keyset[id] +format_args_arg_exprs( + int id: @format_args_arg ref, + int expr: @expr ref +); + +#keyset[id] +format_args_arg_names( + int id: @format_args_arg ref, + int name: @name ref +); + +@generic_arg = + @assoc_type_arg +| @const_arg +| @lifetime_arg +| @type_arg +; + +generic_arg_lists( + unique int id: @generic_arg_list +); + +#keyset[id, index] +generic_arg_list_generic_args( + int id: @generic_arg_list ref, + int index: int ref, + int generic_arg: @generic_arg ref +); + +@generic_param = + @const_param +| @lifetime_param +| @type_param +; + +generic_param_lists( + unique int id: @generic_param_list +); + +#keyset[id, index] +generic_param_list_generic_params( + int id: @generic_param_list ref, + int index: int ref, + int generic_param: @generic_param ref +); + +item_lists( + unique int id: @item_list +); + +#keyset[id, index] +item_list_attrs( + int id: @item_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +item_list_items( + int id: @item_list ref, + int index: int ref, + int item: @item ref +); + +labels( + unique int id: @label +); + +#keyset[id] +label_lifetimes( + int id: @label ref, + int lifetime: @lifetime ref +); + +let_elses( + unique int id: @let_else +); + +#keyset[id] +let_else_block_exprs( + int id: @let_else ref, + int block_expr: @block_expr ref +); + +macro_items( + unique int id: @macro_items +); + +#keyset[id, index] +macro_items_items( + int id: @macro_items ref, + int index: int ref, + int item: @item ref +); + +macro_stmts( + unique int id: @macro_stmts +); + +#keyset[id] +macro_stmts_exprs( + int id: @macro_stmts ref, + int expr: @expr ref +); + +#keyset[id, index] +macro_stmts_statements( + int id: @macro_stmts ref, + int index: int ref, + int statement: @stmt ref +); + +match_arms( + unique int id: @match_arm +); + +#keyset[id, index] +match_arm_attrs( + int id: @match_arm ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +match_arm_exprs( + int id: @match_arm ref, + int expr: @expr ref +); + +#keyset[id] +match_arm_guards( + int id: @match_arm ref, + int guard: @match_guard ref +); + +#keyset[id] +match_arm_pats( + int id: @match_arm ref, + int pat: @pat ref +); + +match_arm_lists( + unique int id: @match_arm_list +); + +#keyset[id, index] +match_arm_list_arms( + int id: @match_arm_list ref, + int index: int ref, + int arm: @match_arm ref +); + +#keyset[id, index] +match_arm_list_attrs( + int id: @match_arm_list ref, + int index: int ref, + int attr: @attr ref +); + +match_guards( + unique int id: @match_guard +); + +#keyset[id] +match_guard_conditions( + int id: @match_guard ref, + int condition: @expr ref +); + +meta( + unique int id: @meta +); + +#keyset[id] +meta_exprs( + int id: @meta ref, + int expr: @expr ref +); + +#keyset[id] +meta_is_unsafe( + int id: @meta ref +); + +#keyset[id] +meta_paths( + int id: @meta ref, + int path: @path ref +); + +#keyset[id] +meta_token_trees( + int id: @meta ref, + int token_tree: @token_tree ref +); + +names( + unique int id: @name +); + +#keyset[id] +name_texts( + int id: @name ref, + string text: string ref +); + +@param_base = + @param +| @self_param +; + +#keyset[id, index] +param_base_attrs( + int id: @param_base ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +param_base_type_reprs( + int id: @param_base ref, + int type_repr: @type_repr ref +); + +param_lists( + unique int id: @param_list +); + +#keyset[id, index] +param_list_params( + int id: @param_list ref, + int index: int ref, + int param: @param ref +); + +#keyset[id] +param_list_self_params( + int id: @param_list ref, + int self_param: @self_param ref +); + +parenthesized_arg_lists( + unique int id: @parenthesized_arg_list +); + +#keyset[id, index] +parenthesized_arg_list_type_args( + int id: @parenthesized_arg_list ref, + int index: int ref, + int type_arg: @type_arg ref +); + +@pat = + @box_pat +| @const_block_pat +| @ident_pat +| @literal_pat +| @macro_pat +| @or_pat +| @paren_pat +| @path_pat +| @range_pat +| @ref_pat +| @rest_pat +| @slice_pat +| @struct_pat +| @tuple_pat +| @tuple_struct_pat +| @wildcard_pat +; + +paths( + unique int id: @path +); + +#keyset[id] +path_qualifiers( + int id: @path ref, + int qualifier: @path ref +); + +#keyset[id] +path_segments_( + int id: @path ref, + int segment: @path_segment ref +); + +path_segments( + unique int id: @path_segment +); + +#keyset[id] +path_segment_generic_arg_lists( + int id: @path_segment ref, + int generic_arg_list: @generic_arg_list ref +); + +#keyset[id] +path_segment_identifiers( + int id: @path_segment ref, + int identifier: @name_ref ref +); + +#keyset[id] +path_segment_parenthesized_arg_lists( + int id: @path_segment ref, + int parenthesized_arg_list: @parenthesized_arg_list ref +); + +#keyset[id] +path_segment_ret_types( + int id: @path_segment ref, + int ret_type: @ret_type_repr ref +); + +#keyset[id] +path_segment_return_type_syntaxes( + int id: @path_segment ref, + int return_type_syntax: @return_type_syntax ref +); + +#keyset[id] +path_segment_type_reprs( + int id: @path_segment ref, + int type_repr: @type_repr ref +); + +#keyset[id] +path_segment_trait_type_reprs( + int id: @path_segment ref, + int trait_type_repr: @path_type_repr ref +); + +renames( + unique int id: @rename +); + +#keyset[id] +rename_names( + int id: @rename ref, + int name: @name ref +); + +@resolvable = + @method_call_expr +| @path_ast_node +; + +#keyset[id] +resolvable_resolved_paths( + int id: @resolvable ref, + string resolved_path: string ref +); + +#keyset[id] +resolvable_resolved_crate_origins( + int id: @resolvable ref, + string resolved_crate_origin: string ref +); + +ret_type_reprs( + unique int id: @ret_type_repr +); + +#keyset[id] +ret_type_repr_type_reprs( + int id: @ret_type_repr ref, + int type_repr: @type_repr ref +); + +return_type_syntaxes( + unique int id: @return_type_syntax +); + +source_files( + unique int id: @source_file +); + +#keyset[id, index] +source_file_attrs( + int id: @source_file ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +source_file_items( + int id: @source_file ref, + int index: int ref, + int item: @item ref +); + +@stmt = + @expr_stmt +| @item +| @let_stmt +; + +stmt_lists( + unique int id: @stmt_list +); + +#keyset[id, index] +stmt_list_attrs( + int id: @stmt_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +stmt_list_statements( + int id: @stmt_list ref, + int index: int ref, + int statement: @stmt ref +); + +#keyset[id] +stmt_list_tail_exprs( + int id: @stmt_list ref, + int tail_expr: @expr ref +); + +struct_expr_fields( + unique int id: @struct_expr_field +); + +#keyset[id, index] +struct_expr_field_attrs( + int id: @struct_expr_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_expr_field_exprs( + int id: @struct_expr_field ref, + int expr: @expr ref +); + +#keyset[id] +struct_expr_field_identifiers( + int id: @struct_expr_field ref, + int identifier: @name_ref ref +); + +struct_expr_field_lists( + unique int id: @struct_expr_field_list +); + +#keyset[id, index] +struct_expr_field_list_attrs( + int id: @struct_expr_field_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +struct_expr_field_list_fields( + int id: @struct_expr_field_list ref, + int index: int ref, + int field: @struct_expr_field ref +); + +#keyset[id] +struct_expr_field_list_spreads( + int id: @struct_expr_field_list ref, + int spread: @expr ref +); + +struct_fields( + unique int id: @struct_field +); + +#keyset[id, index] +struct_field_attrs( + int id: @struct_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_field_defaults( + int id: @struct_field ref, + int default: @expr ref +); + +#keyset[id] +struct_field_is_unsafe( + int id: @struct_field ref +); + +#keyset[id] +struct_field_names( + int id: @struct_field ref, + int name: @name ref +); + +#keyset[id] +struct_field_type_reprs( + int id: @struct_field ref, + int type_repr: @type_repr ref +); + +#keyset[id] +struct_field_visibilities( + int id: @struct_field ref, + int visibility: @visibility ref +); + +struct_pat_fields( + unique int id: @struct_pat_field +); + +#keyset[id, index] +struct_pat_field_attrs( + int id: @struct_pat_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_pat_field_identifiers( + int id: @struct_pat_field ref, + int identifier: @name_ref ref +); + +#keyset[id] +struct_pat_field_pats( + int id: @struct_pat_field ref, + int pat: @pat ref +); + +struct_pat_field_lists( + unique int id: @struct_pat_field_list +); + +#keyset[id, index] +struct_pat_field_list_fields( + int id: @struct_pat_field_list ref, + int index: int ref, + int field: @struct_pat_field ref +); + +#keyset[id] +struct_pat_field_list_rest_pats( + int id: @struct_pat_field_list ref, + int rest_pat: @rest_pat ref +); + +@token = + @comment +; + +token_trees( + unique int id: @token_tree +); + +tuple_fields( + unique int id: @tuple_field +); + +#keyset[id, index] +tuple_field_attrs( + int id: @tuple_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +tuple_field_type_reprs( + int id: @tuple_field ref, + int type_repr: @type_repr ref +); + +#keyset[id] +tuple_field_visibilities( + int id: @tuple_field ref, + int visibility: @visibility ref +); + +type_bounds( + unique int id: @type_bound +); + +#keyset[id] +type_bound_is_async( + int id: @type_bound ref +); + +#keyset[id] +type_bound_is_const( + int id: @type_bound ref +); + +#keyset[id] +type_bound_lifetimes( + int id: @type_bound ref, + int lifetime: @lifetime ref +); + +#keyset[id] +type_bound_type_reprs( + int id: @type_bound ref, + int type_repr: @type_repr ref +); + +#keyset[id] +type_bound_use_bound_generic_args( + int id: @type_bound ref, + int use_bound_generic_args: @use_bound_generic_args ref +); + +type_bound_lists( + unique int id: @type_bound_list +); + +#keyset[id, index] +type_bound_list_bounds( + int id: @type_bound_list ref, + int index: int ref, + int bound: @type_bound ref +); + +@type_repr = + @array_type_repr +| @dyn_trait_type_repr +| @fn_ptr_type_repr +| @for_type_repr +| @impl_trait_type_repr +| @infer_type_repr +| @macro_type_repr +| @never_type_repr +| @paren_type_repr +| @path_type_repr +| @ptr_type_repr +| @ref_type_repr +| @slice_type_repr +| @tuple_type_repr +; + +@use_bound_generic_arg = + @lifetime +| @name_ref +; + +use_bound_generic_args( + unique int id: @use_bound_generic_args +); + +#keyset[id, index] +use_bound_generic_args_use_bound_generic_args( + int id: @use_bound_generic_args ref, + int index: int ref, + int use_bound_generic_arg: @use_bound_generic_arg ref +); + +use_trees( + unique int id: @use_tree +); + +#keyset[id] +use_tree_is_glob( + int id: @use_tree ref +); + +#keyset[id] +use_tree_paths( + int id: @use_tree ref, + int path: @path ref +); + +#keyset[id] +use_tree_renames( + int id: @use_tree ref, + int rename: @rename ref +); + +#keyset[id] +use_tree_use_tree_lists( + int id: @use_tree ref, + int use_tree_list: @use_tree_list ref +); + +use_tree_lists( + unique int id: @use_tree_list +); + +#keyset[id, index] +use_tree_list_use_trees( + int id: @use_tree_list ref, + int index: int ref, + int use_tree: @use_tree ref +); + +@variant_def = + @struct +| @union +| @variant +; + +variant_lists( + unique int id: @variant_list +); + +#keyset[id, index] +variant_list_variants( + int id: @variant_list ref, + int index: int ref, + int variant: @variant ref +); + +visibilities( + unique int id: @visibility +); + +#keyset[id] +visibility_paths( + int id: @visibility ref, + int path: @path ref +); + +where_clauses( + unique int id: @where_clause +); + +#keyset[id, index] +where_clause_predicates( + int id: @where_clause ref, + int index: int ref, + int predicate: @where_pred ref +); + +where_preds( + unique int id: @where_pred +); + +#keyset[id] +where_pred_generic_param_lists( + int id: @where_pred ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +where_pred_lifetimes( + int id: @where_pred ref, + int lifetime: @lifetime ref +); + +#keyset[id] +where_pred_type_reprs( + int id: @where_pred ref, + int type_repr: @type_repr ref +); + +#keyset[id] +where_pred_type_bound_lists( + int id: @where_pred ref, + int type_bound_list: @type_bound_list ref +); + +array_expr_internals( + unique int id: @array_expr_internal +); + +#keyset[id, index] +array_expr_internal_attrs( + int id: @array_expr_internal ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +array_expr_internal_exprs( + int id: @array_expr_internal ref, + int index: int ref, + int expr: @expr ref +); + +#keyset[id] +array_expr_internal_is_semicolon( + int id: @array_expr_internal ref +); + +array_type_reprs( + unique int id: @array_type_repr +); + +#keyset[id] +array_type_repr_const_args( + int id: @array_type_repr ref, + int const_arg: @const_arg ref +); + +#keyset[id] +array_type_repr_element_type_reprs( + int id: @array_type_repr ref, + int element_type_repr: @type_repr ref +); + +asm_clobber_abis( + unique int id: @asm_clobber_abi +); + +asm_consts( + unique int id: @asm_const +); + +#keyset[id] +asm_const_exprs( + int id: @asm_const ref, + int expr: @expr ref +); + +#keyset[id] +asm_const_is_const( + int id: @asm_const ref +); + +asm_exprs( + unique int id: @asm_expr +); + +#keyset[id, index] +asm_expr_asm_pieces( + int id: @asm_expr ref, + int index: int ref, + int asm_piece: @asm_piece ref +); + +#keyset[id, index] +asm_expr_attrs( + int id: @asm_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +asm_expr_templates( + int id: @asm_expr ref, + int index: int ref, + int template: @expr ref +); + +asm_labels( + unique int id: @asm_label +); + +#keyset[id] +asm_label_block_exprs( + int id: @asm_label ref, + int block_expr: @block_expr ref +); + +asm_operand_nameds( + unique int id: @asm_operand_named +); + +#keyset[id] +asm_operand_named_asm_operands( + int id: @asm_operand_named ref, + int asm_operand: @asm_operand ref +); + +#keyset[id] +asm_operand_named_names( + int id: @asm_operand_named ref, + int name: @name ref +); + +asm_options_lists( + unique int id: @asm_options_list +); + +#keyset[id, index] +asm_options_list_asm_options( + int id: @asm_options_list ref, + int index: int ref, + int asm_option: @asm_option ref +); + +asm_reg_operands( + unique int id: @asm_reg_operand +); + +#keyset[id] +asm_reg_operand_asm_dir_specs( + int id: @asm_reg_operand ref, + int asm_dir_spec: @asm_dir_spec ref +); + +#keyset[id] +asm_reg_operand_asm_operand_exprs( + int id: @asm_reg_operand ref, + int asm_operand_expr: @asm_operand_expr ref +); + +#keyset[id] +asm_reg_operand_asm_reg_specs( + int id: @asm_reg_operand ref, + int asm_reg_spec: @asm_reg_spec ref +); + +asm_syms( + unique int id: @asm_sym +); + +#keyset[id] +asm_sym_paths( + int id: @asm_sym ref, + int path: @path ref +); + +assoc_type_args( + unique int id: @assoc_type_arg +); + +#keyset[id] +assoc_type_arg_const_args( + int id: @assoc_type_arg ref, + int const_arg: @const_arg ref +); + +#keyset[id] +assoc_type_arg_generic_arg_lists( + int id: @assoc_type_arg ref, + int generic_arg_list: @generic_arg_list ref +); + +#keyset[id] +assoc_type_arg_identifiers( + int id: @assoc_type_arg ref, + int identifier: @name_ref ref +); + +#keyset[id] +assoc_type_arg_param_lists( + int id: @assoc_type_arg ref, + int param_list: @param_list ref +); + +#keyset[id] +assoc_type_arg_ret_types( + int id: @assoc_type_arg ref, + int ret_type: @ret_type_repr ref +); + +#keyset[id] +assoc_type_arg_return_type_syntaxes( + int id: @assoc_type_arg ref, + int return_type_syntax: @return_type_syntax ref +); + +#keyset[id] +assoc_type_arg_type_reprs( + int id: @assoc_type_arg ref, + int type_repr: @type_repr ref +); + +#keyset[id] +assoc_type_arg_type_bound_lists( + int id: @assoc_type_arg ref, + int type_bound_list: @type_bound_list ref +); + +await_exprs( + unique int id: @await_expr +); + +#keyset[id, index] +await_expr_attrs( + int id: @await_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +await_expr_exprs( + int id: @await_expr ref, + int expr: @expr ref +); + +become_exprs( + unique int id: @become_expr +); + +#keyset[id, index] +become_expr_attrs( + int id: @become_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +become_expr_exprs( + int id: @become_expr ref, + int expr: @expr ref +); + +binary_exprs( + unique int id: @binary_expr +); + +#keyset[id, index] +binary_expr_attrs( + int id: @binary_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +binary_expr_lhs( + int id: @binary_expr ref, + int lhs: @expr ref +); + +#keyset[id] +binary_expr_operator_names( + int id: @binary_expr ref, + string operator_name: string ref +); + +#keyset[id] +binary_expr_rhs( + int id: @binary_expr ref, + int rhs: @expr ref +); + +box_pats( + unique int id: @box_pat +); + +#keyset[id] +box_pat_pats( + int id: @box_pat ref, + int pat: @pat ref +); + +break_exprs( + unique int id: @break_expr +); + +#keyset[id, index] +break_expr_attrs( + int id: @break_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +break_expr_exprs( + int id: @break_expr ref, + int expr: @expr ref +); + +#keyset[id] +break_expr_lifetimes( + int id: @break_expr ref, + int lifetime: @lifetime ref +); + +@call_expr_base = + @call_expr +| @method_call_expr +; + +#keyset[id] +call_expr_base_arg_lists( + int id: @call_expr_base ref, + int arg_list: @arg_list ref +); + +#keyset[id, index] +call_expr_base_attrs( + int id: @call_expr_base ref, + int index: int ref, + int attr: @attr ref +); + +cast_exprs( + unique int id: @cast_expr +); + +#keyset[id, index] +cast_expr_attrs( + int id: @cast_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +cast_expr_exprs( + int id: @cast_expr ref, + int expr: @expr ref +); + +#keyset[id] +cast_expr_type_reprs( + int id: @cast_expr ref, + int type_repr: @type_repr ref +); + +closure_exprs( + unique int id: @closure_expr +); + +#keyset[id] +closure_expr_bodies( + int id: @closure_expr ref, + int body: @expr ref +); + +#keyset[id] +closure_expr_closure_binders( + int id: @closure_expr ref, + int closure_binder: @closure_binder ref +); + +#keyset[id] +closure_expr_is_async( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_const( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_gen( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_move( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_static( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_ret_types( + int id: @closure_expr ref, + int ret_type: @ret_type_repr ref +); + +comments( + unique int id: @comment, + int parent: @ast_node ref, + string text: string ref +); + +const_args( + unique int id: @const_arg +); + +#keyset[id] +const_arg_exprs( + int id: @const_arg ref, + int expr: @expr ref +); + +const_block_pats( + unique int id: @const_block_pat +); + +#keyset[id] +const_block_pat_block_exprs( + int id: @const_block_pat ref, + int block_expr: @block_expr ref +); + +#keyset[id] +const_block_pat_is_const( + int id: @const_block_pat ref +); + +const_params( + unique int id: @const_param +); + +#keyset[id, index] +const_param_attrs( + int id: @const_param ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +const_param_default_vals( + int id: @const_param ref, + int default_val: @const_arg ref +); + +#keyset[id] +const_param_is_const( + int id: @const_param ref +); + +#keyset[id] +const_param_names( + int id: @const_param ref, + int name: @name ref +); + +#keyset[id] +const_param_type_reprs( + int id: @const_param ref, + int type_repr: @type_repr ref +); + +continue_exprs( + unique int id: @continue_expr +); + +#keyset[id, index] +continue_expr_attrs( + int id: @continue_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +continue_expr_lifetimes( + int id: @continue_expr ref, + int lifetime: @lifetime ref +); + +dyn_trait_type_reprs( + unique int id: @dyn_trait_type_repr +); + +#keyset[id] +dyn_trait_type_repr_type_bound_lists( + int id: @dyn_trait_type_repr ref, + int type_bound_list: @type_bound_list ref +); + +expr_stmts( + unique int id: @expr_stmt +); + +#keyset[id] +expr_stmt_exprs( + int id: @expr_stmt ref, + int expr: @expr ref +); + +field_exprs( + unique int id: @field_expr +); + +#keyset[id, index] +field_expr_attrs( + int id: @field_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +field_expr_containers( + int id: @field_expr ref, + int container: @expr ref +); + +#keyset[id] +field_expr_identifiers( + int id: @field_expr ref, + int identifier: @name_ref ref +); + +fn_ptr_type_reprs( + unique int id: @fn_ptr_type_repr +); + +#keyset[id] +fn_ptr_type_repr_abis( + int id: @fn_ptr_type_repr ref, + int abi: @abi ref +); + +#keyset[id] +fn_ptr_type_repr_is_async( + int id: @fn_ptr_type_repr ref +); + +#keyset[id] +fn_ptr_type_repr_is_const( + int id: @fn_ptr_type_repr ref +); + +#keyset[id] +fn_ptr_type_repr_is_unsafe( + int id: @fn_ptr_type_repr ref +); + +#keyset[id] +fn_ptr_type_repr_param_lists( + int id: @fn_ptr_type_repr ref, + int param_list: @param_list ref +); + +#keyset[id] +fn_ptr_type_repr_ret_types( + int id: @fn_ptr_type_repr ref, + int ret_type: @ret_type_repr ref +); + +for_type_reprs( + unique int id: @for_type_repr +); + +#keyset[id] +for_type_repr_generic_param_lists( + int id: @for_type_repr ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +for_type_repr_type_reprs( + int id: @for_type_repr ref, + int type_repr: @type_repr ref +); + +format_args_exprs( + unique int id: @format_args_expr +); + +#keyset[id, index] +format_args_expr_args( + int id: @format_args_expr ref, + int index: int ref, + int arg: @format_args_arg ref +); + +#keyset[id, index] +format_args_expr_attrs( + int id: @format_args_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +format_args_expr_templates( + int id: @format_args_expr ref, + int template: @expr ref +); + +ident_pats( + unique int id: @ident_pat +); + +#keyset[id, index] +ident_pat_attrs( + int id: @ident_pat ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +ident_pat_is_mut( + int id: @ident_pat ref +); + +#keyset[id] +ident_pat_is_ref( + int id: @ident_pat ref +); + +#keyset[id] +ident_pat_names( + int id: @ident_pat ref, + int name: @name ref +); + +#keyset[id] +ident_pat_pats( + int id: @ident_pat ref, + int pat: @pat ref +); + +if_exprs( + unique int id: @if_expr +); + +#keyset[id, index] +if_expr_attrs( + int id: @if_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +if_expr_conditions( + int id: @if_expr ref, + int condition: @expr ref +); + +#keyset[id] +if_expr_elses( + int id: @if_expr ref, + int else: @expr ref +); + +#keyset[id] +if_expr_thens( + int id: @if_expr ref, + int then: @block_expr ref +); + +impl_trait_type_reprs( + unique int id: @impl_trait_type_repr +); + +#keyset[id] +impl_trait_type_repr_type_bound_lists( + int id: @impl_trait_type_repr ref, + int type_bound_list: @type_bound_list ref +); + +index_exprs( + unique int id: @index_expr +); + +#keyset[id, index] +index_expr_attrs( + int id: @index_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +index_expr_bases( + int id: @index_expr ref, + int base: @expr ref +); + +#keyset[id] +index_expr_indices( + int id: @index_expr ref, + int index: @expr ref +); + +infer_type_reprs( + unique int id: @infer_type_repr +); + +@item = + @const +| @enum +| @extern_block +| @extern_crate +| @function +| @impl +| @macro_call +| @macro_def +| @macro_rules +| @module +| @static +| @struct +| @trait +| @trait_alias +| @type_alias +| @union +| @use +; + +@labelable_expr = + @block_expr +| @looping_expr +; + +#keyset[id] +labelable_expr_labels( + int id: @labelable_expr ref, + int label: @label ref +); + +let_exprs( + unique int id: @let_expr +); + +#keyset[id, index] +let_expr_attrs( + int id: @let_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +let_expr_scrutinees( + int id: @let_expr ref, + int scrutinee: @expr ref +); + +#keyset[id] +let_expr_pats( + int id: @let_expr ref, + int pat: @pat ref +); + +let_stmts( + unique int id: @let_stmt +); + +#keyset[id, index] +let_stmt_attrs( + int id: @let_stmt ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +let_stmt_initializers( + int id: @let_stmt ref, + int initializer: @expr ref +); + +#keyset[id] +let_stmt_let_elses( + int id: @let_stmt ref, + int let_else: @let_else ref +); + +#keyset[id] +let_stmt_pats( + int id: @let_stmt ref, + int pat: @pat ref +); + +#keyset[id] +let_stmt_type_reprs( + int id: @let_stmt ref, + int type_repr: @type_repr ref +); + +lifetimes( + unique int id: @lifetime +); + +#keyset[id] +lifetime_texts( + int id: @lifetime ref, + string text: string ref +); + +lifetime_args( + unique int id: @lifetime_arg +); + +#keyset[id] +lifetime_arg_lifetimes( + int id: @lifetime_arg ref, + int lifetime: @lifetime ref +); + +lifetime_params( + unique int id: @lifetime_param +); + +#keyset[id, index] +lifetime_param_attrs( + int id: @lifetime_param ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +lifetime_param_lifetimes( + int id: @lifetime_param ref, + int lifetime: @lifetime ref +); + +#keyset[id] +lifetime_param_type_bound_lists( + int id: @lifetime_param ref, + int type_bound_list: @type_bound_list ref +); + +literal_exprs( + unique int id: @literal_expr +); + +#keyset[id, index] +literal_expr_attrs( + int id: @literal_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +literal_expr_text_values( + int id: @literal_expr ref, + string text_value: string ref +); + +literal_pats( + unique int id: @literal_pat +); + +#keyset[id] +literal_pat_literals( + int id: @literal_pat ref, + int literal: @literal_expr ref +); + +macro_exprs( + unique int id: @macro_expr +); + +#keyset[id] +macro_expr_macro_calls( + int id: @macro_expr ref, + int macro_call: @macro_call ref +); + +macro_pats( + unique int id: @macro_pat +); + +#keyset[id] +macro_pat_macro_calls( + int id: @macro_pat ref, + int macro_call: @macro_call ref +); + +macro_type_reprs( + unique int id: @macro_type_repr +); + +#keyset[id] +macro_type_repr_macro_calls( + int id: @macro_type_repr ref, + int macro_call: @macro_call ref +); + +match_exprs( + unique int id: @match_expr +); + +#keyset[id, index] +match_expr_attrs( + int id: @match_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +match_expr_scrutinees( + int id: @match_expr ref, + int scrutinee: @expr ref +); + +#keyset[id] +match_expr_match_arm_lists( + int id: @match_expr ref, + int match_arm_list: @match_arm_list ref +); + +name_refs( + unique int id: @name_ref +); + +#keyset[id] +name_ref_texts( + int id: @name_ref ref, + string text: string ref +); + +never_type_reprs( + unique int id: @never_type_repr +); + +offset_of_exprs( + unique int id: @offset_of_expr +); + +#keyset[id, index] +offset_of_expr_attrs( + int id: @offset_of_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +offset_of_expr_fields( + int id: @offset_of_expr ref, + int index: int ref, + int field: @name_ref ref +); + +#keyset[id] +offset_of_expr_type_reprs( + int id: @offset_of_expr ref, + int type_repr: @type_repr ref +); + +or_pats( + unique int id: @or_pat +); + +#keyset[id, index] +or_pat_pats( + int id: @or_pat ref, + int index: int ref, + int pat: @pat ref +); + +params( + unique int id: @param +); + +#keyset[id] +param_pats( + int id: @param ref, + int pat: @pat ref +); + +paren_exprs( + unique int id: @paren_expr +); + +#keyset[id, index] +paren_expr_attrs( + int id: @paren_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +paren_expr_exprs( + int id: @paren_expr ref, + int expr: @expr ref +); + +paren_pats( + unique int id: @paren_pat +); + +#keyset[id] +paren_pat_pats( + int id: @paren_pat ref, + int pat: @pat ref +); + +paren_type_reprs( + unique int id: @paren_type_repr +); + +#keyset[id] +paren_type_repr_type_reprs( + int id: @paren_type_repr ref, + int type_repr: @type_repr ref +); + +@path_ast_node = + @path_expr +| @path_pat +| @struct_expr +| @struct_pat +| @tuple_struct_pat +; + +#keyset[id] +path_ast_node_paths( + int id: @path_ast_node ref, + int path: @path ref +); + +@path_expr_base = + @path_expr +; + +path_type_reprs( + unique int id: @path_type_repr +); + +#keyset[id] +path_type_repr_paths( + int id: @path_type_repr ref, + int path: @path ref +); + +prefix_exprs( + unique int id: @prefix_expr +); + +#keyset[id, index] +prefix_expr_attrs( + int id: @prefix_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +prefix_expr_exprs( + int id: @prefix_expr ref, + int expr: @expr ref +); + +#keyset[id] +prefix_expr_operator_names( + int id: @prefix_expr ref, + string operator_name: string ref +); + +ptr_type_reprs( + unique int id: @ptr_type_repr +); + +#keyset[id] +ptr_type_repr_is_const( + int id: @ptr_type_repr ref +); + +#keyset[id] +ptr_type_repr_is_mut( + int id: @ptr_type_repr ref +); + +#keyset[id] +ptr_type_repr_type_reprs( + int id: @ptr_type_repr ref, + int type_repr: @type_repr ref +); + +range_exprs( + unique int id: @range_expr +); + +#keyset[id, index] +range_expr_attrs( + int id: @range_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +range_expr_ends( + int id: @range_expr ref, + int end: @expr ref +); + +#keyset[id] +range_expr_operator_names( + int id: @range_expr ref, + string operator_name: string ref +); + +#keyset[id] +range_expr_starts( + int id: @range_expr ref, + int start: @expr ref +); + +range_pats( + unique int id: @range_pat +); + +#keyset[id] +range_pat_ends( + int id: @range_pat ref, + int end: @pat ref +); + +#keyset[id] +range_pat_operator_names( + int id: @range_pat ref, + string operator_name: string ref +); + +#keyset[id] +range_pat_starts( + int id: @range_pat ref, + int start: @pat ref +); + +ref_exprs( + unique int id: @ref_expr +); + +#keyset[id, index] +ref_expr_attrs( + int id: @ref_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +ref_expr_exprs( + int id: @ref_expr ref, + int expr: @expr ref +); + +#keyset[id] +ref_expr_is_const( + int id: @ref_expr ref +); + +#keyset[id] +ref_expr_is_mut( + int id: @ref_expr ref +); + +#keyset[id] +ref_expr_is_raw( + int id: @ref_expr ref +); + +ref_pats( + unique int id: @ref_pat +); + +#keyset[id] +ref_pat_is_mut( + int id: @ref_pat ref +); + +#keyset[id] +ref_pat_pats( + int id: @ref_pat ref, + int pat: @pat ref +); + +ref_type_reprs( + unique int id: @ref_type_repr +); + +#keyset[id] +ref_type_repr_is_mut( + int id: @ref_type_repr ref +); + +#keyset[id] +ref_type_repr_lifetimes( + int id: @ref_type_repr ref, + int lifetime: @lifetime ref +); + +#keyset[id] +ref_type_repr_type_reprs( + int id: @ref_type_repr ref, + int type_repr: @type_repr ref +); + +rest_pats( + unique int id: @rest_pat +); + +#keyset[id, index] +rest_pat_attrs( + int id: @rest_pat ref, + int index: int ref, + int attr: @attr ref +); + +return_exprs( + unique int id: @return_expr +); + +#keyset[id, index] +return_expr_attrs( + int id: @return_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +return_expr_exprs( + int id: @return_expr ref, + int expr: @expr ref +); + +self_params( + unique int id: @self_param +); + +#keyset[id] +self_param_is_ref( + int id: @self_param ref +); + +#keyset[id] +self_param_is_mut( + int id: @self_param ref +); + +#keyset[id] +self_param_lifetimes( + int id: @self_param ref, + int lifetime: @lifetime ref +); + +#keyset[id] +self_param_names( + int id: @self_param ref, + int name: @name ref +); + +slice_pats( + unique int id: @slice_pat +); + +#keyset[id, index] +slice_pat_pats( + int id: @slice_pat ref, + int index: int ref, + int pat: @pat ref +); + +slice_type_reprs( + unique int id: @slice_type_repr +); + +#keyset[id] +slice_type_repr_type_reprs( + int id: @slice_type_repr ref, + int type_repr: @type_repr ref +); + +struct_field_lists( + unique int id: @struct_field_list +); + +#keyset[id, index] +struct_field_list_fields( + int id: @struct_field_list ref, + int index: int ref, + int field: @struct_field ref +); + +try_exprs( + unique int id: @try_expr +); + +#keyset[id, index] +try_expr_attrs( + int id: @try_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +try_expr_exprs( + int id: @try_expr ref, + int expr: @expr ref +); + +tuple_exprs( + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_attrs( + int id: @tuple_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +tuple_expr_fields( + int id: @tuple_expr ref, + int index: int ref, + int field: @expr ref +); + +tuple_field_lists( + unique int id: @tuple_field_list +); + +#keyset[id, index] +tuple_field_list_fields( + int id: @tuple_field_list ref, + int index: int ref, + int field: @tuple_field ref +); + +tuple_pats( + unique int id: @tuple_pat +); + +#keyset[id, index] +tuple_pat_fields( + int id: @tuple_pat ref, + int index: int ref, + int field: @pat ref +); + +tuple_type_reprs( + unique int id: @tuple_type_repr +); + +#keyset[id, index] +tuple_type_repr_fields( + int id: @tuple_type_repr ref, + int index: int ref, + int field: @type_repr ref +); + +type_args( + unique int id: @type_arg +); + +#keyset[id] +type_arg_type_reprs( + int id: @type_arg ref, + int type_repr: @type_repr ref +); + +type_params( + unique int id: @type_param +); + +#keyset[id, index] +type_param_attrs( + int id: @type_param ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +type_param_default_types( + int id: @type_param ref, + int default_type: @type_repr ref +); + +#keyset[id] +type_param_names( + int id: @type_param ref, + int name: @name ref +); + +#keyset[id] +type_param_type_bound_lists( + int id: @type_param ref, + int type_bound_list: @type_bound_list ref +); + +underscore_exprs( + unique int id: @underscore_expr +); + +#keyset[id, index] +underscore_expr_attrs( + int id: @underscore_expr ref, + int index: int ref, + int attr: @attr ref +); + +variants( + unique int id: @variant +); + +#keyset[id, index] +variant_attrs( + int id: @variant ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +variant_discriminants( + int id: @variant ref, + int discriminant: @expr ref +); + +#keyset[id] +variant_field_lists( + int id: @variant ref, + int field_list: @field_list ref +); + +#keyset[id] +variant_names( + int id: @variant ref, + int name: @name ref +); + +#keyset[id] +variant_visibilities( + int id: @variant ref, + int visibility: @visibility ref +); + +wildcard_pats( + unique int id: @wildcard_pat +); + +yeet_exprs( + unique int id: @yeet_expr +); + +#keyset[id, index] +yeet_expr_attrs( + int id: @yeet_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +yeet_expr_exprs( + int id: @yeet_expr ref, + int expr: @expr ref +); + +yield_exprs( + unique int id: @yield_expr +); + +#keyset[id, index] +yield_expr_attrs( + int id: @yield_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +yield_expr_exprs( + int id: @yield_expr ref, + int expr: @expr ref +); + +block_exprs( + unique int id: @block_expr +); + +#keyset[id, index] +block_expr_attrs( + int id: @block_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +block_expr_is_async( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_const( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_gen( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_move( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_try( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_unsafe( + int id: @block_expr ref +); + +#keyset[id] +block_expr_stmt_lists( + int id: @block_expr ref, + int stmt_list: @stmt_list ref +); + +call_exprs( + unique int id: @call_expr +); + +#keyset[id] +call_expr_functions( + int id: @call_expr ref, + int function: @expr ref +); + +consts( + unique int id: @const +); + +#keyset[id, index] +const_attrs( + int id: @const ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +const_bodies( + int id: @const ref, + int body: @expr ref +); + +#keyset[id] +const_is_const( + int id: @const ref +); + +#keyset[id] +const_is_default( + int id: @const ref +); + +#keyset[id] +const_names( + int id: @const ref, + int name: @name ref +); + +#keyset[id] +const_type_reprs( + int id: @const ref, + int type_repr: @type_repr ref +); + +#keyset[id] +const_visibilities( + int id: @const ref, + int visibility: @visibility ref +); + +enums( + unique int id: @enum +); + +#keyset[id, index] +enum_attrs( + int id: @enum ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +enum_generic_param_lists( + int id: @enum ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +enum_names( + int id: @enum ref, + int name: @name ref +); + +#keyset[id] +enum_variant_lists( + int id: @enum ref, + int variant_list: @variant_list ref +); + +#keyset[id] +enum_visibilities( + int id: @enum ref, + int visibility: @visibility ref +); + +#keyset[id] +enum_where_clauses( + int id: @enum ref, + int where_clause: @where_clause ref +); + +extern_blocks( + unique int id: @extern_block +); + +#keyset[id] +extern_block_abis( + int id: @extern_block ref, + int abi: @abi ref +); + +#keyset[id, index] +extern_block_attrs( + int id: @extern_block ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +extern_block_extern_item_lists( + int id: @extern_block ref, + int extern_item_list: @extern_item_list ref +); + +#keyset[id] +extern_block_is_unsafe( + int id: @extern_block ref +); + +extern_crates( + unique int id: @extern_crate +); + +#keyset[id, index] +extern_crate_attrs( + int id: @extern_crate ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +extern_crate_identifiers( + int id: @extern_crate ref, + int identifier: @name_ref ref +); + +#keyset[id] +extern_crate_renames( + int id: @extern_crate ref, + int rename: @rename ref +); + +#keyset[id] +extern_crate_visibilities( + int id: @extern_crate ref, + int visibility: @visibility ref +); + +functions( + unique int id: @function +); + +#keyset[id] +function_abis( + int id: @function ref, + int abi: @abi ref +); + +#keyset[id] +function_bodies( + int id: @function ref, + int body: @block_expr ref +); + +#keyset[id] +function_generic_param_lists( + int id: @function ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +function_is_async( + int id: @function ref +); + +#keyset[id] +function_is_const( + int id: @function ref +); + +#keyset[id] +function_is_default( + int id: @function ref +); + +#keyset[id] +function_is_gen( + int id: @function ref +); + +#keyset[id] +function_is_unsafe( + int id: @function ref +); + +#keyset[id] +function_names( + int id: @function ref, + int name: @name ref +); + +#keyset[id] +function_ret_types( + int id: @function ref, + int ret_type: @ret_type_repr ref +); + +#keyset[id] +function_visibilities( + int id: @function ref, + int visibility: @visibility ref +); + +#keyset[id] +function_where_clauses( + int id: @function ref, + int where_clause: @where_clause ref +); + +impls( + unique int id: @impl +); + +#keyset[id] +impl_assoc_item_lists( + int id: @impl ref, + int assoc_item_list: @assoc_item_list ref +); + +#keyset[id, index] +impl_attrs( + int id: @impl ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +impl_generic_param_lists( + int id: @impl ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +impl_is_const( + int id: @impl ref +); + +#keyset[id] +impl_is_default( + int id: @impl ref +); + +#keyset[id] +impl_is_unsafe( + int id: @impl ref +); + +#keyset[id] +impl_self_ties( + int id: @impl ref, + int self_ty: @type_repr ref +); + +#keyset[id] +impl_traits( + int id: @impl ref, + int trait: @type_repr ref +); + +#keyset[id] +impl_visibilities( + int id: @impl ref, + int visibility: @visibility ref +); + +#keyset[id] +impl_where_clauses( + int id: @impl ref, + int where_clause: @where_clause ref +); + +@looping_expr = + @for_expr +| @loop_expr +| @while_expr +; + +#keyset[id] +looping_expr_loop_bodies( + int id: @looping_expr ref, + int loop_body: @block_expr ref +); + +macro_calls( + unique int id: @macro_call +); + +#keyset[id, index] +macro_call_attrs( + int id: @macro_call ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +macro_call_paths( + int id: @macro_call ref, + int path: @path ref +); + +#keyset[id] +macro_call_token_trees( + int id: @macro_call ref, + int token_tree: @token_tree ref +); + +#keyset[id] +macro_call_expandeds( + int id: @macro_call ref, + int expanded: @ast_node ref +); + +macro_defs( + unique int id: @macro_def +); + +#keyset[id] +macro_def_args( + int id: @macro_def ref, + int args: @token_tree ref +); + +#keyset[id, index] +macro_def_attrs( + int id: @macro_def ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +macro_def_bodies( + int id: @macro_def ref, + int body: @token_tree ref +); + +#keyset[id] +macro_def_names( + int id: @macro_def ref, + int name: @name ref +); + +#keyset[id] +macro_def_visibilities( + int id: @macro_def ref, + int visibility: @visibility ref +); + +macro_rules( + unique int id: @macro_rules +); + +#keyset[id, index] +macro_rules_attrs( + int id: @macro_rules ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +macro_rules_names( + int id: @macro_rules ref, + int name: @name ref +); + +#keyset[id] +macro_rules_token_trees( + int id: @macro_rules ref, + int token_tree: @token_tree ref +); + +#keyset[id] +macro_rules_visibilities( + int id: @macro_rules ref, + int visibility: @visibility ref +); + +method_call_exprs( + unique int id: @method_call_expr +); + +#keyset[id] +method_call_expr_generic_arg_lists( + int id: @method_call_expr ref, + int generic_arg_list: @generic_arg_list ref +); + +#keyset[id] +method_call_expr_identifiers( + int id: @method_call_expr ref, + int identifier: @name_ref ref +); + +#keyset[id] +method_call_expr_receivers( + int id: @method_call_expr ref, + int receiver: @expr ref +); + +modules( + unique int id: @module +); + +#keyset[id, index] +module_attrs( + int id: @module ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +module_item_lists( + int id: @module ref, + int item_list: @item_list ref +); + +#keyset[id] +module_names( + int id: @module ref, + int name: @name ref +); + +#keyset[id] +module_visibilities( + int id: @module ref, + int visibility: @visibility ref +); + +path_exprs( + unique int id: @path_expr +); + +#keyset[id, index] +path_expr_attrs( + int id: @path_expr ref, + int index: int ref, + int attr: @attr ref +); + +path_pats( + unique int id: @path_pat +); + +statics( + unique int id: @static +); + +#keyset[id, index] +static_attrs( + int id: @static ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +static_bodies( + int id: @static ref, + int body: @expr ref +); + +#keyset[id] +static_is_mut( + int id: @static ref +); + +#keyset[id] +static_is_static( + int id: @static ref +); + +#keyset[id] +static_is_unsafe( + int id: @static ref +); + +#keyset[id] +static_names( + int id: @static ref, + int name: @name ref +); + +#keyset[id] +static_type_reprs( + int id: @static ref, + int type_repr: @type_repr ref +); + +#keyset[id] +static_visibilities( + int id: @static ref, + int visibility: @visibility ref +); + +structs( + unique int id: @struct +); + +#keyset[id, index] +struct_attrs( + int id: @struct ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_field_lists_( + int id: @struct ref, + int field_list: @field_list ref +); + +#keyset[id] +struct_generic_param_lists( + int id: @struct ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +struct_names( + int id: @struct ref, + int name: @name ref +); + +#keyset[id] +struct_visibilities( + int id: @struct ref, + int visibility: @visibility ref +); + +#keyset[id] +struct_where_clauses( + int id: @struct ref, + int where_clause: @where_clause ref +); + +struct_exprs( + unique int id: @struct_expr +); + +#keyset[id] +struct_expr_struct_expr_field_lists( + int id: @struct_expr ref, + int struct_expr_field_list: @struct_expr_field_list ref +); + +struct_pats( + unique int id: @struct_pat +); + +#keyset[id] +struct_pat_struct_pat_field_lists( + int id: @struct_pat ref, + int struct_pat_field_list: @struct_pat_field_list ref +); + +traits( + unique int id: @trait +); + +#keyset[id] +trait_assoc_item_lists( + int id: @trait ref, + int assoc_item_list: @assoc_item_list ref +); + +#keyset[id, index] +trait_attrs( + int id: @trait ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +trait_generic_param_lists( + int id: @trait ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +trait_is_auto( + int id: @trait ref +); + +#keyset[id] +trait_is_unsafe( + int id: @trait ref +); + +#keyset[id] +trait_names( + int id: @trait ref, + int name: @name ref +); + +#keyset[id] +trait_type_bound_lists( + int id: @trait ref, + int type_bound_list: @type_bound_list ref +); + +#keyset[id] +trait_visibilities( + int id: @trait ref, + int visibility: @visibility ref +); + +#keyset[id] +trait_where_clauses( + int id: @trait ref, + int where_clause: @where_clause ref +); + +trait_aliases( + unique int id: @trait_alias +); + +#keyset[id, index] +trait_alias_attrs( + int id: @trait_alias ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +trait_alias_generic_param_lists( + int id: @trait_alias ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +trait_alias_names( + int id: @trait_alias ref, + int name: @name ref +); + +#keyset[id] +trait_alias_type_bound_lists( + int id: @trait_alias ref, + int type_bound_list: @type_bound_list ref +); + +#keyset[id] +trait_alias_visibilities( + int id: @trait_alias ref, + int visibility: @visibility ref +); + +#keyset[id] +trait_alias_where_clauses( + int id: @trait_alias ref, + int where_clause: @where_clause ref +); + +tuple_struct_pats( + unique int id: @tuple_struct_pat +); + +#keyset[id, index] +tuple_struct_pat_fields( + int id: @tuple_struct_pat ref, + int index: int ref, + int field: @pat ref +); + +type_aliases( + unique int id: @type_alias +); + +#keyset[id, index] +type_alias_attrs( + int id: @type_alias ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +type_alias_generic_param_lists( + int id: @type_alias ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +type_alias_is_default( + int id: @type_alias ref +); + +#keyset[id] +type_alias_names( + int id: @type_alias ref, + int name: @name ref +); + +#keyset[id] +type_alias_type_reprs( + int id: @type_alias ref, + int type_repr: @type_repr ref +); + +#keyset[id] +type_alias_type_bound_lists( + int id: @type_alias ref, + int type_bound_list: @type_bound_list ref +); + +#keyset[id] +type_alias_visibilities( + int id: @type_alias ref, + int visibility: @visibility ref +); + +#keyset[id] +type_alias_where_clauses( + int id: @type_alias ref, + int where_clause: @where_clause ref +); + +unions( + unique int id: @union +); + +#keyset[id, index] +union_attrs( + int id: @union ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +union_generic_param_lists( + int id: @union ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +union_names( + int id: @union ref, + int name: @name ref +); + +#keyset[id] +union_struct_field_lists( + int id: @union ref, + int struct_field_list: @struct_field_list ref +); + +#keyset[id] +union_visibilities( + int id: @union ref, + int visibility: @visibility ref +); + +#keyset[id] +union_where_clauses( + int id: @union ref, + int where_clause: @where_clause ref +); + +uses( + unique int id: @use +); + +#keyset[id, index] +use_attrs( + int id: @use ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +use_use_trees( + int id: @use ref, + int use_tree: @use_tree ref +); + +#keyset[id] +use_visibilities( + int id: @use ref, + int visibility: @visibility ref +); + +for_exprs( + unique int id: @for_expr +); + +#keyset[id, index] +for_expr_attrs( + int id: @for_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +for_expr_iterables( + int id: @for_expr ref, + int iterable: @expr ref +); + +#keyset[id] +for_expr_pats( + int id: @for_expr ref, + int pat: @pat ref +); + +loop_exprs( + unique int id: @loop_expr +); + +#keyset[id, index] +loop_expr_attrs( + int id: @loop_expr ref, + int index: int ref, + int attr: @attr ref +); + +while_exprs( + unique int id: @while_expr +); + +#keyset[id, index] +while_expr_attrs( + int id: @while_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +while_expr_conditions( + int id: @while_expr ref, + int condition: @expr ref +); diff --git a/rust/ql/lib/upgrades/e8707b675dc574aca9863eabcc09ac76f15bb9c2/rust.dbscheme b/rust/ql/lib/upgrades/e8707b675dc574aca9863eabcc09ac76f15bb9c2/rust.dbscheme new file mode 100644 index 000000000000..58bc96172f5a --- /dev/null +++ b/rust/ql/lib/upgrades/e8707b675dc574aca9863eabcc09ac76f15bb9c2/rust.dbscheme @@ -0,0 +1,3606 @@ +// generated by codegen, do not edit + +// from ../shared/tree-sitter-extractor/src/generator/prefix.dbscheme +/*- Files and folders -*/ + +/** + * The location of an element. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @file | @folder + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/*- Empty location -*/ + +empty_location( + int location: @location_default ref +); + +/*- Source location prefix -*/ + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/*- Diagnostic messages -*/ + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/*- Diagnostic messages: severity -*/ + +case @diagnostic.severity of + 10 = @diagnostic_debug +| 20 = @diagnostic_info +| 30 = @diagnostic_warning +| 40 = @diagnostic_error +; + +/*- YAML -*/ + +#keyset[parent, idx] +yaml (unique int id: @yaml_node, + int kind: int ref, + int parent: @yaml_node_parent ref, + int idx: int ref, + string tag: string ref, + string tostring: string ref); + +case @yaml_node.kind of + 0 = @yaml_scalar_node +| 1 = @yaml_mapping_node +| 2 = @yaml_sequence_node +| 3 = @yaml_alias_node +; + +@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node; + +@yaml_node_parent = @yaml_collection_node | @file; + +yaml_anchors (unique int node: @yaml_node ref, + string anchor: string ref); + +yaml_aliases (unique int alias: @yaml_alias_node ref, + string target: string ref); + +yaml_scalars (unique int scalar: @yaml_scalar_node ref, + int style: int ref, + string value: string ref); + +yaml_errors (unique int id: @yaml_error, + string message: string ref); + +yaml_locations(unique int locatable: @yaml_locatable ref, + int location: @location_default ref); + +@yaml_locatable = @yaml_node | @yaml_error; + + +// from prefix.dbscheme +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_default ref +); + + +// from schema + +@element = + @extractor_step +| @locatable +| @named_crate +| @unextracted +; + +extractor_steps( + unique int id: @extractor_step, + string action: string ref, + int duration_ms: int ref +); + +#keyset[id] +extractor_step_files( + int id: @extractor_step ref, + int file: @file ref +); + +@locatable = + @ast_node +| @crate +; + +named_crates( + unique int id: @named_crate, + string name: string ref, + int crate: @crate ref +); + +@unextracted = + @missing +| @unimplemented +; + +@ast_node = + @abi +| @addressable +| @arg_list +| @asm_dir_spec +| @asm_operand +| @asm_operand_expr +| @asm_option +| @asm_piece +| @asm_reg_spec +| @assoc_item +| @assoc_item_list +| @attr +| @callable +| @closure_binder +| @expr +| @extern_item +| @extern_item_list +| @field_list +| @format_args_arg +| @generic_arg +| @generic_arg_list +| @generic_param +| @generic_param_list +| @item_list +| @label +| @let_else +| @macro_items +| @match_arm +| @match_arm_list +| @match_guard +| @meta +| @name +| @param_base +| @param_list +| @parenthesized_arg_list +| @pat +| @path +| @path_segment +| @rename +| @resolvable +| @ret_type_repr +| @return_type_syntax +| @source_file +| @stmt +| @stmt_list +| @struct_expr_field +| @struct_expr_field_list +| @struct_field +| @struct_pat_field +| @struct_pat_field_list +| @token +| @token_tree +| @tuple_field +| @type_bound +| @type_bound_list +| @type_repr +| @use_bound_generic_arg +| @use_bound_generic_args +| @use_tree +| @use_tree_list +| @variant_def +| @variant_list +| @visibility +| @where_clause +| @where_pred +; + +crates( + unique int id: @crate +); + +#keyset[id] +crate_names( + int id: @crate ref, + string name: string ref +); + +#keyset[id] +crate_versions( + int id: @crate ref, + string version: string ref +); + +#keyset[id] +crate_modules( + int id: @crate ref, + int module: @module ref +); + +#keyset[id, index] +crate_cfg_options( + int id: @crate ref, + int index: int ref, + string cfg_option: string ref +); + +#keyset[id, index] +crate_named_dependencies( + int id: @crate ref, + int index: int ref, + int named_dependency: @named_crate ref +); + +missings( + unique int id: @missing +); + +unimplementeds( + unique int id: @unimplemented +); + +abis( + unique int id: @abi +); + +#keyset[id] +abi_abi_strings( + int id: @abi ref, + string abi_string: string ref +); + +@addressable = + @item +| @variant +; + +#keyset[id] +addressable_extended_canonical_paths( + int id: @addressable ref, + string extended_canonical_path: string ref +); + +#keyset[id] +addressable_crate_origins( + int id: @addressable ref, + string crate_origin: string ref +); + +arg_lists( + unique int id: @arg_list +); + +#keyset[id, index] +arg_list_args( + int id: @arg_list ref, + int index: int ref, + int arg: @expr ref +); + +asm_dir_specs( + unique int id: @asm_dir_spec +); + +@asm_operand = + @asm_const +| @asm_label +| @asm_reg_operand +| @asm_sym +; + +asm_operand_exprs( + unique int id: @asm_operand_expr +); + +#keyset[id] +asm_operand_expr_in_exprs( + int id: @asm_operand_expr ref, + int in_expr: @expr ref +); + +#keyset[id] +asm_operand_expr_out_exprs( + int id: @asm_operand_expr ref, + int out_expr: @expr ref +); + +asm_options( + unique int id: @asm_option +); + +#keyset[id] +asm_option_is_raw( + int id: @asm_option ref +); + +@asm_piece = + @asm_clobber_abi +| @asm_operand_named +| @asm_options_list +; + +asm_reg_specs( + unique int id: @asm_reg_spec +); + +#keyset[id] +asm_reg_spec_identifiers( + int id: @asm_reg_spec ref, + int identifier: @name_ref ref +); + +@assoc_item = + @const +| @function +| @macro_call +| @type_alias +; + +assoc_item_lists( + unique int id: @assoc_item_list +); + +#keyset[id, index] +assoc_item_list_assoc_items( + int id: @assoc_item_list ref, + int index: int ref, + int assoc_item: @assoc_item ref +); + +#keyset[id, index] +assoc_item_list_attrs( + int id: @assoc_item_list ref, + int index: int ref, + int attr: @attr ref +); + +attrs( + unique int id: @attr +); + +#keyset[id] +attr_meta( + int id: @attr ref, + int meta: @meta ref +); + +@callable = + @closure_expr +| @function +; + +#keyset[id] +callable_param_lists( + int id: @callable ref, + int param_list: @param_list ref +); + +#keyset[id, index] +callable_attrs( + int id: @callable ref, + int index: int ref, + int attr: @attr ref +); + +closure_binders( + unique int id: @closure_binder +); + +#keyset[id] +closure_binder_generic_param_lists( + int id: @closure_binder ref, + int generic_param_list: @generic_param_list ref +); + +@expr = + @array_expr_internal +| @asm_expr +| @await_expr +| @become_expr +| @binary_expr +| @break_expr +| @call_expr_base +| @cast_expr +| @closure_expr +| @continue_expr +| @field_expr +| @format_args_expr +| @if_expr +| @index_expr +| @labelable_expr +| @let_expr +| @literal_expr +| @macro_block_expr +| @macro_expr +| @match_expr +| @offset_of_expr +| @paren_expr +| @path_expr_base +| @prefix_expr +| @range_expr +| @ref_expr +| @return_expr +| @struct_expr +| @try_expr +| @tuple_expr +| @underscore_expr +| @yeet_expr +| @yield_expr +; + +@extern_item = + @function +| @macro_call +| @static +| @type_alias +; + +extern_item_lists( + unique int id: @extern_item_list +); + +#keyset[id, index] +extern_item_list_attrs( + int id: @extern_item_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +extern_item_list_extern_items( + int id: @extern_item_list ref, + int index: int ref, + int extern_item: @extern_item ref +); + +@field_list = + @struct_field_list +| @tuple_field_list +; + +format_args_args( + unique int id: @format_args_arg +); + +#keyset[id] +format_args_arg_exprs( + int id: @format_args_arg ref, + int expr: @expr ref +); + +#keyset[id] +format_args_arg_names( + int id: @format_args_arg ref, + int name: @name ref +); + +@generic_arg = + @assoc_type_arg +| @const_arg +| @lifetime_arg +| @type_arg +; + +generic_arg_lists( + unique int id: @generic_arg_list +); + +#keyset[id, index] +generic_arg_list_generic_args( + int id: @generic_arg_list ref, + int index: int ref, + int generic_arg: @generic_arg ref +); + +@generic_param = + @const_param +| @lifetime_param +| @type_param +; + +generic_param_lists( + unique int id: @generic_param_list +); + +#keyset[id, index] +generic_param_list_generic_params( + int id: @generic_param_list ref, + int index: int ref, + int generic_param: @generic_param ref +); + +item_lists( + unique int id: @item_list +); + +#keyset[id, index] +item_list_attrs( + int id: @item_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +item_list_items( + int id: @item_list ref, + int index: int ref, + int item: @item ref +); + +labels( + unique int id: @label +); + +#keyset[id] +label_lifetimes( + int id: @label ref, + int lifetime: @lifetime ref +); + +let_elses( + unique int id: @let_else +); + +#keyset[id] +let_else_block_exprs( + int id: @let_else ref, + int block_expr: @block_expr ref +); + +macro_items( + unique int id: @macro_items +); + +#keyset[id, index] +macro_items_items( + int id: @macro_items ref, + int index: int ref, + int item: @item ref +); + +match_arms( + unique int id: @match_arm +); + +#keyset[id, index] +match_arm_attrs( + int id: @match_arm ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +match_arm_exprs( + int id: @match_arm ref, + int expr: @expr ref +); + +#keyset[id] +match_arm_guards( + int id: @match_arm ref, + int guard: @match_guard ref +); + +#keyset[id] +match_arm_pats( + int id: @match_arm ref, + int pat: @pat ref +); + +match_arm_lists( + unique int id: @match_arm_list +); + +#keyset[id, index] +match_arm_list_arms( + int id: @match_arm_list ref, + int index: int ref, + int arm: @match_arm ref +); + +#keyset[id, index] +match_arm_list_attrs( + int id: @match_arm_list ref, + int index: int ref, + int attr: @attr ref +); + +match_guards( + unique int id: @match_guard +); + +#keyset[id] +match_guard_conditions( + int id: @match_guard ref, + int condition: @expr ref +); + +meta( + unique int id: @meta +); + +#keyset[id] +meta_exprs( + int id: @meta ref, + int expr: @expr ref +); + +#keyset[id] +meta_is_unsafe( + int id: @meta ref +); + +#keyset[id] +meta_paths( + int id: @meta ref, + int path: @path ref +); + +#keyset[id] +meta_token_trees( + int id: @meta ref, + int token_tree: @token_tree ref +); + +names( + unique int id: @name +); + +#keyset[id] +name_texts( + int id: @name ref, + string text: string ref +); + +@param_base = + @param +| @self_param +; + +#keyset[id, index] +param_base_attrs( + int id: @param_base ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +param_base_type_reprs( + int id: @param_base ref, + int type_repr: @type_repr ref +); + +param_lists( + unique int id: @param_list +); + +#keyset[id, index] +param_list_params( + int id: @param_list ref, + int index: int ref, + int param: @param ref +); + +#keyset[id] +param_list_self_params( + int id: @param_list ref, + int self_param: @self_param ref +); + +parenthesized_arg_lists( + unique int id: @parenthesized_arg_list +); + +#keyset[id, index] +parenthesized_arg_list_type_args( + int id: @parenthesized_arg_list ref, + int index: int ref, + int type_arg: @type_arg ref +); + +@pat = + @box_pat +| @const_block_pat +| @ident_pat +| @literal_pat +| @macro_pat +| @or_pat +| @paren_pat +| @path_pat +| @range_pat +| @ref_pat +| @rest_pat +| @slice_pat +| @struct_pat +| @tuple_pat +| @tuple_struct_pat +| @wildcard_pat +; + +paths( + unique int id: @path +); + +#keyset[id] +path_qualifiers( + int id: @path ref, + int qualifier: @path ref +); + +#keyset[id] +path_segments_( + int id: @path ref, + int segment: @path_segment ref +); + +path_segments( + unique int id: @path_segment +); + +#keyset[id] +path_segment_generic_arg_lists( + int id: @path_segment ref, + int generic_arg_list: @generic_arg_list ref +); + +#keyset[id] +path_segment_identifiers( + int id: @path_segment ref, + int identifier: @name_ref ref +); + +#keyset[id] +path_segment_parenthesized_arg_lists( + int id: @path_segment ref, + int parenthesized_arg_list: @parenthesized_arg_list ref +); + +#keyset[id] +path_segment_ret_types( + int id: @path_segment ref, + int ret_type: @ret_type_repr ref +); + +#keyset[id] +path_segment_return_type_syntaxes( + int id: @path_segment ref, + int return_type_syntax: @return_type_syntax ref +); + +#keyset[id] +path_segment_type_reprs( + int id: @path_segment ref, + int type_repr: @type_repr ref +); + +#keyset[id] +path_segment_trait_type_reprs( + int id: @path_segment ref, + int trait_type_repr: @path_type_repr ref +); + +renames( + unique int id: @rename +); + +#keyset[id] +rename_names( + int id: @rename ref, + int name: @name ref +); + +@resolvable = + @method_call_expr +| @path_ast_node +; + +#keyset[id] +resolvable_resolved_paths( + int id: @resolvable ref, + string resolved_path: string ref +); + +#keyset[id] +resolvable_resolved_crate_origins( + int id: @resolvable ref, + string resolved_crate_origin: string ref +); + +ret_type_reprs( + unique int id: @ret_type_repr +); + +#keyset[id] +ret_type_repr_type_reprs( + int id: @ret_type_repr ref, + int type_repr: @type_repr ref +); + +return_type_syntaxes( + unique int id: @return_type_syntax +); + +source_files( + unique int id: @source_file +); + +#keyset[id, index] +source_file_attrs( + int id: @source_file ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +source_file_items( + int id: @source_file ref, + int index: int ref, + int item: @item ref +); + +@stmt = + @expr_stmt +| @item +| @let_stmt +; + +stmt_lists( + unique int id: @stmt_list +); + +#keyset[id, index] +stmt_list_attrs( + int id: @stmt_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +stmt_list_statements( + int id: @stmt_list ref, + int index: int ref, + int statement: @stmt ref +); + +#keyset[id] +stmt_list_tail_exprs( + int id: @stmt_list ref, + int tail_expr: @expr ref +); + +struct_expr_fields( + unique int id: @struct_expr_field +); + +#keyset[id, index] +struct_expr_field_attrs( + int id: @struct_expr_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_expr_field_exprs( + int id: @struct_expr_field ref, + int expr: @expr ref +); + +#keyset[id] +struct_expr_field_identifiers( + int id: @struct_expr_field ref, + int identifier: @name_ref ref +); + +struct_expr_field_lists( + unique int id: @struct_expr_field_list +); + +#keyset[id, index] +struct_expr_field_list_attrs( + int id: @struct_expr_field_list ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +struct_expr_field_list_fields( + int id: @struct_expr_field_list ref, + int index: int ref, + int field: @struct_expr_field ref +); + +#keyset[id] +struct_expr_field_list_spreads( + int id: @struct_expr_field_list ref, + int spread: @expr ref +); + +struct_fields( + unique int id: @struct_field +); + +#keyset[id, index] +struct_field_attrs( + int id: @struct_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_field_defaults( + int id: @struct_field ref, + int default: @expr ref +); + +#keyset[id] +struct_field_is_unsafe( + int id: @struct_field ref +); + +#keyset[id] +struct_field_names( + int id: @struct_field ref, + int name: @name ref +); + +#keyset[id] +struct_field_type_reprs( + int id: @struct_field ref, + int type_repr: @type_repr ref +); + +#keyset[id] +struct_field_visibilities( + int id: @struct_field ref, + int visibility: @visibility ref +); + +struct_pat_fields( + unique int id: @struct_pat_field +); + +#keyset[id, index] +struct_pat_field_attrs( + int id: @struct_pat_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_pat_field_identifiers( + int id: @struct_pat_field ref, + int identifier: @name_ref ref +); + +#keyset[id] +struct_pat_field_pats( + int id: @struct_pat_field ref, + int pat: @pat ref +); + +struct_pat_field_lists( + unique int id: @struct_pat_field_list +); + +#keyset[id, index] +struct_pat_field_list_fields( + int id: @struct_pat_field_list ref, + int index: int ref, + int field: @struct_pat_field ref +); + +#keyset[id] +struct_pat_field_list_rest_pats( + int id: @struct_pat_field_list ref, + int rest_pat: @rest_pat ref +); + +@token = + @comment +; + +token_trees( + unique int id: @token_tree +); + +tuple_fields( + unique int id: @tuple_field +); + +#keyset[id, index] +tuple_field_attrs( + int id: @tuple_field ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +tuple_field_type_reprs( + int id: @tuple_field ref, + int type_repr: @type_repr ref +); + +#keyset[id] +tuple_field_visibilities( + int id: @tuple_field ref, + int visibility: @visibility ref +); + +type_bounds( + unique int id: @type_bound +); + +#keyset[id] +type_bound_is_async( + int id: @type_bound ref +); + +#keyset[id] +type_bound_is_const( + int id: @type_bound ref +); + +#keyset[id] +type_bound_lifetimes( + int id: @type_bound ref, + int lifetime: @lifetime ref +); + +#keyset[id] +type_bound_type_reprs( + int id: @type_bound ref, + int type_repr: @type_repr ref +); + +#keyset[id] +type_bound_use_bound_generic_args( + int id: @type_bound ref, + int use_bound_generic_args: @use_bound_generic_args ref +); + +type_bound_lists( + unique int id: @type_bound_list +); + +#keyset[id, index] +type_bound_list_bounds( + int id: @type_bound_list ref, + int index: int ref, + int bound: @type_bound ref +); + +@type_repr = + @array_type_repr +| @dyn_trait_type_repr +| @fn_ptr_type_repr +| @for_type_repr +| @impl_trait_type_repr +| @infer_type_repr +| @macro_type_repr +| @never_type_repr +| @paren_type_repr +| @path_type_repr +| @ptr_type_repr +| @ref_type_repr +| @slice_type_repr +| @tuple_type_repr +; + +@use_bound_generic_arg = + @lifetime +| @name_ref +; + +use_bound_generic_args( + unique int id: @use_bound_generic_args +); + +#keyset[id, index] +use_bound_generic_args_use_bound_generic_args( + int id: @use_bound_generic_args ref, + int index: int ref, + int use_bound_generic_arg: @use_bound_generic_arg ref +); + +use_trees( + unique int id: @use_tree +); + +#keyset[id] +use_tree_is_glob( + int id: @use_tree ref +); + +#keyset[id] +use_tree_paths( + int id: @use_tree ref, + int path: @path ref +); + +#keyset[id] +use_tree_renames( + int id: @use_tree ref, + int rename: @rename ref +); + +#keyset[id] +use_tree_use_tree_lists( + int id: @use_tree ref, + int use_tree_list: @use_tree_list ref +); + +use_tree_lists( + unique int id: @use_tree_list +); + +#keyset[id, index] +use_tree_list_use_trees( + int id: @use_tree_list ref, + int index: int ref, + int use_tree: @use_tree ref +); + +@variant_def = + @struct +| @union +| @variant +; + +variant_lists( + unique int id: @variant_list +); + +#keyset[id, index] +variant_list_variants( + int id: @variant_list ref, + int index: int ref, + int variant: @variant ref +); + +visibilities( + unique int id: @visibility +); + +#keyset[id] +visibility_paths( + int id: @visibility ref, + int path: @path ref +); + +where_clauses( + unique int id: @where_clause +); + +#keyset[id, index] +where_clause_predicates( + int id: @where_clause ref, + int index: int ref, + int predicate: @where_pred ref +); + +where_preds( + unique int id: @where_pred +); + +#keyset[id] +where_pred_generic_param_lists( + int id: @where_pred ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +where_pred_lifetimes( + int id: @where_pred ref, + int lifetime: @lifetime ref +); + +#keyset[id] +where_pred_type_reprs( + int id: @where_pred ref, + int type_repr: @type_repr ref +); + +#keyset[id] +where_pred_type_bound_lists( + int id: @where_pred ref, + int type_bound_list: @type_bound_list ref +); + +array_expr_internals( + unique int id: @array_expr_internal +); + +#keyset[id, index] +array_expr_internal_attrs( + int id: @array_expr_internal ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +array_expr_internal_exprs( + int id: @array_expr_internal ref, + int index: int ref, + int expr: @expr ref +); + +#keyset[id] +array_expr_internal_is_semicolon( + int id: @array_expr_internal ref +); + +array_type_reprs( + unique int id: @array_type_repr +); + +#keyset[id] +array_type_repr_const_args( + int id: @array_type_repr ref, + int const_arg: @const_arg ref +); + +#keyset[id] +array_type_repr_element_type_reprs( + int id: @array_type_repr ref, + int element_type_repr: @type_repr ref +); + +asm_clobber_abis( + unique int id: @asm_clobber_abi +); + +asm_consts( + unique int id: @asm_const +); + +#keyset[id] +asm_const_exprs( + int id: @asm_const ref, + int expr: @expr ref +); + +#keyset[id] +asm_const_is_const( + int id: @asm_const ref +); + +asm_exprs( + unique int id: @asm_expr +); + +#keyset[id, index] +asm_expr_asm_pieces( + int id: @asm_expr ref, + int index: int ref, + int asm_piece: @asm_piece ref +); + +#keyset[id, index] +asm_expr_attrs( + int id: @asm_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +asm_expr_templates( + int id: @asm_expr ref, + int index: int ref, + int template: @expr ref +); + +asm_labels( + unique int id: @asm_label +); + +#keyset[id] +asm_label_block_exprs( + int id: @asm_label ref, + int block_expr: @block_expr ref +); + +asm_operand_nameds( + unique int id: @asm_operand_named +); + +#keyset[id] +asm_operand_named_asm_operands( + int id: @asm_operand_named ref, + int asm_operand: @asm_operand ref +); + +#keyset[id] +asm_operand_named_names( + int id: @asm_operand_named ref, + int name: @name ref +); + +asm_options_lists( + unique int id: @asm_options_list +); + +#keyset[id, index] +asm_options_list_asm_options( + int id: @asm_options_list ref, + int index: int ref, + int asm_option: @asm_option ref +); + +asm_reg_operands( + unique int id: @asm_reg_operand +); + +#keyset[id] +asm_reg_operand_asm_dir_specs( + int id: @asm_reg_operand ref, + int asm_dir_spec: @asm_dir_spec ref +); + +#keyset[id] +asm_reg_operand_asm_operand_exprs( + int id: @asm_reg_operand ref, + int asm_operand_expr: @asm_operand_expr ref +); + +#keyset[id] +asm_reg_operand_asm_reg_specs( + int id: @asm_reg_operand ref, + int asm_reg_spec: @asm_reg_spec ref +); + +asm_syms( + unique int id: @asm_sym +); + +#keyset[id] +asm_sym_paths( + int id: @asm_sym ref, + int path: @path ref +); + +assoc_type_args( + unique int id: @assoc_type_arg +); + +#keyset[id] +assoc_type_arg_const_args( + int id: @assoc_type_arg ref, + int const_arg: @const_arg ref +); + +#keyset[id] +assoc_type_arg_generic_arg_lists( + int id: @assoc_type_arg ref, + int generic_arg_list: @generic_arg_list ref +); + +#keyset[id] +assoc_type_arg_identifiers( + int id: @assoc_type_arg ref, + int identifier: @name_ref ref +); + +#keyset[id] +assoc_type_arg_param_lists( + int id: @assoc_type_arg ref, + int param_list: @param_list ref +); + +#keyset[id] +assoc_type_arg_ret_types( + int id: @assoc_type_arg ref, + int ret_type: @ret_type_repr ref +); + +#keyset[id] +assoc_type_arg_return_type_syntaxes( + int id: @assoc_type_arg ref, + int return_type_syntax: @return_type_syntax ref +); + +#keyset[id] +assoc_type_arg_type_reprs( + int id: @assoc_type_arg ref, + int type_repr: @type_repr ref +); + +#keyset[id] +assoc_type_arg_type_bound_lists( + int id: @assoc_type_arg ref, + int type_bound_list: @type_bound_list ref +); + +await_exprs( + unique int id: @await_expr +); + +#keyset[id, index] +await_expr_attrs( + int id: @await_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +await_expr_exprs( + int id: @await_expr ref, + int expr: @expr ref +); + +become_exprs( + unique int id: @become_expr +); + +#keyset[id, index] +become_expr_attrs( + int id: @become_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +become_expr_exprs( + int id: @become_expr ref, + int expr: @expr ref +); + +binary_exprs( + unique int id: @binary_expr +); + +#keyset[id, index] +binary_expr_attrs( + int id: @binary_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +binary_expr_lhs( + int id: @binary_expr ref, + int lhs: @expr ref +); + +#keyset[id] +binary_expr_operator_names( + int id: @binary_expr ref, + string operator_name: string ref +); + +#keyset[id] +binary_expr_rhs( + int id: @binary_expr ref, + int rhs: @expr ref +); + +box_pats( + unique int id: @box_pat +); + +#keyset[id] +box_pat_pats( + int id: @box_pat ref, + int pat: @pat ref +); + +break_exprs( + unique int id: @break_expr +); + +#keyset[id, index] +break_expr_attrs( + int id: @break_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +break_expr_exprs( + int id: @break_expr ref, + int expr: @expr ref +); + +#keyset[id] +break_expr_lifetimes( + int id: @break_expr ref, + int lifetime: @lifetime ref +); + +@call_expr_base = + @call_expr +| @method_call_expr +; + +#keyset[id] +call_expr_base_arg_lists( + int id: @call_expr_base ref, + int arg_list: @arg_list ref +); + +#keyset[id, index] +call_expr_base_attrs( + int id: @call_expr_base ref, + int index: int ref, + int attr: @attr ref +); + +cast_exprs( + unique int id: @cast_expr +); + +#keyset[id, index] +cast_expr_attrs( + int id: @cast_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +cast_expr_exprs( + int id: @cast_expr ref, + int expr: @expr ref +); + +#keyset[id] +cast_expr_type_reprs( + int id: @cast_expr ref, + int type_repr: @type_repr ref +); + +closure_exprs( + unique int id: @closure_expr +); + +#keyset[id] +closure_expr_bodies( + int id: @closure_expr ref, + int body: @expr ref +); + +#keyset[id] +closure_expr_closure_binders( + int id: @closure_expr ref, + int closure_binder: @closure_binder ref +); + +#keyset[id] +closure_expr_is_async( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_const( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_gen( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_move( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_is_static( + int id: @closure_expr ref +); + +#keyset[id] +closure_expr_ret_types( + int id: @closure_expr ref, + int ret_type: @ret_type_repr ref +); + +comments( + unique int id: @comment, + int parent: @ast_node ref, + string text: string ref +); + +const_args( + unique int id: @const_arg +); + +#keyset[id] +const_arg_exprs( + int id: @const_arg ref, + int expr: @expr ref +); + +const_block_pats( + unique int id: @const_block_pat +); + +#keyset[id] +const_block_pat_block_exprs( + int id: @const_block_pat ref, + int block_expr: @block_expr ref +); + +#keyset[id] +const_block_pat_is_const( + int id: @const_block_pat ref +); + +const_params( + unique int id: @const_param +); + +#keyset[id, index] +const_param_attrs( + int id: @const_param ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +const_param_default_vals( + int id: @const_param ref, + int default_val: @const_arg ref +); + +#keyset[id] +const_param_is_const( + int id: @const_param ref +); + +#keyset[id] +const_param_names( + int id: @const_param ref, + int name: @name ref +); + +#keyset[id] +const_param_type_reprs( + int id: @const_param ref, + int type_repr: @type_repr ref +); + +continue_exprs( + unique int id: @continue_expr +); + +#keyset[id, index] +continue_expr_attrs( + int id: @continue_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +continue_expr_lifetimes( + int id: @continue_expr ref, + int lifetime: @lifetime ref +); + +dyn_trait_type_reprs( + unique int id: @dyn_trait_type_repr +); + +#keyset[id] +dyn_trait_type_repr_type_bound_lists( + int id: @dyn_trait_type_repr ref, + int type_bound_list: @type_bound_list ref +); + +expr_stmts( + unique int id: @expr_stmt +); + +#keyset[id] +expr_stmt_exprs( + int id: @expr_stmt ref, + int expr: @expr ref +); + +field_exprs( + unique int id: @field_expr +); + +#keyset[id, index] +field_expr_attrs( + int id: @field_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +field_expr_containers( + int id: @field_expr ref, + int container: @expr ref +); + +#keyset[id] +field_expr_identifiers( + int id: @field_expr ref, + int identifier: @name_ref ref +); + +fn_ptr_type_reprs( + unique int id: @fn_ptr_type_repr +); + +#keyset[id] +fn_ptr_type_repr_abis( + int id: @fn_ptr_type_repr ref, + int abi: @abi ref +); + +#keyset[id] +fn_ptr_type_repr_is_async( + int id: @fn_ptr_type_repr ref +); + +#keyset[id] +fn_ptr_type_repr_is_const( + int id: @fn_ptr_type_repr ref +); + +#keyset[id] +fn_ptr_type_repr_is_unsafe( + int id: @fn_ptr_type_repr ref +); + +#keyset[id] +fn_ptr_type_repr_param_lists( + int id: @fn_ptr_type_repr ref, + int param_list: @param_list ref +); + +#keyset[id] +fn_ptr_type_repr_ret_types( + int id: @fn_ptr_type_repr ref, + int ret_type: @ret_type_repr ref +); + +for_type_reprs( + unique int id: @for_type_repr +); + +#keyset[id] +for_type_repr_generic_param_lists( + int id: @for_type_repr ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +for_type_repr_type_reprs( + int id: @for_type_repr ref, + int type_repr: @type_repr ref +); + +format_args_exprs( + unique int id: @format_args_expr +); + +#keyset[id, index] +format_args_expr_args( + int id: @format_args_expr ref, + int index: int ref, + int arg: @format_args_arg ref +); + +#keyset[id, index] +format_args_expr_attrs( + int id: @format_args_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +format_args_expr_templates( + int id: @format_args_expr ref, + int template: @expr ref +); + +ident_pats( + unique int id: @ident_pat +); + +#keyset[id, index] +ident_pat_attrs( + int id: @ident_pat ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +ident_pat_is_mut( + int id: @ident_pat ref +); + +#keyset[id] +ident_pat_is_ref( + int id: @ident_pat ref +); + +#keyset[id] +ident_pat_names( + int id: @ident_pat ref, + int name: @name ref +); + +#keyset[id] +ident_pat_pats( + int id: @ident_pat ref, + int pat: @pat ref +); + +if_exprs( + unique int id: @if_expr +); + +#keyset[id, index] +if_expr_attrs( + int id: @if_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +if_expr_conditions( + int id: @if_expr ref, + int condition: @expr ref +); + +#keyset[id] +if_expr_elses( + int id: @if_expr ref, + int else: @expr ref +); + +#keyset[id] +if_expr_thens( + int id: @if_expr ref, + int then: @block_expr ref +); + +impl_trait_type_reprs( + unique int id: @impl_trait_type_repr +); + +#keyset[id] +impl_trait_type_repr_type_bound_lists( + int id: @impl_trait_type_repr ref, + int type_bound_list: @type_bound_list ref +); + +index_exprs( + unique int id: @index_expr +); + +#keyset[id, index] +index_expr_attrs( + int id: @index_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +index_expr_bases( + int id: @index_expr ref, + int base: @expr ref +); + +#keyset[id] +index_expr_indices( + int id: @index_expr ref, + int index: @expr ref +); + +infer_type_reprs( + unique int id: @infer_type_repr +); + +@item = + @const +| @enum +| @extern_block +| @extern_crate +| @function +| @impl +| @macro_call +| @macro_def +| @macro_rules +| @module +| @static +| @struct +| @trait +| @trait_alias +| @type_alias +| @union +| @use +; + +@labelable_expr = + @block_expr +| @looping_expr +; + +#keyset[id] +labelable_expr_labels( + int id: @labelable_expr ref, + int label: @label ref +); + +let_exprs( + unique int id: @let_expr +); + +#keyset[id, index] +let_expr_attrs( + int id: @let_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +let_expr_scrutinees( + int id: @let_expr ref, + int scrutinee: @expr ref +); + +#keyset[id] +let_expr_pats( + int id: @let_expr ref, + int pat: @pat ref +); + +let_stmts( + unique int id: @let_stmt +); + +#keyset[id, index] +let_stmt_attrs( + int id: @let_stmt ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +let_stmt_initializers( + int id: @let_stmt ref, + int initializer: @expr ref +); + +#keyset[id] +let_stmt_let_elses( + int id: @let_stmt ref, + int let_else: @let_else ref +); + +#keyset[id] +let_stmt_pats( + int id: @let_stmt ref, + int pat: @pat ref +); + +#keyset[id] +let_stmt_type_reprs( + int id: @let_stmt ref, + int type_repr: @type_repr ref +); + +lifetimes( + unique int id: @lifetime +); + +#keyset[id] +lifetime_texts( + int id: @lifetime ref, + string text: string ref +); + +lifetime_args( + unique int id: @lifetime_arg +); + +#keyset[id] +lifetime_arg_lifetimes( + int id: @lifetime_arg ref, + int lifetime: @lifetime ref +); + +lifetime_params( + unique int id: @lifetime_param +); + +#keyset[id, index] +lifetime_param_attrs( + int id: @lifetime_param ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +lifetime_param_lifetimes( + int id: @lifetime_param ref, + int lifetime: @lifetime ref +); + +#keyset[id] +lifetime_param_type_bound_lists( + int id: @lifetime_param ref, + int type_bound_list: @type_bound_list ref +); + +literal_exprs( + unique int id: @literal_expr +); + +#keyset[id, index] +literal_expr_attrs( + int id: @literal_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +literal_expr_text_values( + int id: @literal_expr ref, + string text_value: string ref +); + +literal_pats( + unique int id: @literal_pat +); + +#keyset[id] +literal_pat_literals( + int id: @literal_pat ref, + int literal: @literal_expr ref +); + +macro_block_exprs( + unique int id: @macro_block_expr +); + +#keyset[id] +macro_block_expr_tail_exprs( + int id: @macro_block_expr ref, + int tail_expr: @expr ref +); + +#keyset[id, index] +macro_block_expr_statements( + int id: @macro_block_expr ref, + int index: int ref, + int statement: @stmt ref +); + +macro_exprs( + unique int id: @macro_expr +); + +#keyset[id] +macro_expr_macro_calls( + int id: @macro_expr ref, + int macro_call: @macro_call ref +); + +macro_pats( + unique int id: @macro_pat +); + +#keyset[id] +macro_pat_macro_calls( + int id: @macro_pat ref, + int macro_call: @macro_call ref +); + +macro_type_reprs( + unique int id: @macro_type_repr +); + +#keyset[id] +macro_type_repr_macro_calls( + int id: @macro_type_repr ref, + int macro_call: @macro_call ref +); + +match_exprs( + unique int id: @match_expr +); + +#keyset[id, index] +match_expr_attrs( + int id: @match_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +match_expr_scrutinees( + int id: @match_expr ref, + int scrutinee: @expr ref +); + +#keyset[id] +match_expr_match_arm_lists( + int id: @match_expr ref, + int match_arm_list: @match_arm_list ref +); + +name_refs( + unique int id: @name_ref +); + +#keyset[id] +name_ref_texts( + int id: @name_ref ref, + string text: string ref +); + +never_type_reprs( + unique int id: @never_type_repr +); + +offset_of_exprs( + unique int id: @offset_of_expr +); + +#keyset[id, index] +offset_of_expr_attrs( + int id: @offset_of_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +offset_of_expr_fields( + int id: @offset_of_expr ref, + int index: int ref, + int field: @name_ref ref +); + +#keyset[id] +offset_of_expr_type_reprs( + int id: @offset_of_expr ref, + int type_repr: @type_repr ref +); + +or_pats( + unique int id: @or_pat +); + +#keyset[id, index] +or_pat_pats( + int id: @or_pat ref, + int index: int ref, + int pat: @pat ref +); + +params( + unique int id: @param +); + +#keyset[id] +param_pats( + int id: @param ref, + int pat: @pat ref +); + +paren_exprs( + unique int id: @paren_expr +); + +#keyset[id, index] +paren_expr_attrs( + int id: @paren_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +paren_expr_exprs( + int id: @paren_expr ref, + int expr: @expr ref +); + +paren_pats( + unique int id: @paren_pat +); + +#keyset[id] +paren_pat_pats( + int id: @paren_pat ref, + int pat: @pat ref +); + +paren_type_reprs( + unique int id: @paren_type_repr +); + +#keyset[id] +paren_type_repr_type_reprs( + int id: @paren_type_repr ref, + int type_repr: @type_repr ref +); + +@path_ast_node = + @path_expr +| @path_pat +| @struct_expr +| @struct_pat +| @tuple_struct_pat +; + +#keyset[id] +path_ast_node_paths( + int id: @path_ast_node ref, + int path: @path ref +); + +@path_expr_base = + @path_expr +; + +path_type_reprs( + unique int id: @path_type_repr +); + +#keyset[id] +path_type_repr_paths( + int id: @path_type_repr ref, + int path: @path ref +); + +prefix_exprs( + unique int id: @prefix_expr +); + +#keyset[id, index] +prefix_expr_attrs( + int id: @prefix_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +prefix_expr_exprs( + int id: @prefix_expr ref, + int expr: @expr ref +); + +#keyset[id] +prefix_expr_operator_names( + int id: @prefix_expr ref, + string operator_name: string ref +); + +ptr_type_reprs( + unique int id: @ptr_type_repr +); + +#keyset[id] +ptr_type_repr_is_const( + int id: @ptr_type_repr ref +); + +#keyset[id] +ptr_type_repr_is_mut( + int id: @ptr_type_repr ref +); + +#keyset[id] +ptr_type_repr_type_reprs( + int id: @ptr_type_repr ref, + int type_repr: @type_repr ref +); + +range_exprs( + unique int id: @range_expr +); + +#keyset[id, index] +range_expr_attrs( + int id: @range_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +range_expr_ends( + int id: @range_expr ref, + int end: @expr ref +); + +#keyset[id] +range_expr_operator_names( + int id: @range_expr ref, + string operator_name: string ref +); + +#keyset[id] +range_expr_starts( + int id: @range_expr ref, + int start: @expr ref +); + +range_pats( + unique int id: @range_pat +); + +#keyset[id] +range_pat_ends( + int id: @range_pat ref, + int end: @pat ref +); + +#keyset[id] +range_pat_operator_names( + int id: @range_pat ref, + string operator_name: string ref +); + +#keyset[id] +range_pat_starts( + int id: @range_pat ref, + int start: @pat ref +); + +ref_exprs( + unique int id: @ref_expr +); + +#keyset[id, index] +ref_expr_attrs( + int id: @ref_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +ref_expr_exprs( + int id: @ref_expr ref, + int expr: @expr ref +); + +#keyset[id] +ref_expr_is_const( + int id: @ref_expr ref +); + +#keyset[id] +ref_expr_is_mut( + int id: @ref_expr ref +); + +#keyset[id] +ref_expr_is_raw( + int id: @ref_expr ref +); + +ref_pats( + unique int id: @ref_pat +); + +#keyset[id] +ref_pat_is_mut( + int id: @ref_pat ref +); + +#keyset[id] +ref_pat_pats( + int id: @ref_pat ref, + int pat: @pat ref +); + +ref_type_reprs( + unique int id: @ref_type_repr +); + +#keyset[id] +ref_type_repr_is_mut( + int id: @ref_type_repr ref +); + +#keyset[id] +ref_type_repr_lifetimes( + int id: @ref_type_repr ref, + int lifetime: @lifetime ref +); + +#keyset[id] +ref_type_repr_type_reprs( + int id: @ref_type_repr ref, + int type_repr: @type_repr ref +); + +rest_pats( + unique int id: @rest_pat +); + +#keyset[id, index] +rest_pat_attrs( + int id: @rest_pat ref, + int index: int ref, + int attr: @attr ref +); + +return_exprs( + unique int id: @return_expr +); + +#keyset[id, index] +return_expr_attrs( + int id: @return_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +return_expr_exprs( + int id: @return_expr ref, + int expr: @expr ref +); + +self_params( + unique int id: @self_param +); + +#keyset[id] +self_param_is_ref( + int id: @self_param ref +); + +#keyset[id] +self_param_is_mut( + int id: @self_param ref +); + +#keyset[id] +self_param_lifetimes( + int id: @self_param ref, + int lifetime: @lifetime ref +); + +#keyset[id] +self_param_names( + int id: @self_param ref, + int name: @name ref +); + +slice_pats( + unique int id: @slice_pat +); + +#keyset[id, index] +slice_pat_pats( + int id: @slice_pat ref, + int index: int ref, + int pat: @pat ref +); + +slice_type_reprs( + unique int id: @slice_type_repr +); + +#keyset[id] +slice_type_repr_type_reprs( + int id: @slice_type_repr ref, + int type_repr: @type_repr ref +); + +struct_field_lists( + unique int id: @struct_field_list +); + +#keyset[id, index] +struct_field_list_fields( + int id: @struct_field_list ref, + int index: int ref, + int field: @struct_field ref +); + +try_exprs( + unique int id: @try_expr +); + +#keyset[id, index] +try_expr_attrs( + int id: @try_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +try_expr_exprs( + int id: @try_expr ref, + int expr: @expr ref +); + +tuple_exprs( + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_attrs( + int id: @tuple_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id, index] +tuple_expr_fields( + int id: @tuple_expr ref, + int index: int ref, + int field: @expr ref +); + +tuple_field_lists( + unique int id: @tuple_field_list +); + +#keyset[id, index] +tuple_field_list_fields( + int id: @tuple_field_list ref, + int index: int ref, + int field: @tuple_field ref +); + +tuple_pats( + unique int id: @tuple_pat +); + +#keyset[id, index] +tuple_pat_fields( + int id: @tuple_pat ref, + int index: int ref, + int field: @pat ref +); + +tuple_type_reprs( + unique int id: @tuple_type_repr +); + +#keyset[id, index] +tuple_type_repr_fields( + int id: @tuple_type_repr ref, + int index: int ref, + int field: @type_repr ref +); + +type_args( + unique int id: @type_arg +); + +#keyset[id] +type_arg_type_reprs( + int id: @type_arg ref, + int type_repr: @type_repr ref +); + +type_params( + unique int id: @type_param +); + +#keyset[id, index] +type_param_attrs( + int id: @type_param ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +type_param_default_types( + int id: @type_param ref, + int default_type: @type_repr ref +); + +#keyset[id] +type_param_names( + int id: @type_param ref, + int name: @name ref +); + +#keyset[id] +type_param_type_bound_lists( + int id: @type_param ref, + int type_bound_list: @type_bound_list ref +); + +underscore_exprs( + unique int id: @underscore_expr +); + +#keyset[id, index] +underscore_expr_attrs( + int id: @underscore_expr ref, + int index: int ref, + int attr: @attr ref +); + +variants( + unique int id: @variant +); + +#keyset[id, index] +variant_attrs( + int id: @variant ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +variant_discriminants( + int id: @variant ref, + int discriminant: @expr ref +); + +#keyset[id] +variant_field_lists( + int id: @variant ref, + int field_list: @field_list ref +); + +#keyset[id] +variant_names( + int id: @variant ref, + int name: @name ref +); + +#keyset[id] +variant_visibilities( + int id: @variant ref, + int visibility: @visibility ref +); + +wildcard_pats( + unique int id: @wildcard_pat +); + +yeet_exprs( + unique int id: @yeet_expr +); + +#keyset[id, index] +yeet_expr_attrs( + int id: @yeet_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +yeet_expr_exprs( + int id: @yeet_expr ref, + int expr: @expr ref +); + +yield_exprs( + unique int id: @yield_expr +); + +#keyset[id, index] +yield_expr_attrs( + int id: @yield_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +yield_expr_exprs( + int id: @yield_expr ref, + int expr: @expr ref +); + +block_exprs( + unique int id: @block_expr +); + +#keyset[id, index] +block_expr_attrs( + int id: @block_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +block_expr_is_async( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_const( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_gen( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_move( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_try( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_unsafe( + int id: @block_expr ref +); + +#keyset[id] +block_expr_stmt_lists( + int id: @block_expr ref, + int stmt_list: @stmt_list ref +); + +call_exprs( + unique int id: @call_expr +); + +#keyset[id] +call_expr_functions( + int id: @call_expr ref, + int function: @expr ref +); + +consts( + unique int id: @const +); + +#keyset[id, index] +const_attrs( + int id: @const ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +const_bodies( + int id: @const ref, + int body: @expr ref +); + +#keyset[id] +const_is_const( + int id: @const ref +); + +#keyset[id] +const_is_default( + int id: @const ref +); + +#keyset[id] +const_names( + int id: @const ref, + int name: @name ref +); + +#keyset[id] +const_type_reprs( + int id: @const ref, + int type_repr: @type_repr ref +); + +#keyset[id] +const_visibilities( + int id: @const ref, + int visibility: @visibility ref +); + +enums( + unique int id: @enum +); + +#keyset[id, index] +enum_attrs( + int id: @enum ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +enum_generic_param_lists( + int id: @enum ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +enum_names( + int id: @enum ref, + int name: @name ref +); + +#keyset[id] +enum_variant_lists( + int id: @enum ref, + int variant_list: @variant_list ref +); + +#keyset[id] +enum_visibilities( + int id: @enum ref, + int visibility: @visibility ref +); + +#keyset[id] +enum_where_clauses( + int id: @enum ref, + int where_clause: @where_clause ref +); + +extern_blocks( + unique int id: @extern_block +); + +#keyset[id] +extern_block_abis( + int id: @extern_block ref, + int abi: @abi ref +); + +#keyset[id, index] +extern_block_attrs( + int id: @extern_block ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +extern_block_extern_item_lists( + int id: @extern_block ref, + int extern_item_list: @extern_item_list ref +); + +#keyset[id] +extern_block_is_unsafe( + int id: @extern_block ref +); + +extern_crates( + unique int id: @extern_crate +); + +#keyset[id, index] +extern_crate_attrs( + int id: @extern_crate ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +extern_crate_identifiers( + int id: @extern_crate ref, + int identifier: @name_ref ref +); + +#keyset[id] +extern_crate_renames( + int id: @extern_crate ref, + int rename: @rename ref +); + +#keyset[id] +extern_crate_visibilities( + int id: @extern_crate ref, + int visibility: @visibility ref +); + +functions( + unique int id: @function +); + +#keyset[id] +function_abis( + int id: @function ref, + int abi: @abi ref +); + +#keyset[id] +function_bodies( + int id: @function ref, + int body: @block_expr ref +); + +#keyset[id] +function_generic_param_lists( + int id: @function ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +function_is_async( + int id: @function ref +); + +#keyset[id] +function_is_const( + int id: @function ref +); + +#keyset[id] +function_is_default( + int id: @function ref +); + +#keyset[id] +function_is_gen( + int id: @function ref +); + +#keyset[id] +function_is_unsafe( + int id: @function ref +); + +#keyset[id] +function_names( + int id: @function ref, + int name: @name ref +); + +#keyset[id] +function_ret_types( + int id: @function ref, + int ret_type: @ret_type_repr ref +); + +#keyset[id] +function_visibilities( + int id: @function ref, + int visibility: @visibility ref +); + +#keyset[id] +function_where_clauses( + int id: @function ref, + int where_clause: @where_clause ref +); + +impls( + unique int id: @impl +); + +#keyset[id] +impl_assoc_item_lists( + int id: @impl ref, + int assoc_item_list: @assoc_item_list ref +); + +#keyset[id, index] +impl_attrs( + int id: @impl ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +impl_generic_param_lists( + int id: @impl ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +impl_is_const( + int id: @impl ref +); + +#keyset[id] +impl_is_default( + int id: @impl ref +); + +#keyset[id] +impl_is_unsafe( + int id: @impl ref +); + +#keyset[id] +impl_self_ties( + int id: @impl ref, + int self_ty: @type_repr ref +); + +#keyset[id] +impl_traits( + int id: @impl ref, + int trait: @type_repr ref +); + +#keyset[id] +impl_visibilities( + int id: @impl ref, + int visibility: @visibility ref +); + +#keyset[id] +impl_where_clauses( + int id: @impl ref, + int where_clause: @where_clause ref +); + +@looping_expr = + @for_expr +| @loop_expr +| @while_expr +; + +#keyset[id] +looping_expr_loop_bodies( + int id: @looping_expr ref, + int loop_body: @block_expr ref +); + +macro_calls( + unique int id: @macro_call +); + +#keyset[id, index] +macro_call_attrs( + int id: @macro_call ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +macro_call_paths( + int id: @macro_call ref, + int path: @path ref +); + +#keyset[id] +macro_call_token_trees( + int id: @macro_call ref, + int token_tree: @token_tree ref +); + +#keyset[id] +macro_call_expandeds( + int id: @macro_call ref, + int expanded: @ast_node ref +); + +macro_defs( + unique int id: @macro_def +); + +#keyset[id] +macro_def_args( + int id: @macro_def ref, + int args: @token_tree ref +); + +#keyset[id, index] +macro_def_attrs( + int id: @macro_def ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +macro_def_bodies( + int id: @macro_def ref, + int body: @token_tree ref +); + +#keyset[id] +macro_def_names( + int id: @macro_def ref, + int name: @name ref +); + +#keyset[id] +macro_def_visibilities( + int id: @macro_def ref, + int visibility: @visibility ref +); + +macro_rules( + unique int id: @macro_rules +); + +#keyset[id, index] +macro_rules_attrs( + int id: @macro_rules ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +macro_rules_names( + int id: @macro_rules ref, + int name: @name ref +); + +#keyset[id] +macro_rules_token_trees( + int id: @macro_rules ref, + int token_tree: @token_tree ref +); + +#keyset[id] +macro_rules_visibilities( + int id: @macro_rules ref, + int visibility: @visibility ref +); + +method_call_exprs( + unique int id: @method_call_expr +); + +#keyset[id] +method_call_expr_generic_arg_lists( + int id: @method_call_expr ref, + int generic_arg_list: @generic_arg_list ref +); + +#keyset[id] +method_call_expr_identifiers( + int id: @method_call_expr ref, + int identifier: @name_ref ref +); + +#keyset[id] +method_call_expr_receivers( + int id: @method_call_expr ref, + int receiver: @expr ref +); + +modules( + unique int id: @module +); + +#keyset[id, index] +module_attrs( + int id: @module ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +module_item_lists( + int id: @module ref, + int item_list: @item_list ref +); + +#keyset[id] +module_names( + int id: @module ref, + int name: @name ref +); + +#keyset[id] +module_visibilities( + int id: @module ref, + int visibility: @visibility ref +); + +path_exprs( + unique int id: @path_expr +); + +#keyset[id, index] +path_expr_attrs( + int id: @path_expr ref, + int index: int ref, + int attr: @attr ref +); + +path_pats( + unique int id: @path_pat +); + +statics( + unique int id: @static +); + +#keyset[id, index] +static_attrs( + int id: @static ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +static_bodies( + int id: @static ref, + int body: @expr ref +); + +#keyset[id] +static_is_mut( + int id: @static ref +); + +#keyset[id] +static_is_static( + int id: @static ref +); + +#keyset[id] +static_is_unsafe( + int id: @static ref +); + +#keyset[id] +static_names( + int id: @static ref, + int name: @name ref +); + +#keyset[id] +static_type_reprs( + int id: @static ref, + int type_repr: @type_repr ref +); + +#keyset[id] +static_visibilities( + int id: @static ref, + int visibility: @visibility ref +); + +structs( + unique int id: @struct +); + +#keyset[id, index] +struct_attrs( + int id: @struct ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +struct_field_lists_( + int id: @struct ref, + int field_list: @field_list ref +); + +#keyset[id] +struct_generic_param_lists( + int id: @struct ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +struct_names( + int id: @struct ref, + int name: @name ref +); + +#keyset[id] +struct_visibilities( + int id: @struct ref, + int visibility: @visibility ref +); + +#keyset[id] +struct_where_clauses( + int id: @struct ref, + int where_clause: @where_clause ref +); + +struct_exprs( + unique int id: @struct_expr +); + +#keyset[id] +struct_expr_struct_expr_field_lists( + int id: @struct_expr ref, + int struct_expr_field_list: @struct_expr_field_list ref +); + +struct_pats( + unique int id: @struct_pat +); + +#keyset[id] +struct_pat_struct_pat_field_lists( + int id: @struct_pat ref, + int struct_pat_field_list: @struct_pat_field_list ref +); + +traits( + unique int id: @trait +); + +#keyset[id] +trait_assoc_item_lists( + int id: @trait ref, + int assoc_item_list: @assoc_item_list ref +); + +#keyset[id, index] +trait_attrs( + int id: @trait ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +trait_generic_param_lists( + int id: @trait ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +trait_is_auto( + int id: @trait ref +); + +#keyset[id] +trait_is_unsafe( + int id: @trait ref +); + +#keyset[id] +trait_names( + int id: @trait ref, + int name: @name ref +); + +#keyset[id] +trait_type_bound_lists( + int id: @trait ref, + int type_bound_list: @type_bound_list ref +); + +#keyset[id] +trait_visibilities( + int id: @trait ref, + int visibility: @visibility ref +); + +#keyset[id] +trait_where_clauses( + int id: @trait ref, + int where_clause: @where_clause ref +); + +trait_aliases( + unique int id: @trait_alias +); + +#keyset[id, index] +trait_alias_attrs( + int id: @trait_alias ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +trait_alias_generic_param_lists( + int id: @trait_alias ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +trait_alias_names( + int id: @trait_alias ref, + int name: @name ref +); + +#keyset[id] +trait_alias_type_bound_lists( + int id: @trait_alias ref, + int type_bound_list: @type_bound_list ref +); + +#keyset[id] +trait_alias_visibilities( + int id: @trait_alias ref, + int visibility: @visibility ref +); + +#keyset[id] +trait_alias_where_clauses( + int id: @trait_alias ref, + int where_clause: @where_clause ref +); + +tuple_struct_pats( + unique int id: @tuple_struct_pat +); + +#keyset[id, index] +tuple_struct_pat_fields( + int id: @tuple_struct_pat ref, + int index: int ref, + int field: @pat ref +); + +type_aliases( + unique int id: @type_alias +); + +#keyset[id, index] +type_alias_attrs( + int id: @type_alias ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +type_alias_generic_param_lists( + int id: @type_alias ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +type_alias_is_default( + int id: @type_alias ref +); + +#keyset[id] +type_alias_names( + int id: @type_alias ref, + int name: @name ref +); + +#keyset[id] +type_alias_type_reprs( + int id: @type_alias ref, + int type_repr: @type_repr ref +); + +#keyset[id] +type_alias_type_bound_lists( + int id: @type_alias ref, + int type_bound_list: @type_bound_list ref +); + +#keyset[id] +type_alias_visibilities( + int id: @type_alias ref, + int visibility: @visibility ref +); + +#keyset[id] +type_alias_where_clauses( + int id: @type_alias ref, + int where_clause: @where_clause ref +); + +unions( + unique int id: @union +); + +#keyset[id, index] +union_attrs( + int id: @union ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +union_generic_param_lists( + int id: @union ref, + int generic_param_list: @generic_param_list ref +); + +#keyset[id] +union_names( + int id: @union ref, + int name: @name ref +); + +#keyset[id] +union_struct_field_lists( + int id: @union ref, + int struct_field_list: @struct_field_list ref +); + +#keyset[id] +union_visibilities( + int id: @union ref, + int visibility: @visibility ref +); + +#keyset[id] +union_where_clauses( + int id: @union ref, + int where_clause: @where_clause ref +); + +uses( + unique int id: @use +); + +#keyset[id, index] +use_attrs( + int id: @use ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +use_use_trees( + int id: @use ref, + int use_tree: @use_tree ref +); + +#keyset[id] +use_visibilities( + int id: @use ref, + int visibility: @visibility ref +); + +for_exprs( + unique int id: @for_expr +); + +#keyset[id, index] +for_expr_attrs( + int id: @for_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +for_expr_iterables( + int id: @for_expr ref, + int iterable: @expr ref +); + +#keyset[id] +for_expr_pats( + int id: @for_expr ref, + int pat: @pat ref +); + +loop_exprs( + unique int id: @loop_expr +); + +#keyset[id, index] +loop_expr_attrs( + int id: @loop_expr ref, + int index: int ref, + int attr: @attr ref +); + +while_exprs( + unique int id: @while_expr +); + +#keyset[id, index] +while_expr_attrs( + int id: @while_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +while_expr_conditions( + int id: @while_expr ref, + int condition: @expr ref +); diff --git a/rust/ql/lib/upgrades/e8707b675dc574aca9863eabcc09ac76f15bb9c2/upgrade.properties b/rust/ql/lib/upgrades/e8707b675dc574aca9863eabcc09ac76f15bb9c2/upgrade.properties new file mode 100644 index 000000000000..5e11ce73174a --- /dev/null +++ b/rust/ql/lib/upgrades/e8707b675dc574aca9863eabcc09ac76f15bb9c2/upgrade.properties @@ -0,0 +1,9 @@ +description: Rename MacroStmts to MacroBlockExpr +compatibility: full + +macro_block_exprs.rel: reorder macro_stmts(@macro_stmts id) id +macro_block_expr_tail_exprs.rel: reorder macro_stmts_exprs(@macro_stmts id, @expr expr) id expr +macro_block_expr_statements.rel: reorder macro_stmts_statements(@macro_stmts id, int index, @stmt statement) id index statement +macro_stmts.rel: delete +macro_stmts_exprs.rel: delete +macro_stmts_statements.rel: delete From 060d5152c470bbe09de81c4186cc542398193b13 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 9 Apr 2025 16:02:54 +0100 Subject: [PATCH 240/336] Rust: Add an Operation class above LogicalOperation, AssignmentOperation etc. --- .../codeql/rust/elements/LogicalOperation.qll | 3 +- .../ql/lib/codeql/rust/elements/Operation.qll | 19 ++++++ .../rust/elements/internal/BinaryExprImpl.qll | 3 +- .../rust/elements/internal/PrefixExprImpl.qll | 3 +- rust/ql/lib/rust.qll | 1 + .../library-tests/operations/Operations.ql | 2 + rust/ql/test/library-tests/operations/test.rs | 64 +++++++++---------- 7 files changed, 60 insertions(+), 35 deletions(-) create mode 100644 rust/ql/lib/codeql/rust/elements/Operation.qll diff --git a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll index ab9aa6ef0fd4..7638bea15fdb 100644 --- a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll +++ b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll @@ -1,11 +1,12 @@ private import codeql.rust.elements.Expr private import codeql.rust.elements.BinaryExpr private import codeql.rust.elements.PrefixExpr +private import codeql.rust.elements.Operation /** * A logical operation, such as `&&`, `||` or `!`. */ -abstract private class LogicalOperationImpl extends Expr { +abstract private class LogicalOperationImpl extends Operation { abstract Expr getAnOperand(); } diff --git a/rust/ql/lib/codeql/rust/elements/Operation.qll b/rust/ql/lib/codeql/rust/elements/Operation.qll new file mode 100644 index 000000000000..a1915f837fdd --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/Operation.qll @@ -0,0 +1,19 @@ +/** + * Provides classes for operations. + */ + +private import rust +private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl + +/** + * INTERNAL: This module contains the customizable definition of `Operation` and should not + * be referenced directly. + */ +module OperationImpl { + /** + * An operation, for example `&&`, `+=`, `!` or `*`. + */ + abstract class Operation extends ExprImpl::Expr { } +} + +final class Operation = OperationImpl::Operation; diff --git a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll index 6aac95fcacee..bb7106cf6e98 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll @@ -5,6 +5,7 @@ */ private import codeql.rust.elements.internal.generated.BinaryExpr +private import codeql.rust.elements.Operation::OperationImpl as OperationImpl /** * INTERNAL: This module contains the customizable definition of `BinaryExpr` and should not @@ -22,7 +23,7 @@ module Impl { * x += y; * ``` */ - class BinaryExpr extends Generated::BinaryExpr { + class BinaryExpr extends Generated::BinaryExpr, OperationImpl::Operation { override string toStringImpl() { result = "... " + this.getOperatorName() + " ..." } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll index bf77c7b88ea4..2008be60660c 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll @@ -5,6 +5,7 @@ */ private import codeql.rust.elements.internal.generated.PrefixExpr +private import codeql.rust.elements.Operation::OperationImpl as OperationImpl /** * INTERNAL: This module contains the customizable definition of `PrefixExpr` and should not @@ -20,7 +21,7 @@ module Impl { * let z = *ptr; * ``` */ - class PrefixExpr extends Generated::PrefixExpr { + class PrefixExpr extends Generated::PrefixExpr, OperationImpl::Operation { override string toStringImpl() { result = this.getOperatorName() + " ..." } } } diff --git a/rust/ql/lib/rust.qll b/rust/ql/lib/rust.qll index ff97a37b5d1f..f09f49b30bb6 100644 --- a/rust/ql/lib/rust.qll +++ b/rust/ql/lib/rust.qll @@ -3,6 +3,7 @@ import codeql.rust.elements import codeql.Locations import codeql.files.FileSystem +import codeql.rust.elements.Operation import codeql.rust.elements.AssignmentOperation import codeql.rust.elements.LogicalOperation import codeql.rust.elements.AsyncBlockExpr diff --git a/rust/ql/test/library-tests/operations/Operations.ql b/rust/ql/test/library-tests/operations/Operations.ql index 7605aa9e7196..1609d4b5d22f 100644 --- a/rust/ql/test/library-tests/operations/Operations.ql +++ b/rust/ql/test/library-tests/operations/Operations.ql @@ -2,6 +2,8 @@ import rust import utils.test.InlineExpectationsTest string describe(Expr op) { + op instanceof Operation and result = "Operation" + or op instanceof PrefixExpr and result = "PrefixExpr" or op instanceof BinaryExpr and result = "BinaryExpr" diff --git a/rust/ql/test/library-tests/operations/test.rs b/rust/ql/test/library-tests/operations/test.rs index 84152bd70723..7ec3d8a3eef1 100644 --- a/rust/ql/test/library-tests/operations/test.rs +++ b/rust/ql/test/library-tests/operations/test.rs @@ -8,48 +8,48 @@ fn test_operations( let mut x: i32; // simple assignment - x = y; // $ AssignmentOperation BinaryExpr + x = y; // $ Operation AssignmentOperation BinaryExpr // comparison operations - x == y; // $ BinaryExpr - x != y; // $ BinaryExpr - x < y; // $ BinaryExpr - x <= y; // $ BinaryExpr - x > y; // $ BinaryExpr - x >= y; // $ BinaryExpr + x == y; // $ Operation BinaryExpr + x != y; // $ Operation BinaryExpr + x < y; // $ Operation BinaryExpr + x <= y; // $ Operation BinaryExpr + x > y; // $ Operation BinaryExpr + x >= y; // $ Operation BinaryExpr // arithmetic operations - x + y; // $ BinaryExpr - x - y; // $ BinaryExpr - x * y; // $ BinaryExpr - x / y; // $ BinaryExpr - x % y; // $ BinaryExpr - x += y; // $ AssignmentOperation BinaryExpr - x -= y; // $ AssignmentOperation BinaryExpr - x *= y; // $ AssignmentOperation BinaryExpr - x /= y; // $ AssignmentOperation BinaryExpr - x %= y; // $ AssignmentOperation BinaryExpr - -x; // $ PrefixExpr + x + y; // $ Operation BinaryExpr + x - y; // $ Operation BinaryExpr + x * y; // $ Operation BinaryExpr + x / y; // $ Operation BinaryExpr + x % y; // $ Operation BinaryExpr + x += y; // $ Operation AssignmentOperation BinaryExpr + x -= y; // $ Operation AssignmentOperation BinaryExpr + x *= y; // $ Operation AssignmentOperation BinaryExpr + x /= y; // $ Operation AssignmentOperation BinaryExpr + x %= y; // $ Operation AssignmentOperation BinaryExpr + -x; // $ Operation PrefixExpr // logical operations - a && b; // $ BinaryExpr LogicalOperation - a || b; // $ BinaryExpr LogicalOperation - !a; // $ PrefixExpr LogicalOperation + a && b; // $ Operation BinaryExpr LogicalOperation + a || b; // $ Operation BinaryExpr LogicalOperation + !a; // $ Operation PrefixExpr LogicalOperation // bitwise operations - x & y; // $ BinaryExpr - x | y; // $ BinaryExpr - x ^ y; // $ BinaryExpr - x << y; // $ BinaryExpr - x >> y; // $ BinaryExpr - x &= y; // $ AssignmentOperation BinaryExpr - x |= y; // $ AssignmentOperation BinaryExpr - x ^= y; // $ AssignmentOperation BinaryExpr - x <<= y; // $ AssignmentOperation BinaryExpr - x >>= y; // $ AssignmentOperation BinaryExpr + x & y; // $ Operation BinaryExpr + x | y; // $ Operation BinaryExpr + x ^ y; // $ Operation BinaryExpr + x << y; // $ Operation BinaryExpr + x >> y; // $ Operation BinaryExpr + x &= y; // $ Operation AssignmentOperation BinaryExpr + x |= y; // $ Operation AssignmentOperation BinaryExpr + x ^= y; // $ Operation AssignmentOperation BinaryExpr + x <<= y; // $ Operation AssignmentOperation BinaryExpr + x >>= y; // $ Operation AssignmentOperation BinaryExpr // miscellaneous expressions that might be operations - *ptr; // $ PrefixExpr + *ptr; // $ Operation PrefixExpr &x; // $ RefExpr res?; From be2017621fce954873af3fd47c8eba1a5531bc94 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 May 2025 12:36:31 +0100 Subject: [PATCH 241/336] Rust: Unify getAnOperand() methods into Operation. --- .../codeql/rust/elements/LogicalOperation.qll | 4 -- .../ql/lib/codeql/rust/elements/Operation.qll | 9 ++- .../rust/elements/internal/BinaryExprImpl.qll | 2 + .../rust/elements/internal/PrefixExprImpl.qll | 2 + .../library-tests/operations/Operations.ql | 12 +++- rust/ql/test/library-tests/operations/test.rs | 64 +++++++++---------- 6 files changed, 52 insertions(+), 41 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll index 7638bea15fdb..40a3c4a4e261 100644 --- a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll +++ b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll @@ -7,7 +7,6 @@ private import codeql.rust.elements.Operation * A logical operation, such as `&&`, `||` or `!`. */ abstract private class LogicalOperationImpl extends Operation { - abstract Expr getAnOperand(); } final class LogicalOperation = LogicalOperationImpl; @@ -16,7 +15,6 @@ final class LogicalOperation = LogicalOperationImpl; * A binary logical operation, such as `&&` or `||`. */ abstract private class BinaryLogicalOperationImpl extends BinaryExpr, LogicalOperationImpl { - override Expr getAnOperand() { result = [this.getLhs(), this.getRhs()] } } final class BinaryLogicalOperation = BinaryLogicalOperationImpl; @@ -47,6 +45,4 @@ final class UnaryLogicalOperation = UnaryLogicalOperationImpl; */ final class LogicalNotExpr extends UnaryLogicalOperationImpl { LogicalNotExpr() { this.getOperatorName() = "!" } - - override Expr getAnOperand() { result = this.getExpr() } } diff --git a/rust/ql/lib/codeql/rust/elements/Operation.qll b/rust/ql/lib/codeql/rust/elements/Operation.qll index a1915f837fdd..6564e9127435 100644 --- a/rust/ql/lib/codeql/rust/elements/Operation.qll +++ b/rust/ql/lib/codeql/rust/elements/Operation.qll @@ -10,10 +10,15 @@ private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl * be referenced directly. */ module OperationImpl { + /** + * An operation, for example `&&`, `+=`, `!` or `*`. + */ + abstract class Operation extends ExprImpl::Expr { /** - * An operation, for example `&&`, `+=`, `!` or `*`. + * Gets an operand of this operation. */ - abstract class Operation extends ExprImpl::Expr { } + abstract Expr getAnOperand(); + } } final class Operation = OperationImpl::Operation; diff --git a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll index bb7106cf6e98..7793fc5808cb 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll @@ -25,5 +25,7 @@ module Impl { */ class BinaryExpr extends Generated::BinaryExpr, OperationImpl::Operation { override string toStringImpl() { result = "... " + this.getOperatorName() + " ..." } + + override Expr getAnOperand() { result = [this.getLhs(), this.getRhs()] } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll index 2008be60660c..782f0addf640 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll @@ -23,5 +23,7 @@ module Impl { */ class PrefixExpr extends Generated::PrefixExpr, OperationImpl::Operation { override string toStringImpl() { result = this.getOperatorName() + " ..." } + + override Expr getAnOperand() { result = this.getExpr() } } } diff --git a/rust/ql/test/library-tests/operations/Operations.ql b/rust/ql/test/library-tests/operations/Operations.ql index 1609d4b5d22f..5829b5b360f4 100644 --- a/rust/ql/test/library-tests/operations/Operations.ql +++ b/rust/ql/test/library-tests/operations/Operations.ql @@ -16,15 +16,21 @@ string describe(Expr op) { } module OperationsTest implements TestSig { - string getARelevantTag() { result = describe(_) } + string getARelevantTag() { result = describe(_) or result = "Operands" } predicate hasActualResult(Location location, string element, string tag, string value) { exists(Expr op | location = op.getLocation() and location.getFile().getBaseName() != "" and element = op.toString() and - tag = describe(op) and - value = "" + ( + tag = describe(op) and + value = "" + or + op instanceof Operation and + tag = "Operands" and + value = count(op.(Operation).getAnOperand()).toString() + ) ) } } diff --git a/rust/ql/test/library-tests/operations/test.rs b/rust/ql/test/library-tests/operations/test.rs index 7ec3d8a3eef1..1e8da17c2e4e 100644 --- a/rust/ql/test/library-tests/operations/test.rs +++ b/rust/ql/test/library-tests/operations/test.rs @@ -8,48 +8,48 @@ fn test_operations( let mut x: i32; // simple assignment - x = y; // $ Operation AssignmentOperation BinaryExpr + x = y; // $ Operation Operands=2 AssignmentOperation BinaryExpr // comparison operations - x == y; // $ Operation BinaryExpr - x != y; // $ Operation BinaryExpr - x < y; // $ Operation BinaryExpr - x <= y; // $ Operation BinaryExpr - x > y; // $ Operation BinaryExpr - x >= y; // $ Operation BinaryExpr + x == y; // $ Operation Operands=2 BinaryExpr + x != y; // $ Operation Operands=2 BinaryExpr + x < y; // $ Operation Operands=2 BinaryExpr + x <= y; // $ Operation Operands=2 BinaryExpr + x > y; // $ Operation Operands=2 BinaryExpr + x >= y; // $ Operation Operands=2 BinaryExpr // arithmetic operations - x + y; // $ Operation BinaryExpr - x - y; // $ Operation BinaryExpr - x * y; // $ Operation BinaryExpr - x / y; // $ Operation BinaryExpr - x % y; // $ Operation BinaryExpr - x += y; // $ Operation AssignmentOperation BinaryExpr - x -= y; // $ Operation AssignmentOperation BinaryExpr - x *= y; // $ Operation AssignmentOperation BinaryExpr - x /= y; // $ Operation AssignmentOperation BinaryExpr - x %= y; // $ Operation AssignmentOperation BinaryExpr - -x; // $ Operation PrefixExpr + x + y; // $ Operation Operands=2 BinaryExpr + x - y; // $ Operation Operands=2 BinaryExpr + x * y; // $ Operation Operands=2 BinaryExpr + x / y; // $ Operation Operands=2 BinaryExpr + x % y; // $ Operation Operands=2 BinaryExpr + x += y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x -= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x *= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x /= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x %= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + -x; // $ Operation Operands=1 PrefixExpr // logical operations - a && b; // $ Operation BinaryExpr LogicalOperation - a || b; // $ Operation BinaryExpr LogicalOperation - !a; // $ Operation PrefixExpr LogicalOperation + a && b; // $ Operation Operands=2 BinaryExpr LogicalOperation + a || b; // $ Operation Operands=2 BinaryExpr LogicalOperation + !a; // $ Operation Operands=1 PrefixExpr LogicalOperation // bitwise operations - x & y; // $ Operation BinaryExpr - x | y; // $ Operation BinaryExpr - x ^ y; // $ Operation BinaryExpr - x << y; // $ Operation BinaryExpr - x >> y; // $ Operation BinaryExpr - x &= y; // $ Operation AssignmentOperation BinaryExpr - x |= y; // $ Operation AssignmentOperation BinaryExpr - x ^= y; // $ Operation AssignmentOperation BinaryExpr - x <<= y; // $ Operation AssignmentOperation BinaryExpr - x >>= y; // $ Operation AssignmentOperation BinaryExpr + x & y; // $ Operation Operands=2 BinaryExpr + x | y; // $ Operation Operands=2 BinaryExpr + x ^ y; // $ Operation Operands=2 BinaryExpr + x << y; // $ Operation Operands=2 BinaryExpr + x >> y; // $ Operation Operands=2 BinaryExpr + x &= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x |= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x ^= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x <<= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x >>= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr // miscellaneous expressions that might be operations - *ptr; // $ Operation PrefixExpr + *ptr; // $ Operation Operands=1 PrefixExpr &x; // $ RefExpr res?; From dc1b4fcf7aa2c603e9412e9a1ea98b444c53574f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 May 2025 12:50:47 +0100 Subject: [PATCH 242/336] Rust: Unify getOperatorName() methods into Operation. --- .../ql/lib/codeql/rust/elements/Operation.qll | 5 ++ .../rust/elements/internal/BinaryExprImpl.qll | 2 + .../rust/elements/internal/PrefixExprImpl.qll | 2 + .../library-tests/operations/Operations.ql | 5 +- rust/ql/test/library-tests/operations/test.rs | 64 +++++++++---------- 5 files changed, 45 insertions(+), 33 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/Operation.qll b/rust/ql/lib/codeql/rust/elements/Operation.qll index 6564e9127435..26486686cb20 100644 --- a/rust/ql/lib/codeql/rust/elements/Operation.qll +++ b/rust/ql/lib/codeql/rust/elements/Operation.qll @@ -14,6 +14,11 @@ module OperationImpl { * An operation, for example `&&`, `+=`, `!` or `*`. */ abstract class Operation extends ExprImpl::Expr { + /** + * Gets the operator name of this operation, if it exists. + */ + abstract string getOperatorName(); + /** * Gets an operand of this operation. */ diff --git a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll index 7793fc5808cb..42ac0521db3c 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll @@ -26,6 +26,8 @@ module Impl { class BinaryExpr extends Generated::BinaryExpr, OperationImpl::Operation { override string toStringImpl() { result = "... " + this.getOperatorName() + " ..." } + override string getOperatorName() { result = Generated::BinaryExpr.super.getOperatorName() } + override Expr getAnOperand() { result = [this.getLhs(), this.getRhs()] } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll index 782f0addf640..56cc43babd0c 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll @@ -24,6 +24,8 @@ module Impl { class PrefixExpr extends Generated::PrefixExpr, OperationImpl::Operation { override string toStringImpl() { result = this.getOperatorName() + " ..." } + override string getOperatorName() { result = Generated::PrefixExpr.super.getOperatorName() } + override Expr getAnOperand() { result = this.getExpr() } } } diff --git a/rust/ql/test/library-tests/operations/Operations.ql b/rust/ql/test/library-tests/operations/Operations.ql index 5829b5b360f4..cbb81bdcb025 100644 --- a/rust/ql/test/library-tests/operations/Operations.ql +++ b/rust/ql/test/library-tests/operations/Operations.ql @@ -16,7 +16,7 @@ string describe(Expr op) { } module OperationsTest implements TestSig { - string getARelevantTag() { result = describe(_) or result = "Operands" } + string getARelevantTag() { result = describe(_) or result = ["Op", "Operands"] } predicate hasActualResult(Location location, string element, string tag, string value) { exists(Expr op | @@ -27,6 +27,9 @@ module OperationsTest implements TestSig { tag = describe(op) and value = "" or + tag = "Op" and + value = op.(Operation).getOperatorName() + or op instanceof Operation and tag = "Operands" and value = count(op.(Operation).getAnOperand()).toString() diff --git a/rust/ql/test/library-tests/operations/test.rs b/rust/ql/test/library-tests/operations/test.rs index 1e8da17c2e4e..f82a9501fef4 100644 --- a/rust/ql/test/library-tests/operations/test.rs +++ b/rust/ql/test/library-tests/operations/test.rs @@ -8,48 +8,48 @@ fn test_operations( let mut x: i32; // simple assignment - x = y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x = y; // $ Operation Op== Operands=2 AssignmentOperation BinaryExpr // comparison operations - x == y; // $ Operation Operands=2 BinaryExpr - x != y; // $ Operation Operands=2 BinaryExpr - x < y; // $ Operation Operands=2 BinaryExpr - x <= y; // $ Operation Operands=2 BinaryExpr - x > y; // $ Operation Operands=2 BinaryExpr - x >= y; // $ Operation Operands=2 BinaryExpr + x == y; // $ Operation Op=== Operands=2 BinaryExpr + x != y; // $ Operation Op=!= Operands=2 BinaryExpr + x < y; // $ Operation Op=< Operands=2 BinaryExpr + x <= y; // $ Operation Op=<= Operands=2 BinaryExpr + x > y; // $ Operation Op=> Operands=2 BinaryExpr + x >= y; // $ Operation Op=>= Operands=2 BinaryExpr // arithmetic operations - x + y; // $ Operation Operands=2 BinaryExpr - x - y; // $ Operation Operands=2 BinaryExpr - x * y; // $ Operation Operands=2 BinaryExpr - x / y; // $ Operation Operands=2 BinaryExpr - x % y; // $ Operation Operands=2 BinaryExpr - x += y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x -= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x *= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x /= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x %= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - -x; // $ Operation Operands=1 PrefixExpr + x + y; // $ Operation Op=+ Operands=2 BinaryExpr + x - y; // $ Operation Op=- Operands=2 BinaryExpr + x * y; // $ Operation Op=* Operands=2 BinaryExpr + x / y; // $ Operation Op=/ Operands=2 BinaryExpr + x % y; // $ Operation Op=% Operands=2 BinaryExpr + x += y; // $ Operation Op=+= Operands=2 AssignmentOperation BinaryExpr + x -= y; // $ Operation Op=-= Operands=2 AssignmentOperation BinaryExpr + x *= y; // $ Operation Op=*= Operands=2 AssignmentOperation BinaryExpr + x /= y; // $ Operation Op=/= Operands=2 AssignmentOperation BinaryExpr + x %= y; // $ Operation Op=%= Operands=2 AssignmentOperation BinaryExpr + -x; // $ Operation Op=- Operands=1 PrefixExpr // logical operations - a && b; // $ Operation Operands=2 BinaryExpr LogicalOperation - a || b; // $ Operation Operands=2 BinaryExpr LogicalOperation - !a; // $ Operation Operands=1 PrefixExpr LogicalOperation + a && b; // $ Operation Op=&& Operands=2 BinaryExpr LogicalOperation + a || b; // $ Operation Op=|| Operands=2 BinaryExpr LogicalOperation + !a; // $ Operation Op=! Operands=1 PrefixExpr LogicalOperation // bitwise operations - x & y; // $ Operation Operands=2 BinaryExpr - x | y; // $ Operation Operands=2 BinaryExpr - x ^ y; // $ Operation Operands=2 BinaryExpr - x << y; // $ Operation Operands=2 BinaryExpr - x >> y; // $ Operation Operands=2 BinaryExpr - x &= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x |= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x ^= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x <<= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x >>= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x & y; // $ Operation Op=& Operands=2 BinaryExpr + x | y; // $ Operation Op=| Operands=2 BinaryExpr + x ^ y; // $ Operation Op=^ Operands=2 BinaryExpr + x << y; // $ Operation Op=<< Operands=2 BinaryExpr + x >> y; // $ Operation Op=>> Operands=2 BinaryExpr + x &= y; // $ Operation Op=&= Operands=2 AssignmentOperation BinaryExpr + x |= y; // $ Operation Op=|= Operands=2 AssignmentOperation BinaryExpr + x ^= y; // $ Operation Op=^= Operands=2 AssignmentOperation BinaryExpr + x <<= y; // $ Operation Op=<<= Operands=2 AssignmentOperation BinaryExpr + x >>= y; // $ Operation Op=>>= Operands=2 AssignmentOperation BinaryExpr // miscellaneous expressions that might be operations - *ptr; // $ Operation Operands=1 PrefixExpr + *ptr; // $ Operation Op=* Operands=1 PrefixExpr &x; // $ RefExpr res?; From 09dc7fc5c4a012cecebc090135c6ede65c89bd4d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 May 2025 16:58:43 +0100 Subject: [PATCH 243/336] Rust: Autoformat. --- rust/ql/lib/codeql/rust/elements/LogicalOperation.qll | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll index 40a3c4a4e261..72cc4ffdf57e 100644 --- a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll +++ b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll @@ -6,16 +6,14 @@ private import codeql.rust.elements.Operation /** * A logical operation, such as `&&`, `||` or `!`. */ -abstract private class LogicalOperationImpl extends Operation { -} +abstract private class LogicalOperationImpl extends Operation { } final class LogicalOperation = LogicalOperationImpl; /** * A binary logical operation, such as `&&` or `||`. */ -abstract private class BinaryLogicalOperationImpl extends BinaryExpr, LogicalOperationImpl { -} +abstract private class BinaryLogicalOperationImpl extends BinaryExpr, LogicalOperationImpl { } final class BinaryLogicalOperation = BinaryLogicalOperationImpl; From 566b3dd8d909af9c6cfb3866d0f9c773d54176c2 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 May 2025 17:13:14 +0100 Subject: [PATCH 244/336] Rust: Update code scanning queries list. --- .../query-suite/rust-code-scanning.qls.expected | 1 + 1 file changed, 1 insertion(+) diff --git a/rust/ql/integration-tests/query-suite/rust-code-scanning.qls.expected b/rust/ql/integration-tests/query-suite/rust-code-scanning.qls.expected index 0e619031ed59..b3683f02d927 100644 --- a/rust/ql/integration-tests/query-suite/rust-code-scanning.qls.expected +++ b/rust/ql/integration-tests/query-suite/rust-code-scanning.qls.expected @@ -14,6 +14,7 @@ ql/rust/ql/src/queries/security/CWE-311/CleartextTransmission.ql ql/rust/ql/src/queries/security/CWE-312/CleartextLogging.ql ql/rust/ql/src/queries/security/CWE-327/BrokenCryptoAlgorithm.ql ql/rust/ql/src/queries/security/CWE-328/WeakSensitiveDataHashing.ql +ql/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql ql/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql ql/rust/ql/src/queries/summary/LinesOfCode.ql ql/rust/ql/src/queries/summary/LinesOfUserCode.ql From 16ed8476ce7a7c2cb5032d5c5e563b8d70b9c50d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 May 2025 17:24:13 +0100 Subject: [PATCH 245/336] Rust: Use the new 'quality' tag. --- rust/ql/src/queries/unusedentities/UnreachableCode.ql | 1 + rust/ql/src/queries/unusedentities/UnusedValue.ql | 1 + rust/ql/src/queries/unusedentities/UnusedVariable.ql | 1 + 3 files changed, 3 insertions(+) diff --git a/rust/ql/src/queries/unusedentities/UnreachableCode.ql b/rust/ql/src/queries/unusedentities/UnreachableCode.ql index aa49c30ce5ad..15a45c6f4b58 100644 --- a/rust/ql/src/queries/unusedentities/UnreachableCode.ql +++ b/rust/ql/src/queries/unusedentities/UnreachableCode.ql @@ -6,6 +6,7 @@ * @precision medium * @id rust/dead-code * @tags maintainability + * quality */ import rust diff --git a/rust/ql/src/queries/unusedentities/UnusedValue.ql b/rust/ql/src/queries/unusedentities/UnusedValue.ql index 1b0a498afe5c..11e29d475e49 100644 --- a/rust/ql/src/queries/unusedentities/UnusedValue.ql +++ b/rust/ql/src/queries/unusedentities/UnusedValue.ql @@ -6,6 +6,7 @@ * @precision medium * @id rust/unused-value * @tags maintainability + * quality */ import rust diff --git a/rust/ql/src/queries/unusedentities/UnusedVariable.ql b/rust/ql/src/queries/unusedentities/UnusedVariable.ql index 388c98d07b6a..398551a84a74 100644 --- a/rust/ql/src/queries/unusedentities/UnusedVariable.ql +++ b/rust/ql/src/queries/unusedentities/UnusedVariable.ql @@ -6,6 +6,7 @@ * @precision high * @id rust/unused-variable * @tags maintainability + * quality */ import rust From f59ef58c1f3640a251e714de4160ca6f7912178e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 May 2025 17:47:48 +0100 Subject: [PATCH 246/336] Rust: Update query suite list. --- .../query-suite/rust-code-quality.qls.expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/ql/integration-tests/query-suite/rust-code-quality.qls.expected b/rust/ql/integration-tests/query-suite/rust-code-quality.qls.expected index 8b137891791f..94c62ec81aea 100644 --- a/rust/ql/integration-tests/query-suite/rust-code-quality.qls.expected +++ b/rust/ql/integration-tests/query-suite/rust-code-quality.qls.expected @@ -1 +1 @@ - +ql/rust/ql/src/queries/unusedentities/UnusedVariable.ql From 5694f029de96449cffc8160e48ac9eb5113b744b Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Fri, 2 May 2025 14:03:50 -0400 Subject: [PATCH 247/336] Misc. cleanup --- cpp/ql/lib/experimental/Quantum/Language.qll | 88 +++--- .../experimental/Quantum/OpenSSL/CtxFlow.qll | 8 +- .../experimental/Quantum/OpenSSL/OpenSSL.qll | 271 +----------------- 3 files changed, 53 insertions(+), 314 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index 0d0caf7f49b5..7e1857cc68af 100644 --- a/cpp/ql/lib/experimental/Quantum/Language.qll +++ b/cpp/ql/lib/experimental/Quantum/Language.qll @@ -1,6 +1,7 @@ private import codeql.cryptography.Model import semmle.code.cpp.ir.IR import semmle.code.cpp.security.FlowSources as FlowSources +import semmle.code.cpp.dataflow.new.DataFlow private import cpp as Lang module CryptoInput implements InputSig { @@ -15,10 +16,44 @@ module CryptoInput implements InputSig { result = node.asParameter() or result = node.asVariable() } + + string locationToFileBaseNameAndLineNumberString(Location location) { + result = location.getFile().getBaseName() + ":" + location.getStartLine() + } + + predicate artifactOutputFlowsToGenericInput( + DataFlow::Node artifactOutput, DataFlow::Node otherInput + ) { + ArtifactFlow::flow(artifactOutput, otherInput) + } } module Crypto = CryptographyBase; +module ArtifactFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source = any(Crypto::ArtifactInstance artifact).getOutputNode() + } + + predicate isSink(DataFlow::Node sink) { + sink = any(Crypto::FlowAwareElement other).getInputNode() + } + + predicate isBarrierOut(DataFlow::Node node) { + node = any(Crypto::FlowAwareElement element).getInputNode() + } + + predicate isBarrierIn(DataFlow::Node node) { + node = any(Crypto::FlowAwareElement element).getOutputNode() + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + node1.(AdditionalFlowInputStep).getOutput() = node2 + } +} + +module ArtifactFlow = DataFlow::Global; + /** * Artifact output to node input configuration */ @@ -31,9 +66,9 @@ abstract class AdditionalFlowInputStep extends DataFlow::Node { /** * Generic data source to node input configuration */ -module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { +module GenericDataSourceFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { - source = any(Crypto::GenericDataSourceInstance i).getOutputNode() + source = any(Crypto::GenericSourceInstance i).getOutputNode() } predicate isSink(DataFlow::Node sink) { @@ -53,41 +88,6 @@ module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { } } -// // // TODO: I think this will be inefficient, no? -// // class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource instanceof Literal { -// // override DataFlow::Node getOutputNode() { -// // result.asExpr() = this -// // } -// // override predicate flowsTo(Crypto::FlowAwareElement other) { -// // // TODO: separate config to avoid blowing up data-flow analysis -// // GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) -// // } -// // override string getAdditionalDescription() { result = this.toString() } -// // } -// /** -// * Definitions of various generic data sources -// */ -// // final class DefaultFlowSource = SourceNode; -// // final class DefaultRemoteFlowSource = RemoteFlowSource; -// // class GenericLocalDataSource extends Crypto::GenericLocalDataSource { -// // GenericLocalDataSource() { -// // any(DefaultFlowSource src | not src instanceof DefaultRemoteFlowSource).asExpr() = this -// // } -// // override DataFlow::Node getOutputNode() { result.asExpr() = this } -// // override predicate flowsTo(Crypto::FlowAwareElement other) { -// // GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) -// // } -// // override string getAdditionalDescription() { result = this.toString() } -// // } -// // class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { -// // GenericRemoteDataSource() { any(DefaultRemoteFlowSource src).asExpr() = this } -// // override DataFlow::Node getOutputNode() { result.asExpr() = this } -// // override predicate flowsTo(Crypto::FlowAwareElement other) { -// // GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) -// // } -// // override string getAdditionalDescription() { result = this.toString() } -// // } -// module GenericDataSourceUniversalFlow = DataFlow::Global; module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source = any(Crypto::ArtifactInstance artifact).getOutputNode() @@ -112,10 +112,12 @@ module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { module ArtifactUniversalFlow = DataFlow::Global; -abstract class CipherOutputArtifact extends Crypto::KeyOperationOutputArtifactInstance { - override predicate flowsTo(Crypto::FlowAwareElement other) { - ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) - } -} - +// abstract class CipherOutputArtifact extends Crypto::KeyOperationOutputArtifactInstance { +// override predicate flowsTo(Crypto::FlowAwareElement other) { +// ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) +// } +// } +// // final override predicate flowsTo(FlowAwareElement other) { +// // Input::artifactOutputFlowsToGenericInput(this.getOutputNode(), other.getInputNode()) +// // } import OpenSSL.OpenSSL diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll index c07902022d89..88e4a1c378b0 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll @@ -1,9 +1,11 @@ +//TODO: model as data on open APIs should be able to get common flows, and obviate some of this +// e.g., copy/dup calls, need to ingest those models for openSSL and refactor. /** * In OpenSSL, flow between 'context' parameters is often used to * store state/config of how an operation will eventually be performed. * Tracing algorithms and configurations to operations therefore - * requires tracing context parameters for many OpenSSL apis. - * + * requires tracing context parameters for many OpenSSL apis. + * * This library provides a dataflow analysis to track context parameters * between any two functions accepting openssl context parameters. * The dataflow takes into consideration flowing through duplication and copy calls @@ -88,7 +90,7 @@ module OpenSSLCTXArgumentFlowConfig implements DataFlow::ConfigSig { module OpenSSLCTXArgumentFlow = DataFlow::Global; -predicate ctxFlowsTo(CTXPointerArgument source, CTXPointerArgument sink) { +predicate ctxArgFlowsToCtxArg(CTXPointerArgument source, CTXPointerArgument sink) { exists(DataFlow::Node a, DataFlow::Node b | OpenSSLCTXArgumentFlow::flow(a, b) and a.asExpr() = source and diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll index 1f9fb9a54bae..6b28c4ee8e4b 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll @@ -3,272 +3,7 @@ import semmle.code.cpp.dataflow.new.DataFlow module OpenSSLModel { import experimental.Quantum.Language - import experimental.Quantum.OpenSSL.AlgorithmInstances.Instances - import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.AlgorithmValueConsumers - import experimental.Quantum.OpenSSL.Operations.Operations - // import experimental.Quantum.OpenSSL.EVPCipherOperation - // import experimental.Quantum.OpenSSL.EVPHashOperation - // import experimental.Quantum.OpenSSL.EVPCipherAlgorithmSource - // import experimental.Quantum.OpenSSL.EVPHashAlgorithmSource - // import experimental.Quantum.OpenSSL.Random - // // Imports the additional algorithm flow step for OpenSSL - // import experimental.Quantum.OpenSSL.OpenSSLAlgorithmGetter - // // TODO: trace CTX from init variants to the context arg of EVP update calls - // //https://docs.openssl.org/master/man3/EVP_EncryptInit/#synopsis - // abstract class EVP_Cipher_Init_Call extends Call { - // Expr getContextArg() { result = this.getArgument(0) } - // abstract Expr getKeyArg(); - // abstract Expr getIVArg(); - // abstract Crypto::CipherOperationSubtype getCipherOperationSubtype(); - // } - // abstract class EVP_Cipher_EX_Init_Call extends EVP_Cipher_Init_Call { - // override Expr getKeyArg() { result = this.getArgument(3) } - // override Expr getIVArg() { result = this.getArgument(4) } - // } - // abstract class EVP_Cipher_EX2_Init_Call extends EVP_Cipher_Init_Call { - // override Expr getKeyArg() { result = this.getArgument(2) } - // override Expr getIVArg() { result = this.getArgument(3) } - // } - // abstract class EVP_Cipher_Operation_Call extends Crypto::CipherOperationInstance instanceof Call { - // Expr getContextArg() { result = this.(Call).getArgument(0) } - // abstract Expr getInputArg(); - // Expr getOutputArg() { result = this.(Call).getArgument(1) } - // abstract Expr getInitCall(); - // } - // abstract class EVP_Update_Call extends EVP_Cipher_Operation_Call { - // override Expr getInputArg() { result = this.(Call).getArgument(3) } - // } - // abstract class EVP_Final_Call extends EVP_Cipher_Operation_Call{ - // override Expr getInputArg() { none() } - // } - // class EVP_Cipher_Call extends EVP_Cipher_Operation_Call{ - // // TODO/QUESTION: what is the better way to do this? - // EVP_Cipher_Call() { this.(Call).getTarget().getName() = "EVP_Cipher" } - // override Expr getInputArg() { result = this.(Call).getArgument(2) } - // override Expr getOutputArg() { result = this.(Call).getArgument(1) } - // override Crypto::CipherOperationSubtype getCipherOperationSubtype(){ - // result instanceof Crypto::EncryptionSubtype - // } - // override Expr getInitCall(){ - // //TODO: - // none() - // } - // override Crypto::NonceArtifactConsumer getNonceConsumer(){ - // none() - // } - // override Crypto::CipherInputConsumer getInputConsumer(){ - // none() - // } - // override Crypto::CipherOutputArtifactInstance getOutputArtifact(){ - // none() - // } - // override Crypto::AlgorithmConsumer getAlgorithmConsumer(){ - // none() - // } - // } - //TODO: what about EVP_CIpher - // class EVP_EncryptUpdateCall extends Crypto::CipherOperationInstance instanceof Call { - // // NICK QUESTION: is there a better way to tie this to openssl? - // EVP_EncryptUpdateCall() { this.getTarget().getName() = "EVP_EncryptUpdate" } - // Expr getContextArg() { result = super.getArgument(0) } - // Expr getInputArg() { result = super.getArgument(3) } - // Expr getOutputArg() { result = super.getArgument(1) } - // override Crypto::CipherOperationSubtype getCipherOperationSubtype(){ - // result instanceof Crypto::EncryptionSubtype - // } - // override Crypto::NonceArtifactConsumer getNonceConsumer(){ - // none() - // } - // override Crypto::CipherInputConsumer getInputConsumer(){ - // none() - // } - // override Crypto::CipherOutputArtifactInstance getOutputArtifact(){ - // none() - // } - // override Crypto::AlgorithmConsumer getAlgorithmConsumer(){ - // none() - // } - // } - //EVP_EncryptUpdate - // /** - // * Hash function references in OpenSSL. - // */ - // predicate hash_ref_type_mapping_known(string name, Crypto::THashType algo) { - // // `ma` name has an LN_ or SN_ prefix, which we want to ignore - // // capture any name after the _ prefix using regex matching - // name = ["sha1", "sha160"] and algo instanceof Crypto::SHA1 - // or - // name = ["sha224", "sha256", "sha384", "sha512"] and algo instanceof Crypto::SHA2 - // or - // name = ["sha3-224", "sha3-256", "sha3-384", "sha3-512"] and algo instanceof Crypto::SHA3 - // or - // name = "md2" and algo instanceof Crypto::MD2 - // or - // name = "md4" and algo instanceof Crypto::MD4 - // or - // name = "md5" and algo instanceof Crypto::MD5 - // or - // name = "ripemd160" and algo instanceof Crypto::RIPEMD160 - // or - // name = "whirlpool" and algo instanceof Crypto::WHIRLPOOL - // } - // predicate hash_ref_type_mapping(FunctionCallOrMacroAccess ref, string name, Crypto::THashType algo) { - // name = ref.getTargetName().regexpCapture("(?:SN_|LN_|EVP_)([a-z0-9]+)", 1) and - // hash_ref_type_mapping_known(name, algo) - // } - // class FunctionCallOrMacroAccess extends Element { - // FunctionCallOrMacroAccess() { this instanceof FunctionCall or this instanceof MacroAccess } - // string getTargetName() { - // result = this.(FunctionCall).getTarget().getName() - // or - // result = this.(MacroAccess).getMacroName() - // } - // } - // class HashAlgorithmCallOrMacro extends Crypto::HashAlgorithmInstance instanceof FunctionCallOrMacroAccess - // { - // HashAlgorithmCallOrMacro() { hash_ref_type_mapping(this, _, _) } - // string getTargetName() { result = this.(FunctionCallOrMacroAccess).getTargetName() } - // } - // class HashAlgorithm extends Crypto::HashAlgorithm { - // HashAlgorithmCallOrMacro instance; - // HashAlgorithm() { this = Crypto::THashAlgorithm(instance) } - // override string getSHA2OrSHA3DigestSize(Location location) { - // ( - // this.getHashType() instanceof Crypto::SHA2 or - // this.getHashType() instanceof Crypto::SHA3 - // ) and - // exists(string name | - // hash_ref_type_mapping(instance, name, this.getHashType()) and - // result = name.regexpFind("\\d{3}", 0, _) and - // location = instance.getLocation() - // ) - // } - // override string getRawAlgorithmName() { result = instance.getTargetName() } - // override Crypto::THashType getHashType() { hash_ref_type_mapping(instance, _, result) } - // Element getInstance() { result = instance } - // override Location getLocation() { result = instance.getLocation() } - // } - // /** - // * Data-flow configuration for key derivation algorithm flow to EVP_KDF_derive. - // */ - // module AlgorithmToEVPKeyDeriveConfig implements DataFlow::ConfigSig { - // predicate isSource(DataFlow::Node source) { - // source.asExpr() = any(KeyDerivationAlgorithm a).getInstance() - // } - // predicate isSink(DataFlow::Node sink) { - // exists(EVP_KDF_derive kdo | - // sink.asExpr() = kdo.getCall().getAlgorithmArg() - // or - // sink.asExpr() = kdo.getCall().getContextArg() // via `EVP_KDF_CTX_set_params` - // ) - // } - // predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - // none() // TODO - // } - // } - // module AlgorithmToEVPKeyDeriveFlow = DataFlow::Global; - // predicate algorithm_to_EVP_KDF_derive(KeyDerivationAlgorithm algo, EVP_KDF_derive derive) { - // none() - // } - // /** - // * Key derivation operation (e.g., `EVP_KDF_derive`) - // */ - // class EVP_KDF_derive_FunctionCall extends Crypto::KeyDerivationOperationInstance instanceof FunctionCall - // { - // EVP_KDF_derive_FunctionCall() { this.getTarget().getName() = "EVP_KDF_derive" } - // Expr getAlgorithmArg() { result = super.getArgument(3) } - // Expr getContextArg() { result = super.getArgument(0) } - // } - // class EVP_KDF_derive extends Crypto::KeyDerivationOperation { - // EVP_KDF_derive_FunctionCall instance; - // EVP_KDF_derive() { this = Crypto::TKeyDerivationOperation(instance) } - // override Crypto::Algorithm getAlgorithm() { algorithm_to_EVP_KDF_derive(result, this) } - // EVP_KDF_derive_FunctionCall getCall() { result = instance } - // } - // /** - // * Key derivation algorithm nodes - // */ - // abstract class KeyDerivationAlgorithm extends Crypto::KeyDerivationAlgorithm { - // abstract Expr getInstance(); - // } - // /** - // * `EVP_KDF_fetch` returns a key derivation algorithm. - // */ - // class EVP_KDF_fetch_Call extends FunctionCall { - // EVP_KDF_fetch_Call() { this.getTarget().getName() = "EVP_KDF_fetch" } - // Expr getAlgorithmArg() { result = this.getArgument(1) } - // } - // class EVP_KDF_fetch_AlgorithmArg extends Crypto::KeyDerivationAlgorithmInstance instanceof Expr { - // EVP_KDF_fetch_AlgorithmArg() { exists(EVP_KDF_fetch_Call call | this = call.getAlgorithmArg()) } - // } - // predicate kdf_names(string algo) { algo = ["HKDF", "PKCS12KDF", "PBKDF2"] } - // class KDFAlgorithmStringLiteral extends StringLiteral { - // KDFAlgorithmStringLiteral() { kdf_names(this.getValue().toUpperCase()) } - // } - // private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { - // predicate isSource(DataFlow::Node src) { src.asExpr() instanceof KDFAlgorithmStringLiteral } - // predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof EVP_KDF_fetch_AlgorithmArg } - // } - // module AlgorithmStringToFetchFlow = DataFlow::Global; - // predicate algorithmStringToKDFFetchArgFlow( - // string name, KDFAlgorithmStringLiteral origin, EVP_KDF_fetch_AlgorithmArg arg - // ) { - // origin.getValue().toUpperCase() = name and - // AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), DataFlow::exprNode(arg)) - // } - // /** - // * HKDF key derivation algorithm. - // */ - // class HKDF extends KeyDerivationAlgorithm, Crypto::HKDF { - // KDFAlgorithmStringLiteral origin; - // EVP_KDF_fetch_AlgorithmArg instance; - // HKDF() { - // this = Crypto::TKeyDerivationAlgorithm(instance) and - // algorithmStringToKDFFetchArgFlow("HKDF", origin, instance) - // } - // override string getRawAlgorithmName() { result = origin.getValue() } - // override Crypto::HashAlgorithm getHashAlgorithm() { none() } - // override Crypto::LocatableElement getOrigin(string name) { - // result = origin and name = origin.toString() - // } - // override Expr getInstance() { result = origin } - // } - // /** - // * PBKDF2 key derivation algorithm. - // */ - // class PBKDF2 extends KeyDerivationAlgorithm, Crypto::PBKDF2 { - // KDFAlgorithmStringLiteral origin; - // EVP_KDF_fetch_AlgorithmArg instance; - // PBKDF2() { - // this = Crypto::TKeyDerivationAlgorithm(instance) and - // algorithmStringToKDFFetchArgFlow("PBKDF2", origin, instance) - // } - // override string getRawAlgorithmName() { result = origin.getValue() } - // override string getIterationCount(Location location) { none() } // TODO - // override string getKeyLength(Location location) { none() } // TODO - // override Crypto::HashAlgorithm getHashAlgorithm() { none() } // TODO - // override Crypto::LocatableElement getOrigin(string name) { - // result = origin and name = origin.toString() - // } - // override Expr getInstance() { result = instance } - // } - // /** - // * PKCS12KDF key derivation algorithm. - // */ - // class PKCS12KDF extends KeyDerivationAlgorithm, Crypto::PKCS12KDF { - // KDFAlgorithmStringLiteral origin; - // EVP_KDF_fetch_AlgorithmArg instance; - // PKCS12KDF() { - // this = Crypto::TKeyDerivationAlgorithm(instance) and - // algorithmStringToKDFFetchArgFlow("PKCS12KDF", origin, instance) - // } - // override string getRawAlgorithmName() { result = origin.getValue() } - // override string getIterationCount(Location location) { none() } // TODO - // override string getIDByte(Location location) { none() } // TODO - // override Crypto::HashAlgorithm getHashAlgorithm() { none() } // TODO - // override Crypto::LocatableElement getOrigin(string name) { - // result = origin and name = origin.toString() - // } - // override Expr getInstance() { result = instance } - // } + import experimental.Quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances + import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers + import experimental.Quantum.OpenSSL.Operations.OpenSSLOperations } From c08525ad81b4bd600661e002bc1624fbc2024d66 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Fri, 2 May 2025 14:07:13 -0400 Subject: [PATCH 248/336] Additional cleanup --- cpp/ql/lib/experimental/Quantum/Language.qll | 8 -------- 1 file changed, 8 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index 7e1857cc68af..2d076a1323c0 100644 --- a/cpp/ql/lib/experimental/Quantum/Language.qll +++ b/cpp/ql/lib/experimental/Quantum/Language.qll @@ -112,12 +112,4 @@ module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig { module ArtifactUniversalFlow = DataFlow::Global; -// abstract class CipherOutputArtifact extends Crypto::KeyOperationOutputArtifactInstance { -// override predicate flowsTo(Crypto::FlowAwareElement other) { -// ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) -// } -// } -// // final override predicate flowsTo(FlowAwareElement other) { -// // Input::artifactOutputFlowsToGenericInput(this.getOutputNode(), other.getInputNode()) -// // } import OpenSSL.OpenSSL From 7481de75cbe4d0fa0180e32d1eeddae6a41415e8 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Fri, 2 May 2025 14:07:38 -0400 Subject: [PATCH 249/336] Updating the model to infer implicit cipher key sizes. --- .../codeql/cryptography/Model.qll | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index a7938b1d1ce7..8fcc304e9ef9 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -582,6 +582,28 @@ module CryptographyBase Input> { } } + predicate fixedImplicitCipherKeySize(TAlgorithm type, int size) { + type = TSymmetricCipher(DES()) and size = 56 + or + type = TSymmetricCipher(DESX()) and size = 184 + or + type = TSymmetricCipher(DoubleDES()) and size = 112 + or + type = TSymmetricCipher(TripleDES()) and size = 168 + or + type = TSymmetricCipher(CHACHA20()) and size = 256 + or + type = TSymmetricCipher(IDEA()) and size = 128 + or + type = TSymmetricCipher(KUZNYECHIK()) and size = 256 + or + type = TSymmetricCipher(MAGMA()) and size = 256 + or + type = TSymmetricCipher(SM4()) and size = 128 + or + type = TSymmetricCipher(SEED()) and size = 128 + } + bindingset[type] predicate symmetric_cipher_to_name_and_structure( TSymmetricCipherType type, string name, CipherStructureType s @@ -790,6 +812,10 @@ module CryptographyBase Input> { * If a specific key size is unknown, this predicate should be implemented as `none()`. * * If the algorithm accepts a range of key sizes without a particular one specified, this predicate should be implemented as `none()`. + * + * NOTE: if the algorithm has a single key size, the implicit key size does not need to be modeled. + * This will be automatically inferred and applied at the node level. + * See `fixedImplicitCipherKeySize`. */ abstract string getKeySizeFixed(); @@ -2178,7 +2204,14 @@ module CryptographyBase Input> { /** * Gets the key size variant of this algorithm in bits, e.g., 128 for "AES-128". */ - string getKeySizeFixed() { result = instance.asAlg().getKeySizeFixed() } // TODO: key sizes for known algorithms + string getKeySizeFixed() { + result = instance.asAlg().getKeySizeFixed() + or + exists(int size | + KeyOpAlg::fixedImplicitCipherKeySize(instance.asAlg().getAlgorithmType(), size) and + result = size.toString() + ) + } /** * Gets the key size generic source node. From 09d473674b060b748cfb0e1b65e4c6bd526169a0 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Fri, 2 May 2025 14:10:38 -0400 Subject: [PATCH 250/336] Working refactor for cipher, padding, block mode. Still haven't completed connecting padding to algorithm instances if through a set padding interface. --- .../AlgorithmInstances/AlgToAVCFlow.qll | 170 ++++++++ .../BlockAlgorithmInstance.qll | 76 ++++ .../CipherAlgorithmInstance.qll | 129 ++++++ .../KnownAlgorithmConstants.qll} | 401 ++++++++++++------ .../OpenSSLAlgorithmInstanceBase.qll | 6 + .../OpenSSLAlgorithmInstances.qll | 4 + .../PaddingAlgorithmInstance.qll | 167 ++++++++ .../CipherAlgorithmValueConsumer.qll | 39 ++ .../DirectAlgorithmValueConsumer.qll | 36 ++ .../OpenSSLAlgorithmValueConsumerBase.qll | 9 + .../OpenSSLAlgorithmValueConsumers.qll | 4 + .../PaddingAlgorithmValueConsumer.qll | 36 ++ .../Operations/EVPCipherInitializer.qll | 123 ++++++ .../OpenSSL/Operations/EVPCipherOperation.qll | 114 +++++ .../Operations/OpenSSLOperationBase.qll | 21 + .../OpenSSL/Operations/OpenSSLOperations.qll | 1 + 16 files changed, 1205 insertions(+), 131 deletions(-) create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/AlgToAVCFlow.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/BlockAlgorithmInstance.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll rename cpp/ql/lib/experimental/Quantum/OpenSSL/{OpenSSLKnownAlgorithmConstants.qll => AlgorithmInstances/KnownAlgorithmConstants.qll} (90%) create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstanceBase.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstances.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/PaddingAlgorithmInstance.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/CipherAlgorithmValueConsumer.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/DirectAlgorithmValueConsumer.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumerBase.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumers.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/PaddingAlgorithmValueConsumer.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherInitializer.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherOperation.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperationBase.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperations.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/AlgToAVCFlow.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/AlgToAVCFlow.qll new file mode 100644 index 000000000000..25cdea6accf7 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/AlgToAVCFlow.qll @@ -0,0 +1,170 @@ +import cpp +import semmle.code.cpp.dataflow.new.DataFlow +import experimental.Quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants +import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers // import all known alg value consummers + +/** + * Traces 'known algorithms' to AVCs, specifically + * algorithms that are in the set of known algorithm constants. + * Padding-specific consumers exist that have their own values that + * overlap with the known algorithm constants. + * Padding consumers (specific padding consumers) are excluded from the set of sinks. + */ +module KnownOpenSSLAlgorithmToAlgorithmValueConsumerConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source.asExpr() instanceof KnownOpenSSLAlgorithmConstant + } + + predicate isSink(DataFlow::Node sink) { + exists(OpenSSLAlgorithmValueConsumer c | + c.getInputNode() = sink and + not c instanceof PaddingAlgorithmValueConsumer + ) + } + + predicate isBarrier(DataFlow::Node node) { + // False positive reducer, don't flow out through argv + exists(VariableAccess va, Variable v | + v.getAnAccess() = va and va = node.asExpr() + or + va = node.asIndirectExpr() + | + v.getName().matches("%argv") + ) + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + knownPassThroughStep(node1, node2) + } +} + +module KnownOpenSSLAlgorithmToAlgorithmValueConsumerFlow = + DataFlow::Global; + +module RSAPaddingAlgorithmToPaddingAlgorithmValueConsumerConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source.asExpr() instanceof KnownOpenSSLAlgorithmConstant + } + + predicate isSink(DataFlow::Node sink) { + exists(PaddingAlgorithmValueConsumer c | c.getInputNode() = sink) + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + knownPassThroughStep(node1, node2) + } +} + +module RSAPaddingAlgorithmToPaddingAlgorithmValueConsumerFlow = + DataFlow::Global; + +class OpenSSLAlgorithmAdditionalFlowStep extends AdditionalFlowInputStep { + OpenSSLAlgorithmAdditionalFlowStep() { exists(AlgorithmPassthroughCall c | c.getInNode() = this) } + + override DataFlow::Node getOutput() { + exists(AlgorithmPassthroughCall c | c.getInNode() = this and c.getOutNode() = result) + } +} + +abstract class AlgorithmPassthroughCall extends Call { + abstract DataFlow::Node getInNode(); + + abstract DataFlow::Node getOutNode(); +} + +class CopyAndDupAlgorithmPassthroughCall extends AlgorithmPassthroughCall { + DataFlow::Node inNode; + DataFlow::Node outNode; + + CopyAndDupAlgorithmPassthroughCall() { + // Flow out through any return or other argument of the same type + // Assume flow in and out is asIndirectExpr or asDefinitingArgument since a pointer is assumed + // to be involved + // NOTE: not attempting to detect openssl specific copy/dup functions, but anything suspected to be copy/dup + this.getTarget().getName().toLowerCase().matches(["%_dup%", "%_copy%"]) and + exists(Expr inArg, Type t | + inArg = this.getAnArgument() and t = inArg.getUnspecifiedType().stripType() + | + inNode.asIndirectExpr() = inArg and + ( + // Case 1: flow through another argument as an out arg of the same type + exists(Expr outArg | + outArg = this.getAnArgument() and + outArg != inArg and + outArg.getUnspecifiedType().stripType() = t + | + outNode.asDefiningArgument() = outArg + ) + or + // Case 2: flow through the return value if the result is the same as the intput type + exists(Expr outArg | outArg = this and outArg.getUnspecifiedType().stripType() = t | + outNode.asIndirectExpr() = outArg + ) + ) + ) + } + + override DataFlow::Node getInNode() { result = inNode } + + override DataFlow::Node getOutNode() { result = outNode } +} + +class NIDToPointerPassthroughCall extends AlgorithmPassthroughCall { + DataFlow::Node inNode; + DataFlow::Node outNode; + + NIDToPointerPassthroughCall() { + this.getTarget().getName() in ["OBJ_nid2obj", "OBJ_nid2ln", "OBJ_nid2sn"] and + inNode.asExpr() = this.getArgument(0) and + outNode.asExpr() = this + //outNode.asIndirectExpr() = this + } + + override DataFlow::Node getInNode() { result = inNode } + + override DataFlow::Node getOutNode() { result = outNode } +} + +class PointerToPointerPassthroughCall extends AlgorithmPassthroughCall { + DataFlow::Node inNode; + DataFlow::Node outNode; + + PointerToPointerPassthroughCall() { + this.getTarget().getName() = "OBJ_txt2obj" and + inNode.asIndirectExpr() = this.getArgument(0) and + outNode.asIndirectExpr() = this + or + //outNode.asExpr() = this + this.getTarget().getName() in ["OBJ_obj2txt", "i2t_ASN1_OBJECT"] and + inNode.asIndirectExpr() = this.getArgument(2) and + outNode.asDefiningArgument() = this.getArgument(0) + } + + override DataFlow::Node getInNode() { result = inNode } + + override DataFlow::Node getOutNode() { result = outNode } +} + +class PointerToNIDPassthroughCall extends AlgorithmPassthroughCall { + DataFlow::Node inNode; + DataFlow::Node outNode; + + PointerToNIDPassthroughCall() { + this.getTarget().getName() in ["OBJ_obj2nid", "OBJ_ln2nid", "OBJ_sn2nid", "OBJ_txt2nid"] and + ( + inNode.asIndirectExpr() = this.getArgument(0) + or + inNode.asExpr() = this.getArgument(0) + ) and + outNode.asExpr() = this + } + + override DataFlow::Node getInNode() { result = inNode } + + override DataFlow::Node getOutNode() { result = outNode } +} + +// TODO: pkeys pass through EVP_PKEY_CTX_new and any similar variant +predicate knownPassThroughStep(DataFlow::Node node1, DataFlow::Node node2) { + exists(AlgorithmPassthroughCall c | c.getInNode() = node1 and c.getOutNode() = node2) +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/BlockAlgorithmInstance.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/BlockAlgorithmInstance.qll new file mode 100644 index 000000000000..1e17c64f34ca --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/BlockAlgorithmInstance.qll @@ -0,0 +1,76 @@ +import cpp +import experimental.Quantum.Language +import OpenSSLAlgorithmInstanceBase +import experimental.Quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants +import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer +import AlgToAVCFlow + +/** + * Given a `KnownOpenSSLBlockModeAlgorithmConstant`, converts this to a block family type. + * Does not bind if there is know mapping (no mapping to 'unknown' or 'other'). + */ +predicate knownOpenSSLConstantToBlockModeFamilyType( + KnownOpenSSLBlockModeAlgorithmConstant e, Crypto::TBlockCipherModeOfOperationType type +) { + exists(string name | + name = e.getNormalizedName() and + ( + name.matches("CBC") and type instanceof Crypto::CBC + or + name.matches("CFB%") and type instanceof Crypto::CFB + or + name.matches("CTR") and type instanceof Crypto::CTR + or + name.matches("GCM") and type instanceof Crypto::GCM + or + name.matches("OFB") and type instanceof Crypto::OFB + or + name.matches("XTS") and type instanceof Crypto::XTS + or + name.matches("CCM") and type instanceof Crypto::CCM + or + name.matches("GCM") and type instanceof Crypto::GCM + or + name.matches("CCM") and type instanceof Crypto::CCM + or + name.matches("ECB") and type instanceof Crypto::ECB + ) + ) +} + +class KnownOpenSSLBlockModeConstantAlgorithmInstance extends OpenSSLAlgorithmInstance, + Crypto::ModeOfOperationAlgorithmInstance instanceof KnownOpenSSLBlockModeAlgorithmConstant +{ + OpenSSLAlgorithmValueConsumer getterCall; + + KnownOpenSSLBlockModeConstantAlgorithmInstance() { + // Two possibilities: + // 1) The source is a literal and flows to a getter, then we know we have an instance + // 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that + // Possibility 1: + this instanceof Literal and + exists(DataFlow::Node src, DataFlow::Node sink | + // Sink is an argument to a CipherGetterCall + sink = getterCall.(OpenSSLAlgorithmValueConsumer).getInputNode() and + // Source is `this` + src.asExpr() = this and + // This traces to a getter + KnownOpenSSLAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink) + ) + or + // Possibility 2: + this instanceof DirectAlgorithmValueConsumer and getterCall = this + } + + override Crypto::TBlockCipherModeOfOperationType getModeType() { + knownOpenSSLConstantToBlockModeFamilyType(this, result) + or + not knownOpenSSLConstantToBlockModeFamilyType(this, _) and result = Crypto::OtherMode() + } + + // NOTE: I'm not going to attempt to parse out the mode specific part, so returning + // the same as the raw name for now. + override string getRawModeAlgorithmName() { result = this.(Literal).getValue().toString() } + + override OpenSSLAlgorithmValueConsumer getAVC() { result = getterCall } +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll new file mode 100644 index 000000000000..03f2643d46d2 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll @@ -0,0 +1,129 @@ +import cpp +import experimental.Quantum.Language +import KnownAlgorithmConstants +import Crypto::KeyOpAlg as KeyOpAlg +import OpenSSLAlgorithmInstanceBase +import PaddingAlgorithmInstance +import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers +import AlgToAVCFlow +import BlockAlgorithmInstance + +/** + * Given a `KnownOpenSSLCipherAlgorithmConstant`, converts this to a cipher family type. + * Does not bind if there is know mapping (no mapping to 'unknown' or 'other'). + */ +predicate knownOpenSSLConstantToCipherFamilyType( + KnownOpenSSLCipherAlgorithmConstant e, Crypto::KeyOpAlg::TAlgorithm type +) { + exists(string name | + name = e.getNormalizedName() and + ( + name.matches("AES%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::AES()) + or + name.matches("ARIA%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::ARIA()) + or + name.matches("BLOWFISH%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::BLOWFISH()) + or + name.matches("BF%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::BLOWFISH()) + or + name.matches("CAMELLIA%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::CAMELLIA()) + or + name.matches("CHACHA20%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::CHACHA20()) + or + name.matches("CAST5%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::CAST5()) + or + name.matches("2DES%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::DoubleDES()) + or + name.matches("3DES%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::TripleDES()) + or + name.matches("DES%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::DES()) + or + name.matches("DESX%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::DESX()) + or + name.matches("GOST%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::GOST()) + or + name.matches("IDEA%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::IDEA()) + or + name.matches("KUZNYECHIK%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::KUZNYECHIK()) + or + name.matches("MAGMA%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::MAGMA()) + or + name.matches("RC2%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::RC2()) + or + name.matches("RC4%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::RC4()) + or + name.matches("RC5%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::RC5()) + or + name.matches("RSA%") and type = KeyOpAlg::TAsymmetricCipher(KeyOpAlg::RSA()) + or + name.matches("SEED%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::SEED()) + or + name.matches("SM4%") and type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::SM4()) + ) + ) +} + +class KnownOpenSSLCipherConstantAlgorithmInstance extends OpenSSLAlgorithmInstance, + Crypto::KeyOperationAlgorithmInstance instanceof KnownOpenSSLCipherAlgorithmConstant +{ + //OpenSSLAlgorithmInstance, + OpenSSLAlgorithmValueConsumer getterCall; + + KnownOpenSSLCipherConstantAlgorithmInstance() { + ( + // Two possibilities: + // 1) The source is a literal and flows to a getter, then we know we have an instance + // 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that + // Possibility 1: + this instanceof Literal and + exists(DataFlow::Node src, DataFlow::Node sink | + // Sink is an argument to a CipherGetterCall + sink = getterCall.(OpenSSLAlgorithmValueConsumer).getInputNode() and + // Source is `this` + src.asExpr() = this and + // This traces to a getter + KnownOpenSSLAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink) + ) + or + // Possibility 2: + this instanceof DirectAlgorithmValueConsumer and getterCall = this + ) + } + + override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { + // if there is a block mode associated with the same element, then that's the block mode + // note, if none are associated, we may need to parse if the cipher is a block cipher + // to determine if this is an unknown vs not relevant. + result = this + } + + override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { + //TODO: the padding is either self, or it flows through getter ctx to a set padding call + // like EVP_PKEY_CTX_set_rsa_padding + result = this + // or trace through getter ctx to set padding + } + + override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } + + override string getKeySizeFixed() { + exists(int keySize | + this.(KnownOpenSSLCipherAlgorithmConstant).getExplicitKeySize() = keySize and + result = keySize.toString() + ) + } + + override Crypto::KeyOpAlg::Algorithm getAlgorithmType() { + knownOpenSSLConstantToCipherFamilyType(this, result) + or + not knownOpenSSLConstantToCipherFamilyType(this, _) and + result = Crypto::KeyOpAlg::TUnknownKeyOperationAlgorithmType() + } + + override OpenSSLAlgorithmValueConsumer getAVC() { result = getterCall } + + override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { + // TODO: trace to any key size initializer, symmetric and asymmetric + none() + } +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll similarity index 90% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll rename to cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll index 0d328e287f6a..80bd6b422da4 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLKnownAlgorithmConstants.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll @@ -1,5 +1,5 @@ import cpp -import LibraryDetector +import experimental.Quantum.OpenSSL.LibraryDetector class KnownOpenSSLAlgorithmConstant extends Expr { string normalizedName; @@ -16,6 +16,28 @@ class KnownOpenSSLAlgorithmConstant extends Expr { string getAlgType() { result = algType } } +class KnownOpenSSLCipherAlgorithmConstant extends KnownOpenSSLAlgorithmConstant { + KnownOpenSSLCipherAlgorithmConstant() { + this.(KnownOpenSSLAlgorithmConstant).getAlgType().toLowerCase().matches("%encryption") + } + + int getExplicitKeySize() { + result = this.getNormalizedName().regexpCapture(".*-(\\d*)", 1).toInt() + } +} + +class KnownOpenSSLPaddingAlgorithmConstant extends KnownOpenSSLAlgorithmConstant { + KnownOpenSSLPaddingAlgorithmConstant() { + this.(KnownOpenSSLAlgorithmConstant).getAlgType().toLowerCase().matches("%padding") + } +} + +class KnownOpenSSLBlockModeAlgorithmConstant extends KnownOpenSSLAlgorithmConstant { + KnownOpenSSLBlockModeAlgorithmConstant() { + this.(KnownOpenSSLAlgorithmConstant).getAlgType().toLowerCase().matches("block_mode") + } +} + /** * Resolves a call to a 'direct algorithm getter', e.g., EVP_MD5() * This approach to fetching algorithms was used in OpenSSL 1.0.2. @@ -222,9 +244,9 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "gost2001" and nid = 811 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" or - name = "gost2012_256" and nid = 979 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + name = "gost2012_256" and nid = 979 and normalized = "GOST" and algType = "HASH" // TODO: Verify algorithm type or - name = "gost2012_512" and nid = 980 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" + name = "gost2012_512" and nid = 980 and normalized = "GOST" and algType = "HASH" // TODO: Verify algorithm type or name = "ed25519" and nid = 1087 and normalized = "ED25519" and algType = "ELLIPTIC_CURVE" or @@ -276,159 +298,222 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "sm3" and nid = 1143 and normalized = "SM3" and algType = "HASH" or - name = "aes-128-cbc" and nid = 419 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-128-cbc" and nid = 419 and normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-128-cbc" and nid = 419 and normalized = "CBC" and algType = "BLOCK_MODE" or - name = "aes-128-ecb" and nid = 418 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-128-ecb" and nid = 418 and normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-128-ecb" and nid = 418 and normalized = "ECB" and algType = "BLOCK_MODE" or - name = "aes-192-cbc" and nid = 423 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-192-cbc" and nid = 423 and normalized = "AES-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-192-cbc" and nid = 423 and normalized = "CBC" and algType = "BLOCK_MODE" or - name = "aes-192-ecb" and nid = 422 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-192-ecb" and nid = 422 and normalized = "AES-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-192-ecb" and nid = 422 and normalized = "ECB" and algType = "BLOCK_MODE" or - name = "aes-256-cbc" and nid = 427 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-256-cbc" and nid = 427 and normalized = "AES-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-256-cbc" and nid = 427 and normalized = "CBC" and algType = "BLOCK_MODE" or - name = "aes-256-ecb" and nid = 426 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-256-ecb" and nid = 426 and normalized = "AES-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-256-ecb" and nid = 426 and normalized = "ECB" and algType = "BLOCK_MODE" or name = "aria-128-cbc" and nid = 1066 and normalized = "CBC" and algType = "BLOCK_MODE" or - name = "aria-128-cbc" and nid = 1066 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-cbc" and + nid = 1066 and + normalized = "ARIA-128" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-128-cfb" and nid = 1067 and normalized = "CFB" and algType = "BLOCK_MODE" or - name = "aria-128-cfb" and nid = 1067 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-cfb" and + nid = 1067 and + normalized = "ARIA-128" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-128-ctr" and nid = 1069 and normalized = "CTR" and algType = "BLOCK_MODE" or - name = "aria-128-ctr" and nid = 1069 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-ctr" and + nid = 1069 and + normalized = "ARIA-128" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-128-ecb" and nid = 1065 and normalized = "ECB" and algType = "BLOCK_MODE" or - name = "aria-128-ecb" and nid = 1065 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-ecb" and + nid = 1065 and + normalized = "ARIA-128" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-128-ofb" and nid = 1068 and normalized = "OFB" and algType = "BLOCK_MODE" or - name = "aria-128-ofb" and nid = 1068 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-ofb" and + nid = 1068 and + normalized = "ARIA-128" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-128-cfb1" and nid = 1080 and normalized = "CFB1" and algType = "BLOCK_MODE" or - name = "aria-128-cfb1" and nid = 1080 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-cfb1" and + nid = 1080 and + normalized = "ARIA-128" and + algType = "SYMMETRIC_ENCRYPTION" or - name = "aria-128-cfb8" and nid = 1083 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-cfb8" and + nid = 1083 and + normalized = "ARIA-128" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-128-cfb8" and nid = 1083 and normalized = "CFB8" and algType = "BLOCK_MODE" or name = "aria-192-cbc" and nid = 1071 and normalized = "CBC" and algType = "BLOCK_MODE" or - name = "aria-192-cbc" and nid = 1071 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-cbc" and + nid = 1071 and + normalized = "ARIA-192" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-192-cfb" and nid = 1072 and normalized = "CFB" and algType = "BLOCK_MODE" or - name = "aria-192-cfb" and nid = 1072 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-cfb" and + nid = 1072 and + normalized = "ARIA-192" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-192-ctr" and nid = 1074 and normalized = "CTR" and algType = "BLOCK_MODE" or - name = "aria-192-ctr" and nid = 1074 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-ctr" and + nid = 1074 and + normalized = "ARIA-192" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-192-ecb" and nid = 1070 and normalized = "ECB" and algType = "BLOCK_MODE" or - name = "aria-192-ecb" and nid = 1070 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-ecb" and + nid = 1070 and + normalized = "ARIA-192" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-192-ofb" and nid = 1073 and normalized = "OFB" and algType = "BLOCK_MODE" or - name = "aria-192-ofb" and nid = 1073 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-ofb" and + nid = 1073 and + normalized = "ARIA-192" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-192-cfb1" and nid = 1081 and normalized = "CFB1" and algType = "BLOCK_MODE" or - name = "aria-192-cfb1" and nid = 1081 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-cfb1" and + nid = 1081 and + normalized = "ARIA-192" and + algType = "SYMMETRIC_ENCRYPTION" or - name = "aria-192-cfb8" and nid = 1084 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-cfb8" and + nid = 1084 and + normalized = "ARIA-192" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-192-cfb8" and nid = 1084 and normalized = "CFB8" and algType = "BLOCK_MODE" or name = "aria-256-cbc" and nid = 1076 and normalized = "CBC" and algType = "BLOCK_MODE" or - name = "aria-256-cbc" and nid = 1076 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-cbc" and + nid = 1076 and + normalized = "ARIA-256" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-256-cfb" and nid = 1077 and normalized = "CFB" and algType = "BLOCK_MODE" or - name = "aria-256-cfb" and nid = 1077 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-cfb" and + nid = 1077 and + normalized = "ARIA-256" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-256-ctr" and nid = 1079 and normalized = "CTR" and algType = "BLOCK_MODE" or - name = "aria-256-ctr" and nid = 1079 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-ctr" and + nid = 1079 and + normalized = "ARIA-256" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-256-ecb" and nid = 1075 and normalized = "ECB" and algType = "BLOCK_MODE" or - name = "aria-256-ecb" and nid = 1075 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-ecb" and + nid = 1075 and + normalized = "ARIA-256" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-256-ofb" and nid = 1078 and normalized = "OFB" and algType = "BLOCK_MODE" or - name = "aria-256-ofb" and nid = 1078 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-ofb" and + nid = 1078 and + normalized = "ARIA-256" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-256-cfb1" and nid = 1082 and normalized = "CFB1" and algType = "BLOCK_MODE" or - name = "aria-256-cfb1" and nid = 1082 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-cfb1" and + nid = 1082 and + normalized = "ARIA-256" and + algType = "SYMMETRIC_ENCRYPTION" or - name = "aria-256-cfb8" and nid = 1085 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-cfb8" and + nid = 1085 and + normalized = "ARIA-256" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-256-cfb8" and nid = 1085 and normalized = "CFB8" and algType = "BLOCK_MODE" or name = "camellia-128-cbc" and nid = 751 and - normalized = "CAMELLIA128" and + normalized = "CAMELLIA-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-128-cbc" and nid = 751 and normalized = "CBC" and algType = "BLOCK_MODE" or name = "camellia-128-ecb" and nid = 754 and - normalized = "CAMELLIA128" and + normalized = "CAMELLIA-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-128-ecb" and nid = 754 and normalized = "ECB" and algType = "BLOCK_MODE" or name = "camellia-192-cbc" and nid = 752 and - normalized = "CAMELLIA192" and + normalized = "CAMELLIA-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-192-cbc" and nid = 752 and normalized = "CBC" and algType = "BLOCK_MODE" or name = "camellia-192-ecb" and nid = 755 and - normalized = "CAMELLIA192" and + normalized = "CAMELLIA-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-192-ecb" and nid = 755 and normalized = "ECB" and algType = "BLOCK_MODE" or name = "camellia-256-cbc" and nid = 753 and - normalized = "CAMELLIA256" and + normalized = "CAMELLIA-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-256-cbc" and nid = 753 and normalized = "CBC" and algType = "BLOCK_MODE" or name = "camellia-256-ecb" and nid = 756 and - normalized = "CAMELLIA256" and + normalized = "CAMELLIA-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-256-ecb" and nid = 756 and normalized = "ECB" and algType = "BLOCK_MODE" or name = "rc4" and nid = 5 and normalized = "RC4" and algType = "SYMMETRIC_ENCRYPTION" or - name = "rc4-40" and nid = 97 and normalized = "RC4" and algType = "SYMMETRIC_ENCRYPTION" + name = "rc4-40" and nid = 97 and normalized = "RC4-40" and algType = "SYMMETRIC_ENCRYPTION" or name = "des-ecb" and nid = 29 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" or @@ -510,7 +595,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "seed-ofb" and nid = 778 and normalized = "OFB" and algType = "BLOCK_MODE" or - name = "rc2-cbc" and nid = 37 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" + name = "rc2-cbc" and nid = 37 and normalized = "RC2-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "rc2-cbc" and nid = 37 and normalized = "CBC" and algType = "BLOCK_MODE" or @@ -526,11 +611,11 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "rc2-ofb" and nid = 40 and normalized = "OFB" and algType = "BLOCK_MODE" or - name = "rc2-64-cbc" and nid = 166 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" + name = "rc2-64-cbc" and nid = 166 and normalized = "RC2-64" and algType = "SYMMETRIC_ENCRYPTION" or name = "rc2-64-cbc" and nid = 166 and normalized = "CBC" and algType = "BLOCK_MODE" or - name = "rc2-40-cbc" and nid = 98 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" + name = "rc2-40-cbc" and nid = 98 and normalized = "RC2-40" and algType = "SYMMETRIC_ENCRYPTION" or name = "rc2-40-cbc" and nid = 98 and normalized = "CBC" and algType = "BLOCK_MODE" or @@ -586,7 +671,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "sm4-ctr" and nid = 1139 and normalized = "CTR" and algType = "BLOCK_MODE" or - name = "aes-128-gcm" and nid = 895 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-128-gcm" and nid = 895 and normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-128-gcm" and nid = 895 and normalized = "GCM" and algType = "BLOCK_MODE" or @@ -604,32 +689,32 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "id-aes128-wrap" and nid = 788 and - normalized = "AES128" and + normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "id-aes192-wrap" and nid = 789 and - normalized = "AES192" and + normalized = "AES-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "id-aes256-wrap" and nid = 790 and - normalized = "AES256" and + normalized = "AES-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "id-aes128-wrap-pad" and nid = 897 and - normalized = "AES128" and + normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "id-aes192-wrap-pad" and nid = 900 and - normalized = "AES192" and + normalized = "AES-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "id-aes256-wrap-pad" and nid = 903 and - normalized = "AES256" and + normalized = "AES-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "chacha20" and nid = 1019 and normalized = "CHACHA20" and algType = "SYMMETRIC_ENCRYPTION" @@ -738,7 +823,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "pkcs5" and nid = 187 and normalized = "PKCS5" and algType = "KEY_DERIVATION" or - name = "aes-256-gcm" and nid = 901 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-256-gcm" and nid = 901 and normalized = "AES-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-256-gcm" and nid = 901 and normalized = "GCM" and algType = "BLOCK_MODE" or @@ -775,53 +860,71 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "id-alg-dh-sig-hmac-sha1" and nid = 325 and normalized = "SHA1" and algType = "HASH" or - name = "aes-128-ofb" and nid = 420 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-128-ofb" and nid = 420 and normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-128-ofb" and nid = 420 and normalized = "OFB" and algType = "BLOCK_MODE" or - name = "aes-128-cfb" and nid = 421 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-128-cfb" and nid = 421 and normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-128-cfb" and nid = 421 and normalized = "CFB" and algType = "BLOCK_MODE" or - name = "aes-192-ofb" and nid = 424 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-192-ofb" and nid = 424 and normalized = "AES-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-192-ofb" and nid = 424 and normalized = "OFB" and algType = "BLOCK_MODE" or - name = "aes-192-cfb" and nid = 425 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-192-cfb" and nid = 425 and normalized = "AES-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-192-cfb" and nid = 425 and normalized = "CFB" and algType = "BLOCK_MODE" or - name = "aes-256-ofb" and nid = 428 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-256-ofb" and nid = 428 and normalized = "AES-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-256-ofb" and nid = 428 and normalized = "OFB" and algType = "BLOCK_MODE" or - name = "aes-256-cfb" and nid = 429 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-256-cfb" and nid = 429 and normalized = "AES-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-256-cfb" and nid = 429 and normalized = "CFB" and algType = "BLOCK_MODE" or name = "des-cdmf" and nid = 643 and normalized = "DES" and algType = "SYMMETRIC_ENCRYPTION" or - name = "aes-128-cfb1" and nid = 650 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-128-cfb1" and + nid = 650 and + normalized = "AES-128" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aes-128-cfb1" and nid = 650 and normalized = "CFB" and algType = "BLOCK_MODE" or - name = "aes-192-cfb1" and nid = 651 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-192-cfb1" and + nid = 651 and + normalized = "AES-192" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aes-192-cfb1" and nid = 651 and normalized = "CFB" and algType = "BLOCK_MODE" or - name = "aes-256-cfb1" and nid = 652 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-256-cfb1" and + nid = 652 and + normalized = "AES-256" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aes-256-cfb1" and nid = 652 and normalized = "CFB" and algType = "BLOCK_MODE" or - name = "aes-128-cfb8" and nid = 653 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-128-cfb8" and + nid = 653 and + normalized = "AES-128" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aes-128-cfb8" and nid = 653 and normalized = "CFB8" and algType = "BLOCK_MODE" or - name = "aes-192-cfb8" and nid = 654 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-192-cfb8" and + nid = 654 and + normalized = "AES-192" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aes-192-cfb8" and nid = 654 and normalized = "CFB8" and algType = "BLOCK_MODE" or - name = "aes-256-cfb8" and nid = 655 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-256-cfb8" and + nid = 655 and + normalized = "AES-256" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aes-256-cfb8" and nid = 655 and normalized = "CFB8" and algType = "BLOCK_MODE" or @@ -851,84 +954,84 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "camellia-128-cfb" and nid = 757 and - normalized = "CAMELLIA128" and + normalized = "CAMELLIA-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-128-cfb" and nid = 757 and normalized = "CFB" and algType = "BLOCK_MODE" or name = "camellia-192-cfb" and nid = 758 and - normalized = "CAMELLIA192" and + normalized = "CAMELLIA-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-192-cfb" and nid = 758 and normalized = "CFB" and algType = "BLOCK_MODE" or name = "camellia-256-cfb" and nid = 759 and - normalized = "CAMELLIA256" and + normalized = "CAMELLIA-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-256-cfb" and nid = 759 and normalized = "CFB" and algType = "BLOCK_MODE" or name = "camellia-128-cfb1" and nid = 760 and - normalized = "CAMELLIA128" and + normalized = "CAMELLIA-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-128-cfb1" and nid = 760 and normalized = "CFB" and algType = "BLOCK_MODE" or name = "camellia-192-cfb1" and nid = 761 and - normalized = "CAMELLIA192" and + normalized = "CAMELLIA-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-192-cfb1" and nid = 761 and normalized = "CFB" and algType = "BLOCK_MODE" or name = "camellia-256-cfb1" and nid = 762 and - normalized = "CAMELLIA256" and + normalized = "CAMELLIA-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-256-cfb1" and nid = 762 and normalized = "CFB" and algType = "BLOCK_MODE" or name = "camellia-128-cfb8" and nid = 763 and - normalized = "CAMELLIA128" and + normalized = "CAMELLIA-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-128-cfb8" and nid = 763 and normalized = "CFB8" and algType = "BLOCK_MODE" or name = "camellia-192-cfb8" and nid = 764 and - normalized = "CAMELLIA192" and + normalized = "CAMELLIA-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-192-cfb8" and nid = 764 and normalized = "CFB8" and algType = "BLOCK_MODE" or name = "camellia-256-cfb8" and nid = 765 and - normalized = "CAMELLIA256" and + normalized = "CAMELLIA-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-256-cfb8" and nid = 765 and normalized = "CFB8" and algType = "BLOCK_MODE" or name = "camellia-128-ofb" and nid = 766 and - normalized = "CAMELLIA128" and + normalized = "CAMELLIA-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-128-ofb" and nid = 766 and normalized = "OFB" and algType = "BLOCK_MODE" or name = "camellia-192-ofb" and nid = 767 and - normalized = "CAMELLIA192" and + normalized = "CAMELLIA-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-192-ofb" and nid = 767 and normalized = "OFB" and algType = "BLOCK_MODE" or name = "camellia-256-ofb" and nid = 768 and - normalized = "CAMELLIA256" and + normalized = "CAMELLIA-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-256-ofb" and nid = 768 and normalized = "OFB" and algType = "BLOCK_MODE" @@ -956,56 +1059,56 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "gost2001cc" and nid = 851 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" or - name = "aes-128-ccm" and nid = 896 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-128-ccm" and nid = 896 and normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-128-ccm" and nid = 896 and normalized = "CCM" and algType = "BLOCK_MODE" or - name = "aes-192-gcm" and nid = 898 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-192-gcm" and nid = 898 and normalized = "AES-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-192-gcm" and nid = 898 and normalized = "GCM" and algType = "BLOCK_MODE" or - name = "aes-192-ccm" and nid = 899 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-192-ccm" and nid = 899 and normalized = "AES-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-192-ccm" and nid = 899 and normalized = "CCM" and algType = "BLOCK_MODE" or - name = "aes-256-ccm" and nid = 902 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-256-ccm" and nid = 902 and normalized = "AES-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-256-ccm" and nid = 902 and normalized = "CCM" and algType = "BLOCK_MODE" or - name = "aes-128-ctr" and nid = 904 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-128-ctr" and nid = 904 and normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-128-ctr" and nid = 904 and normalized = "CTR" and algType = "BLOCK_MODE" or - name = "aes-192-ctr" and nid = 905 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-192-ctr" and nid = 905 and normalized = "AES-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-192-ctr" and nid = 905 and normalized = "CTR" and algType = "BLOCK_MODE" or - name = "aes-256-ctr" and nid = 906 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-256-ctr" and nid = 906 and normalized = "AES-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-256-ctr" and nid = 906 and normalized = "CTR" and algType = "BLOCK_MODE" or name = "id-camellia128-wrap" and nid = 907 and - normalized = "CAMELLIA128" and + normalized = "CAMELLIA-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "id-camellia192-wrap" and nid = 908 and - normalized = "CAMELLIA192" and + normalized = "CAMELLIA-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "id-camellia256-wrap" and nid = 909 and - normalized = "CAMELLIA256" and + normalized = "CAMELLIA-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "mgf1" and nid = 911 and normalized = "MGF1" and algType = "HASH" or - name = "aes-128-xts" and nid = 913 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-128-xts" and nid = 913 and normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-128-xts" and nid = 913 and normalized = "XTS" and algType = "BLOCK_MODE" or - name = "aes-256-xts" and nid = 914 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-256-xts" and nid = 914 and normalized = "AES-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-256-xts" and nid = 914 and normalized = "XTS" and algType = "BLOCK_MODE" or @@ -1017,7 +1120,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "aes-128-cbc-hmac-sha1" and nid = 916 and - normalized = "AES128" and + normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-128-cbc-hmac-sha1" and nid = 916 and normalized = "CBC" and algType = "BLOCK_MODE" @@ -1026,14 +1129,14 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "aes-192-cbc-hmac-sha1" and nid = 917 and - normalized = "AES192" and + normalized = "AES-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-192-cbc-hmac-sha1" and nid = 917 and normalized = "CBC" and algType = "BLOCK_MODE" or name = "aes-256-cbc-hmac-sha1" and nid = 918 and - normalized = "AES256" and + normalized = "AES-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-256-cbc-hmac-sha1" and nid = 918 and normalized = "CBC" and algType = "BLOCK_MODE" @@ -1042,7 +1145,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "aes-128-cbc-hmac-sha256" and nid = 948 and - normalized = "AES128" and + normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-128-cbc-hmac-sha256" and nid = 948 and normalized = "CBC" and algType = "BLOCK_MODE" @@ -1051,7 +1154,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "aes-192-cbc-hmac-sha256" and nid = 949 and - normalized = "AES192" and + normalized = "AES-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-192-cbc-hmac-sha256" and nid = 949 and normalized = "CBC" and algType = "BLOCK_MODE" @@ -1060,93 +1163,93 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "aes-256-cbc-hmac-sha256" and nid = 950 and - normalized = "AES256" and + normalized = "AES-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "aes-256-cbc-hmac-sha256" and nid = 950 and normalized = "CBC" and algType = "BLOCK_MODE" or - name = "aes-128-ocb" and nid = 958 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-128-ocb" and nid = 958 and normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION" or - name = "aes-192-ocb" and nid = 959 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-192-ocb" and nid = 959 and normalized = "AES-192" and algType = "SYMMETRIC_ENCRYPTION" or - name = "aes-256-ocb" and nid = 960 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-256-ocb" and nid = 960 and normalized = "AES-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-128-gcm" and nid = 961 and - normalized = "CAMELLIA128" and + normalized = "CAMELLIA-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-128-gcm" and nid = 961 and normalized = "GCM" and algType = "BLOCK_MODE" or name = "camellia-128-ccm" and nid = 962 and - normalized = "CAMELLIA128" and + normalized = "CAMELLIA-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-128-ccm" and nid = 962 and normalized = "CCM" and algType = "BLOCK_MODE" or name = "camellia-128-ctr" and nid = 963 and - normalized = "CAMELLIA128" and + normalized = "CAMELLIA-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-128-ctr" and nid = 963 and normalized = "CTR" and algType = "BLOCK_MODE" or name = "camellia-128-cmac" and nid = 964 and - normalized = "CAMELLIA128" and + normalized = "CAMELLIA-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-192-gcm" and nid = 965 and - normalized = "CAMELLIA192" and + normalized = "CAMELLIA-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-192-gcm" and nid = 965 and normalized = "GCM" and algType = "BLOCK_MODE" or name = "camellia-192-ccm" and nid = 966 and - normalized = "CAMELLIA192" and + normalized = "CAMELLIA-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-192-ccm" and nid = 966 and normalized = "CCM" and algType = "BLOCK_MODE" or name = "camellia-192-ctr" and nid = 967 and - normalized = "CAMELLIA192" and + normalized = "CAMELLIA-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-192-ctr" and nid = 967 and normalized = "CTR" and algType = "BLOCK_MODE" or name = "camellia-192-cmac" and nid = 968 and - normalized = "CAMELLIA192" and + normalized = "CAMELLIA-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-256-gcm" and nid = 969 and - normalized = "CAMELLIA256" and + normalized = "CAMELLIA-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-256-gcm" and nid = 969 and normalized = "GCM" and algType = "BLOCK_MODE" or name = "camellia-256-ccm" and nid = 970 and - normalized = "CAMELLIA256" and + normalized = "CAMELLIA-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-256-ccm" and nid = 970 and normalized = "CCM" and algType = "BLOCK_MODE" or name = "camellia-256-ctr" and nid = 971 and - normalized = "CAMELLIA256" and + normalized = "CAMELLIA-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "camellia-256-ctr" and nid = 971 and normalized = "CTR" and algType = "BLOCK_MODE" or name = "camellia-256-cmac" and nid = 972 and - normalized = "CAMELLIA256" and + normalized = "CAMELLIA-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "id-scrypt" and nid = 973 and normalized = "SCRYPT" and algType = "KEY_DERIVATION" @@ -1386,27 +1489,45 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "aria-128-ccm" and nid = 1120 and normalized = "CCM" and algType = "BLOCK_MODE" or - name = "aria-128-ccm" and nid = 1120 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-ccm" and + nid = 1120 and + normalized = "ARIA-128" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-192-ccm" and nid = 1121 and normalized = "CCM" and algType = "BLOCK_MODE" or - name = "aria-192-ccm" and nid = 1121 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-ccm" and + nid = 1121 and + normalized = "ARIA-192" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-256-ccm" and nid = 1122 and normalized = "CCM" and algType = "BLOCK_MODE" or - name = "aria-256-ccm" and nid = 1122 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-ccm" and + nid = 1122 and + normalized = "ARIA-256" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-128-gcm" and nid = 1123 and normalized = "GCM" and algType = "BLOCK_MODE" or - name = "aria-128-gcm" and nid = 1123 and normalized = "ARIA128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-128-gcm" and + nid = 1123 and + normalized = "ARIA-128" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-192-gcm" and nid = 1124 and normalized = "GCM" and algType = "BLOCK_MODE" or - name = "aria-192-gcm" and nid = 1124 and normalized = "ARIA192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-192-gcm" and + nid = 1124 and + normalized = "ARIA-192" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aria-256-gcm" and nid = 1125 and normalized = "GCM" and algType = "BLOCK_MODE" or - name = "aria-256-gcm" and nid = 1125 and normalized = "ARIA256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aria-256-gcm" and + nid = 1125 and + normalized = "ARIA-256" and + algType = "SYMMETRIC_ENCRYPTION" or name = "sm4-cfb1" and nid = 1136 and normalized = "SM4" and algType = "SYMMETRIC_ENCRYPTION" or @@ -1505,15 +1626,24 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "magma-mac" and nid = 1192 and normalized = "MAGMA" and algType = "SYMMETRIC_ENCRYPTION" or - name = "aes-128-siv" and nid = 1198 and normalized = "AES128" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-128-siv" and + nid = 1198 and + normalized = "AES-128" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aes-128-siv" and nid = 1198 and normalized = "SIV" and algType = "BLOCK_MODE" or - name = "aes-192-siv" and nid = 1199 and normalized = "AES192" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-192-siv" and + nid = 1199 and + normalized = "AES-192" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aes-192-siv" and nid = 1199 and normalized = "SIV" and algType = "BLOCK_MODE" or - name = "aes-256-siv" and nid = 1200 and normalized = "AES256" and algType = "SYMMETRIC_ENCRYPTION" + name = "aes-256-siv" and + nid = 1200 and + normalized = "AES-256" and + algType = "SYMMETRIC_ENCRYPTION" or name = "aes-256-siv" and nid = 1200 and normalized = "SIV" and algType = "BLOCK_MODE" or @@ -2000,42 +2130,42 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "id-aes128-ccm" and nid = 896 and - normalized = "AES128" and + normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "id-aes128-ccm" and nid = 896 and normalized = "CCM" and algType = "BLOCK_MODE" or name = "id-aes128-gcm" and nid = 895 and - normalized = "AES128" and + normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "id-aes128-gcm" and nid = 895 and normalized = "GCM" and algType = "BLOCK_MODE" or name = "id-aes192-ccm" and nid = 899 and - normalized = "AES192" and + normalized = "AES-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "id-aes192-ccm" and nid = 899 and normalized = "CCM" and algType = "BLOCK_MODE" or name = "id-aes192-gcm" and nid = 898 and - normalized = "AES192" and + normalized = "AES-192" and algType = "SYMMETRIC_ENCRYPTION" or name = "id-aes192-gcm" and nid = 898 and normalized = "GCM" and algType = "BLOCK_MODE" or name = "id-aes256-ccm" and nid = 902 and - normalized = "AES256" and + normalized = "AES-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "id-aes256-ccm" and nid = 902 and normalized = "CCM" and algType = "BLOCK_MODE" or name = "id-aes256-gcm" and nid = 901 and - normalized = "AES256" and + normalized = "AES-256" and algType = "SYMMETRIC_ENCRYPTION" or name = "id-aes256-gcm" and nid = 901 and normalized = "GCM" and algType = "BLOCK_MODE" @@ -2407,27 +2537,36 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "pbe-sha1-rc2-128" and nid = 148 and - normalized = "RC2" and + normalized = "RC2-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "pbe-sha1-rc2-40" and nid = 149 and normalized = "SHA1" and algType = "HASH" or - name = "pbe-sha1-rc2-40" and nid = 149 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" + name = "pbe-sha1-rc2-40" and + nid = 149 and + normalized = "RC2-40" and + algType = "SYMMETRIC_ENCRYPTION" or name = "pbe-sha1-rc2-64" and nid = 68 and normalized = "SHA1" and algType = "HASH" or - name = "pbe-sha1-rc2-64" and nid = 68 and normalized = "RC2" and algType = "SYMMETRIC_ENCRYPTION" + name = "pbe-sha1-rc2-64" and + nid = 68 and + normalized = "RC2-64" and + algType = "SYMMETRIC_ENCRYPTION" or name = "pbe-sha1-rc4-128" and nid = 144 and normalized = "SHA1" and algType = "HASH" or name = "pbe-sha1-rc4-128" and nid = 144 and - normalized = "RC4" and + normalized = "RC4-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "pbe-sha1-rc4-40" and nid = 145 and normalized = "SHA1" and algType = "HASH" or - name = "pbe-sha1-rc4-40" and nid = 145 and normalized = "RC4" and algType = "SYMMETRIC_ENCRYPTION" + name = "pbe-sha1-rc4-40" and + nid = 145 and + normalized = "RC4-40" and + algType = "SYMMETRIC_ENCRYPTION" or name = "pbewithmd2anddes-cbc" and nid = 9 and @@ -2478,7 +2617,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "pbewithsha1and128bitrc2-cbc" and nid = 148 and - normalized = "RC2" and + normalized = "RC2-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "pbewithsha1and128bitrc2-cbc" and @@ -2490,7 +2629,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "pbewithsha1and128bitrc4" and nid = 144 and - normalized = "RC4" and + normalized = "RC4-128" and algType = "SYMMETRIC_ENCRYPTION" or name = "pbewithsha1and2-keytripledes-cbc" and @@ -2505,7 +2644,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "pbewithsha1and2-keytripledes-cbc" and nid = 147 and - normalized = "TRIPLEDES" and + normalized = "3DES" and algType = "SYMMETRIC_ENCRYPTION" or name = "pbewithsha1and3-keytripledes-cbc" and @@ -2520,14 +2659,14 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "pbewithsha1and3-keytripledes-cbc" and nid = 146 and - normalized = "TRIPLEDES" and + normalized = "3DES" and algType = "SYMMETRIC_ENCRYPTION" or name = "pbewithsha1and40bitrc2-cbc" and nid = 149 and normalized = "SHA1" and algType = "HASH" or name = "pbewithsha1and40bitrc2-cbc" and nid = 149 and - normalized = "RC2" and + normalized = "RC2-40" and algType = "SYMMETRIC_ENCRYPTION" or name = "pbewithsha1and40bitrc2-cbc" and @@ -2539,7 +2678,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "pbewithsha1and40bitrc4" and nid = 145 and - normalized = "RC4" and + normalized = "RC4-40" and algType = "SYMMETRIC_ENCRYPTION" or name = "pbewithsha1anddes-cbc" and nid = 170 and normalized = "SHA1" and algType = "HASH" diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstanceBase.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstanceBase.qll new file mode 100644 index 000000000000..6a206773bfb8 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstanceBase.qll @@ -0,0 +1,6 @@ +import experimental.Quantum.Language +import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase + +abstract class OpenSSLAlgorithmInstance extends Crypto::AlgorithmInstance { + abstract OpenSSLAlgorithmValueConsumer getAVC(); +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstances.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstances.qll new file mode 100644 index 000000000000..2a3f136f117a --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstances.qll @@ -0,0 +1,4 @@ +import OpenSSLAlgorithmInstanceBase +import CipherAlgorithmInstance +import PaddingAlgorithmInstance +import BlockAlgorithmInstance diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/PaddingAlgorithmInstance.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/PaddingAlgorithmInstance.qll new file mode 100644 index 000000000000..219289c7da08 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/PaddingAlgorithmInstance.qll @@ -0,0 +1,167 @@ +import cpp +import experimental.Quantum.Language +import OpenSSLAlgorithmInstanceBase +import experimental.Quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants +import AlgToAVCFlow +import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer + +/** + * Given a `KnownOpenSSLPaddingAlgorithmConstant`, converts this to a padding family type. + * Does not bind if there is know mapping (no mapping to 'unknown' or 'other'). + */ +predicate knownOpenSSLConstantToPaddingFamilyType( + KnownOpenSSLPaddingAlgorithmConstant e, Crypto::TPaddingType type +) { + exists(string name | + name = e.getNormalizedName() and + ( + name.matches("OAEP") and type = Crypto::OAEP() + or + name.matches("PSS") and type = Crypto::PSS() + or + name.matches("PKCS7") and type = Crypto::PKCS7() + or + name.matches("PKCS1V15") and type = Crypto::PKCS1_v1_5() + ) + ) +} + +//abstract class OpenSSLPaddingAlgorithmInstance extends OpenSSLAlgorithmInstance, Crypto::PaddingAlgorithmInstance{} +// TODO: need to alter this to include known padding constants which don't have the +// same mechanics as those with known nids +class KnownOpenSSLPaddingConstantAlgorithmInstance extends OpenSSLAlgorithmInstance, + Crypto::PaddingAlgorithmInstance instanceof Expr +{ + OpenSSLAlgorithmValueConsumer getterCall; + boolean isPaddingSpecificConsumer; + + KnownOpenSSLPaddingConstantAlgorithmInstance() { + // three possibilities: + // 1) The source is a 'typical' literal and flows to a getter, then we know we have an instance + // 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that + // 3) the source is a padding-specific literal flowing to a padding-specific consumer + // Possibility 1: + this instanceof Literal and + this instanceof KnownOpenSSLPaddingAlgorithmConstant and + exists(DataFlow::Node src, DataFlow::Node sink | + // Sink is an argument to a CipherGetterCall + sink = getterCall.(OpenSSLAlgorithmValueConsumer).getInputNode() and + // Source is `this` + src.asExpr() = this and + // This traces to a getter + KnownOpenSSLAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink) and + isPaddingSpecificConsumer = false + ) + or + // Possibility 2: + this instanceof DirectAlgorithmValueConsumer and + getterCall = this and + this instanceof KnownOpenSSLPaddingAlgorithmConstant and + isPaddingSpecificConsumer = false + or + // Possibility 3: + // from rsa.h in openssl: + // # define RSA_PKCS1_PADDING 1 + // # define RSA_NO_PADDING 3 + // # define RSA_PKCS1_OAEP_PADDING 4 + // # define RSA_X931_PADDING 5 + // /* EVP_PKEY_ only */ + // # define RSA_PKCS1_PSS_PADDING 6 + // # define RSA_PKCS1_WITH_TLS_PADDING 7 + // /* internal RSA_ only */ + // # define RSA_PKCS1_NO_IMPLICIT_REJECT_PADDING 8 + this instanceof Literal and + this.getValue().toInt() in [0, 1, 3, 4, 5, 6, 7, 8] and + exists(DataFlow::Node src, DataFlow::Node sink | + // Sink is an argument to a CipherGetterCall + sink = getterCall.(OpenSSLAlgorithmValueConsumer).getInputNode() and + // Source is `this` + src.asExpr() = this and + // This traces to a padding-specific consumer + RSAPaddingAlgorithmToPaddingAlgorithmValueConsumerFlow::flow(src, sink) + ) and + isPaddingSpecificConsumer = true + } + + override string getRawPaddingAlgorithmName() { result = this.(Literal).getValue().toString() } + + override OpenSSLAlgorithmValueConsumer getAVC() { result = getterCall } + + override Crypto::TPaddingType getPaddingType() { + isPaddingSpecificConsumer = true and + ( + if this.(Literal).getValue().toInt() in [1, 7, 8] + then result = Crypto::PKCS1_v1_5() + else + if this.(Literal).getValue().toInt() = 3 + then result = Crypto::NoPadding() + else + if this.(Literal).getValue().toInt() = 4 + then result = Crypto::OAEP() + else + if this.(Literal).getValue().toInt() = 5 + then result = Crypto::ANSI_X9_23() + else + if this.(Literal).getValue().toInt() = 6 + then result = Crypto::PSS() + else result = Crypto::OtherPadding() + ) + or + isPaddingSpecificConsumer = false and + knownOpenSSLConstantToPaddingFamilyType(this, result) + } +} + +// // Values used for EVP_PKEY_CTX_set_rsa_padding, these are +// // not the same as 'typical' constants found in the set of known algorithm constants +// // they do not have an NID +// // TODO: what about setting the padding directly? +// class KnownRSAPaddingConstant extends OpenSSLPaddingAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof Literal +// { +// KnownRSAPaddingConstant() { +// // from rsa.h in openssl: +// // # define RSA_PKCS1_PADDING 1 +// // # define RSA_NO_PADDING 3 +// // # define RSA_PKCS1_OAEP_PADDING 4 +// // # define RSA_X931_PADDING 5 +// // /* EVP_PKEY_ only */ +// // # define RSA_PKCS1_PSS_PADDING 6 +// // # define RSA_PKCS1_WITH_TLS_PADDING 7 +// // /* internal RSA_ only */ +// // # define RSA_PKCS1_NO_IMPLICIT_REJECT_PADDING 8 +// this instanceof Literal and +// this.getValue().toInt() in [0, 1, 3, 4, 5, 6, 7, 8] +// // TODO: trace to padding-specific consumers +// RSAPaddingAlgorithmToPaddingAlgorithmValueConsumerFlow +// } +// override string getRawPaddingAlgorithmName() { result = this.(Literal).getValue().toString() } +// override Crypto::TPaddingType getPaddingType() { +// if this.(Literal).getValue().toInt() in [1, 6, 7, 8] +// then result = Crypto::PKCS1_v1_5() +// else +// if this.(Literal).getValue().toInt() = 3 +// then result = Crypto::NoPadding() +// else +// if this.(Literal).getValue().toInt() = 4 +// then result = Crypto::OAEP() +// else +// if this.(Literal).getValue().toInt() = 5 +// then result = Crypto::ANSI_X9_23() +// else result = Crypto::OtherPadding() +// } +// } +class OAEPPaddingAlgorithmInstance extends Crypto::OAEPPaddingAlgorithmInstance, + KnownOpenSSLPaddingConstantAlgorithmInstance +{ + OAEPPaddingAlgorithmInstance() { + this.(Crypto::PaddingAlgorithmInstance).getPaddingType() = Crypto::OAEP() + } + + override Crypto::HashAlgorithmInstance getOAEPEncodingHashAlgorithm() { + none() //TODO + } + + override Crypto::HashAlgorithmInstance getMGF1HashAlgorithm() { + none() //TODO + } +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/CipherAlgorithmValueConsumer.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/CipherAlgorithmValueConsumer.qll new file mode 100644 index 000000000000..19777bc06d1e --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/CipherAlgorithmValueConsumer.qll @@ -0,0 +1,39 @@ +import cpp +import experimental.Quantum.Language +import experimental.Quantum.OpenSSL.LibraryDetector +import experimental.Quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants +import experimental.Quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase +import OpenSSLAlgorithmValueConsumerBase + +abstract class CipherAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { } + +// https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html +class EVPCipherAlgorithmValueConsumer extends CipherAlgorithmValueConsumer { + DataFlow::Node valueArgNode; + DataFlow::Node resultNode; + + EVPCipherAlgorithmValueConsumer() { + resultNode.asExpr() = this and + isPossibleOpenSSLFunction(this.(Call).getTarget()) and + ( + this.(Call).getTarget().getName() in [ + "EVP_get_cipherbyname", "EVP_get_cipherbyobj", "EVP_get_cipherbynid" + ] and + valueArgNode.asExpr() = this.(Call).getArgument(0) + or + this.(Call).getTarget().getName() in ["EVP_CIPHER_fetch", "EVP_ASYM_CIPHER_fetch"] and + valueArgNode.asExpr() = this.(Call).getArgument(1) + ) + } + + override DataFlow::Node getResultNode() { result = resultNode } + + override Crypto::ConsumerInputDataFlowNode getInputNode() { result = valueArgNode } + + // override DataFlow::Node getInputNode() { result = valueArgNode } + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + exists(OpenSSLAlgorithmInstance i | i.getAVC() = this and result = i) + //TODO: As a potential alternative, for OpenSSL only, add a generic source node for literals and only create flow (flowsTo) to + // OpenSSL AVCs... the unknown literal sources would have to be any literals not in the known set. + } +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/DirectAlgorithmValueConsumer.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/DirectAlgorithmValueConsumer.qll new file mode 100644 index 000000000000..cebe7a86a129 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/DirectAlgorithmValueConsumer.qll @@ -0,0 +1,36 @@ +import cpp +import experimental.Quantum.Language +import experimental.Quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants +import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase + +// TODO: can self referential to itself, which is also an algorithm (Known algorithm) +/** + * Cases like EVP_MD5(), + * there is no input, rather it directly gets an algorithm + * and returns it. + */ +class DirectAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { + DataFlow::Node resultNode; + Expr resultExpr; + + DirectAlgorithmValueConsumer() { + this instanceof KnownOpenSSLAlgorithmConstant and + this instanceof Call and + resultExpr = this and + resultNode.asExpr() = resultExpr + } + + /** + * These cases take in no explicit value (the value is implicit) + */ + override Crypto::ConsumerInputDataFlowNode getInputNode() { none() } + + override DataFlow::Node getResultNode() { result = resultNode } + + // override DataFlow::Node getOutputNode() { result = resultNode } + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + // Note: algorithm source definitions enforces that + // this class will be a known algorithm source + result = this + } +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumerBase.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumerBase.qll new file mode 100644 index 000000000000..dddcf14c7134 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumerBase.qll @@ -0,0 +1,9 @@ +import experimental.Quantum.Language +import semmle.code.cpp.dataflow.new.DataFlow + +abstract class OpenSSLAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer instanceof Call { + /** + * Returns the node representing the resulting algorithm + */ + abstract DataFlow::Node getResultNode(); +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumers.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumers.qll new file mode 100644 index 000000000000..46021269d71d --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumers.qll @@ -0,0 +1,4 @@ +import OpenSSLAlgorithmValueConsumerBase +import CipherAlgorithmValueConsumer +import DirectAlgorithmValueConsumer +import PaddingAlgorithmValueConsumer diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/PaddingAlgorithmValueConsumer.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/PaddingAlgorithmValueConsumer.qll new file mode 100644 index 000000000000..009b22cf1b86 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/PaddingAlgorithmValueConsumer.qll @@ -0,0 +1,36 @@ +import cpp +import experimental.Quantum.Language +import experimental.Quantum.OpenSSL.LibraryDetector +import experimental.Quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants +import experimental.Quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase +import OpenSSLAlgorithmValueConsumerBase + +abstract class PaddingAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { } + +// https://docs.openssl.org/master/man7/EVP_ASYM_CIPHER-RSA/#rsa-asymmetric-cipher-parameters +// TODO: need to handle setting padding through EVP_PKEY_CTX_set_params, where modes like "OSSL_PKEY_RSA_PAD_MODE_OAEP" +// are set. +class EVP_PKEY_CTX_set_rsa_padding_AlgorithmValueConsumer extends PaddingAlgorithmValueConsumer { + DataFlow::Node valueArgNode; + DataFlow::Node resultNode; + + EVP_PKEY_CTX_set_rsa_padding_AlgorithmValueConsumer() { + resultNode.asExpr() = this and + isPossibleOpenSSLFunction(this.(Call).getTarget()) and + ( + this.(Call).getTarget().getName() in ["EVP_PKEY_CTX_set_rsa_padding"] and + valueArgNode.asExpr() = this.(Call).getArgument(1) + ) + } + + override DataFlow::Node getResultNode() { result = resultNode } + + override Crypto::ConsumerInputDataFlowNode getInputNode() { result = valueArgNode } + + // override DataFlow::Node getInputNode() { result = valueArgNode } + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + exists(OpenSSLAlgorithmInstance i | i.getAVC() = this and result = i) + //TODO: As a potential alternative, for OpenSSL only, add a generic source node for literals and only create flow (flowsTo) to + // OpenSSL AVCs... the unknown literal sources would have to be any literals not in the known set. + } +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherInitializer.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherInitializer.qll new file mode 100644 index 000000000000..584fd18a64c2 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherInitializer.qll @@ -0,0 +1,123 @@ +/** + * see: https://docs.openssl.org/master/man3/EVP_EncryptInit/ + * Models cipher initialization for EVP cipher operations. + */ + +import experimental.Quantum.Language +import experimental.Quantum.OpenSSL.CtxFlow as CTXFlow + +module EncValToInitEncArgConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr().getValue().toInt() in [0, 1] } + + predicate isSink(DataFlow::Node sink) { + exists(EVP_Cipher_Inititalizer initCall | sink.asExpr() = initCall.getOperataionSubtypeArg()) + } +} + +module EncValToInitEncArgFlow = DataFlow::Global; + +int getEncConfigValue(Expr e) { + exists(EVP_Cipher_Inititalizer initCall | e = initCall.getOperataionSubtypeArg()) and + exists(DataFlow::Node a, DataFlow::Node b | + EncValToInitEncArgFlow::flow(a, b) and b.asExpr() = e and result = a.asExpr().getValue().toInt() + ) +} + +bindingset[i] +Crypto::KeyOperationSubtype intToCipherOperationSubtype(int i) { + if i = 0 + then result instanceof Crypto::TEncryptMode + else + if i = 1 + then result instanceof Crypto::TDecryptMode + else result instanceof Crypto::TUnknownKeyOperationMode +} + +// TODO: need to add key consumer +abstract class EVP_Cipher_Inititalizer extends Call { + Expr getContextArg() { result = this.(Call).getArgument(0) } + + Expr getAlgorithmArg() { result = this.(Call).getArgument(1) } + + abstract Expr getKeyArg(); + + abstract Expr getIVArg(); + + // abstract Crypto::CipherOperationSubtype getCipherOperationSubtype(); + abstract Expr getOperataionSubtypeArg(); + + Crypto::KeyOperationSubtype getCipherOperationSubtype() { + if this.(Call).getTarget().getName().toLowerCase().matches("%encrypt%") + then result instanceof Crypto::TEncryptMode + else + if this.(Call).getTarget().getName().toLowerCase().matches("%decrypt%") + then result instanceof Crypto::TDecryptMode + else + if exists(getEncConfigValue(this.getOperataionSubtypeArg())) + then result = intToCipherOperationSubtype(getEncConfigValue(this.getOperataionSubtypeArg())) + else result instanceof Crypto::TUnknownKeyOperationMode + } +} + +abstract class EVP_EX_Initializer extends EVP_Cipher_Inititalizer { + override Expr getKeyArg() { result = this.(Call).getArgument(3) } + + override Expr getIVArg() { result = this.(Call).getArgument(4) } +} + +abstract class EVP_EX2_Initializer extends EVP_Cipher_Inititalizer { + override Expr getKeyArg() { result = this.(Call).getArgument(2) } + + override Expr getIVArg() { result = this.(Call).getArgument(3) } +} + +class EVP_Cipher_EX_Init_Call extends EVP_EX_Initializer { + EVP_Cipher_EX_Init_Call() { + this.(Call).getTarget().getName() in [ + "EVP_EncryptInit_ex", "EVP_DecryptInit_ex", "EVP_CipherInit_ex" + ] + } + + override Expr getOperataionSubtypeArg() { + this.(Call).getTarget().getName().toLowerCase().matches("%cipherinit%") and + result = this.(Call).getArgument(5) + } +} + +class EVP_Cipher_EX2_or_Simple_Init_Call extends EVP_EX2_Initializer { + EVP_Cipher_EX2_or_Simple_Init_Call() { + this.(Call).getTarget().getName() in [ + "EVP_EncryptInit_ex2", "EVP_DecryptInit_ex2", "EVP_CipherInit_ex2", "EVP_EncryptInit", + "EVP_DecryptInit", "EVP_CipherInit" + ] + } + + override Expr getOperataionSubtypeArg() { + this.(Call).getTarget().getName().toLowerCase().matches("%cipherinit%") and + result = this.(Call).getArgument(4) + } +} + +class EVP_CipherInit_SKEY_Call extends EVP_EX2_Initializer { + EVP_CipherInit_SKEY_Call() { this.(Call).getTarget().getName() in ["EVP_CipherInit_SKEY"] } + + override Expr getOperataionSubtypeArg() { result = this.(Call).getArgument(5) } +} + +class EVPCipherInitializerAlgorithmArgument extends Expr { + EVPCipherInitializerAlgorithmArgument() { + exists(EVP_Cipher_Inititalizer initCall | this = initCall.getAlgorithmArg()) + } +} + +class EVPCipherInitializerKeyArgument extends Expr { + EVPCipherInitializerKeyArgument() { + exists(EVP_Cipher_Inititalizer initCall | this = initCall.getKeyArg()) + } +} + +class EVPCipherInitializerIVArgument extends Expr { + EVPCipherInitializerIVArgument() { + exists(EVP_Cipher_Inititalizer initCall | this = initCall.getIVArg()) + } +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherOperation.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherOperation.qll new file mode 100644 index 000000000000..56288e6acb75 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherOperation.qll @@ -0,0 +1,114 @@ +import experimental.Quantum.Language +import experimental.Quantum.OpenSSL.CtxFlow as CTXFlow +import EVPCipherInitializer +import OpenSSLOperationBase +import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers + +// import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.AlgorithmValueConsumers +// import OpenSSLOperation +module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + exists(OpenSSLAlgorithmValueConsumer c | c.getResultNode() = source) + } + + predicate isSink(DataFlow::Node sink) { + exists(EVP_Cipher_Operation c | c.getInitCall().getAlgorithmArg() = sink.asExpr()) + } +} + +module AlgGetterToAlgConsumerFlow = DataFlow::Global; + +// class EVPCipherOutput extends CipherOutputArtifact { +// EVPCipherOutput() { exists(EVP_Cipher_Operation op | op.getOutputArg() = this) } +// override DataFlow::Node getOutputNode() { result.asDefiningArgument() = this } +// } +// +/** + * see: https://docs.openssl.org/master/man3/EVP_EncryptInit/#synopsis + * Base configuration for all EVP cipher operations. + * NOTE: cannot extend instance of OpenSSLOperation, as we need to override + * elements of OpenSSLOperation (i.e., we are creating an instance) + */ +abstract class EVP_Cipher_Operation extends OpenSSLOperation, Crypto::KeyOperationInstance { + Expr getContextArg() { result = this.(Call).getArgument(0) } + + override Expr getOutputArg() { result = this.(Call).getArgument(1) } + + override Crypto::KeyOperationSubtype getKeyOperationSubtype() { + result instanceof Crypto::TEncryptMode and + this.(Call).getTarget().getName().toLowerCase().matches("%encrypt%") + or + result instanceof Crypto::TDecryptMode and + this.(Call).getTarget().getName().toLowerCase().matches("%decrypt%") + or + result = this.getInitCall().getCipherOperationSubtype() and + this.(Call).getTarget().getName().toLowerCase().matches("%cipher%") + } + + EVP_Cipher_Inititalizer getInitCall() { + CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg()) + } + + override Crypto::ConsumerInputDataFlowNode getNonceConsumer() { + this.getInitCall().getIVArg() = result.asExpr() + } + + override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() } + + override Crypto::ConsumerInputDataFlowNode getKeyConsumer() { + this.getInitCall().getKeyArg() = result.asExpr() + } + + override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { result = this.getOutputNode() } + + override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { + AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(), + DataFlow::exprNode(this.getInitCall().getAlgorithmArg())) + } +} + +// abstract class EVP_Update_Call extends EVP_Cipher_Operation { } +abstract class EVP_Final_Call extends EVP_Cipher_Operation { + override Expr getInputArg() { none() } +} + +// TODO: only model Final (model final as operation and model update but not as an operation) +// Updates are multiple input consumers (most important) +// PUNT assuming update doesn't ouput, otherwise it outputs arifacts, but is not an operation +class EVP_Cipher_Call extends EVP_Cipher_Operation { + EVP_Cipher_Call() { this.(Call).getTarget().getName() = "EVP_Cipher" } + + override Expr getInputArg() { result = this.(Call).getArgument(2) } +} + +// class EVP_Encrypt_Decrypt_or_Cipher_Update_Call extends EVP_Update_Call { +// EVP_Encrypt_Decrypt_or_Cipher_Update_Call() { +// this.(Call).getTarget().getName() in [ +// "EVP_EncryptUpdate", "EVP_DecryptUpdate", "EVP_CipherUpdate" +// ] +// } +// override Expr getInputArg() { result = this.(Call).getArgument(3) } +// } +class EVP_Encrypt_Decrypt_or_Cipher_Final_Call extends EVP_Final_Call { + EVP_Encrypt_Decrypt_or_Cipher_Final_Call() { + this.(Call).getTarget().getName() in [ + "EVP_EncryptFinal_ex", "EVP_DecryptFinal_ex", "EVP_CipherFinal_ex", "EVP_EncryptFinal", + "EVP_DecryptFinal", "EVP_CipherFinal" + ] + } +} + +class EVP_PKEY_Operation extends EVP_Cipher_Operation { + EVP_PKEY_Operation() { + this.(Call).getTarget().getName() in ["EVP_PKEY_decrypt", "EVP_PKEY_encrypt"] + } + + override Expr getInputArg() { result = this.(Call).getArgument(3) } + // TODO: how PKEY is initialized is different that symmetric cipher + // Consider making an entirely new class for this and specializing + // the get init call +} + +class EVPCipherInputArgument extends Expr { + EVPCipherInputArgument() { exists(EVP_Cipher_Operation op | op.getInputArg() = this) } +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperationBase.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperationBase.qll new file mode 100644 index 000000000000..851d7a4b7e99 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperationBase.qll @@ -0,0 +1,21 @@ +import experimental.Quantum.Language + +abstract class OpenSSLOperation extends Crypto::OperationInstance instanceof Call { + abstract Expr getInputArg(); + + /** + * Can be an argument of a call or a return value of a function. + */ + abstract Expr getOutputArg(); + + DataFlow::Node getInputNode() { + // Assumed to be default to asExpr + result.asExpr() = this.getInputArg() + } + + DataFlow::Node getOutputNode() { + if exists(Call c | c.getAnArgument() = this) + then result.asDefiningArgument() = this + else result.asExpr() = this + } +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperations.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperations.qll new file mode 100644 index 000000000000..76a60b064e55 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperations.qll @@ -0,0 +1 @@ +import EVPCipherOperation From 94632931ba08b3cac96882de1d1e2aa315ffd69d Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Fri, 2 May 2025 14:11:10 -0400 Subject: [PATCH 251/336] Clean up --- .../OpenSSL/OpenSSLAlgorithmGetter.qll | 495 ------------------ 1 file changed, 495 deletions(-) delete mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll deleted file mode 100644 index b436f3b412a8..000000000000 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll +++ /dev/null @@ -1,495 +0,0 @@ - -// import cpp -// import semmle.code.cpp.dataflow.new.DataFlow -// import LibraryDetector -// import OpenSSLKnownAlgorithmConstants -// import experimental.Quantum.Language -// class OpenSSLAlgorithmAdditionalFlowStep extends AdditionalFlowInputStep { -// OpenSSLAlgorithmAdditionalFlowStep() { exists(AlgorithmPassthroughCall c | c.getInNode() = this) } -// override DataFlow::Node getOutput() { -// exists(AlgorithmPassthroughCall c | c.getInNode() = this and c.getOutNode() = result) -// } -// } -// module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig { -// predicate isSource(DataFlow::Node source) { -// exists(OpenSSLAlgorithmGetterCall c | c.getResultNode() = source) -// } -// predicate isSink(DataFlow::Node sink) { -// exists(Crypto::AlgorithmConsumer c | c.getInputNode() = sink) -// } -// } -// module AlgGetterToAlgConsumerFlow = DataFlow::Global; -// abstract class AlgorithmPassthroughCall extends Call { -// abstract DataFlow::Node getInNode(); -// abstract DataFlow::Node getOutNode(); -// } -// class CopyAndDupAlgorithmPassthroughCall extends AlgorithmPassthroughCall { -// DataFlow::Node inNode; -// DataFlow::Node outNode; -// CopyAndDupAlgorithmPassthroughCall() { -// // Flow out through any return or other argument of the same type -// // Assume flow in and out is asIndirectExpr or asDefinitingArgument since a pointer is assumed -// // to be involved -// // NOTE: not attempting to detect openssl specific copy/dup functions, but anything suspected to be copy/dup -// this.getTarget().getName().toLowerCase().matches(["%_dup%", "%_copy%"]) and -// exists(Expr inArg, Type t | -// inArg = this.getAnArgument() and t = inArg.getUnspecifiedType().stripType() -// | -// inNode.asIndirectExpr() = inArg and -// ( -// // Case 1: flow through another argument as an out arg of the same type -// exists(Expr outArg | -// outArg = this.getAnArgument() and -// outArg != inArg and -// outArg.getUnspecifiedType().stripType() = t -// | -// outNode.asDefiningArgument() = outArg -// ) -// or -// // Case 2: flow through the return value if the result is the same as the intput type -// exists(Expr outArg | outArg = this and outArg.getUnspecifiedType().stripType() = t | -// outNode.asIndirectExpr() = outArg -// ) -// ) -// ) -// } -// override DataFlow::Node getInNode() { result = inNode } -// override DataFlow::Node getOutNode() { result = outNode } -// } -// class NIDToPointerPassthroughCall extends AlgorithmPassthroughCall { -// DataFlow::Node inNode; -// DataFlow::Node outNode; -// NIDToPointerPassthroughCall() { -// this.getTarget().getName() in ["OBJ_nid2obj", "OBJ_nid2ln", "OBJ_nid2sn"] and -// inNode.asExpr() = this.getArgument(0) and -// outNode.asExpr() = this -// //outNode.asIndirectExpr() = this -// } -// override DataFlow::Node getInNode() { result = inNode } -// override DataFlow::Node getOutNode() { result = outNode } -// } -// class PointerToPointerPassthroughCall extends AlgorithmPassthroughCall { -// DataFlow::Node inNode; -// DataFlow::Node outNode; -// PointerToPointerPassthroughCall() { -// this.getTarget().getName() = "OBJ_txt2obj" and -// inNode.asIndirectExpr() = this.getArgument(0) and -// outNode.asIndirectExpr() = this -// or -// //outNode.asExpr() = this -// this.getTarget().getName() in ["OBJ_obj2txt", "i2t_ASN1_OBJECT"] and -// inNode.asIndirectExpr() = this.getArgument(2) and -// outNode.asDefiningArgument() = this.getArgument(0) -// } -// override DataFlow::Node getInNode() { result = inNode } -// override DataFlow::Node getOutNode() { result = outNode } -// } -// class PointerToNIDPassthroughCall extends AlgorithmPassthroughCall { -// DataFlow::Node inNode; -// DataFlow::Node outNode; -// PointerToNIDPassthroughCall() { -// this.getTarget().getName() in ["OBJ_obj2nid", "OBJ_ln2nid", "OBJ_sn2nid", "OBJ_txt2nid"] and -// ( -// inNode.asIndirectExpr() = this.getArgument(0) -// or -// inNode.asExpr() = this.getArgument(0) -// ) and -// outNode.asExpr() = this -// } -// override DataFlow::Node getInNode() { result = inNode } -// override DataFlow::Node getOutNode() { result = outNode } -// } -// predicate knownPassThroughStep(DataFlow::Node node1, DataFlow::Node node2) { -// exists(AlgorithmPassthroughCall c | c.getInNode() = node1 and c.getOutNode() = node2) -// } -// abstract class OpenSSLAlgorithmGetterCall extends Call { -// abstract DataFlow::Node getValueArgNode(); -// abstract DataFlow::Node getResultNode(); -// abstract Expr getValueArgExpr(); -// abstract Expr getResultExpr(); -// } -// module KnownOpenSSLAlgorithmToAlgorithmGetterConfig implements DataFlow::ConfigSig { -// predicate isSource(DataFlow::Node source) { -// source.asExpr() instanceof KnownOpenSSLAlgorithmConstant -// } -// predicate isSink(DataFlow::Node sink) { -// exists(OpenSSLAlgorithmGetterCall c | c.getValueArgNode() = sink) -// } -// predicate isBarrier(DataFlow::Node node) { -// // False positive reducer, don't flow out through argv -// exists(VariableAccess va, Variable v | -// v.getAnAccess() = va and va = node.asExpr() -// or -// va = node.asIndirectExpr() -// | -// v.getName().matches("%argv") -// ) -// } -// predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { -// knownPassThroughStep(node1, node2) -// } -// } -// module KnownOpenSSLAlgorithmToAlgorithmGetterFlow = -// DataFlow::Global; -// /** -// * Cases like EVP_MD5(), -// * there is no input, rather it directly gets an algorithm -// * and returns it. -// */ -// class DirectGetterCall extends OpenSSLAlgorithmGetterCall { -// DataFlow::Node resultNode; -// Expr resultExpr; -// DirectGetterCall() { -// this instanceof KnownOpenSSLAlgorithmConstant and -// this instanceof Call and -// resultExpr = this and -// resultNode.asExpr() = resultExpr -// } -// override DataFlow::Node getValueArgNode() { none() } -// override DataFlow::Node getResultNode() { result = resultNode } -// override Expr getValueArgExpr() { none() } -// override Expr getResultExpr() { result = resultExpr } -// } -// // https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html -// class EVPCipherGetterCall extends OpenSSLAlgorithmGetterCall { -// DataFlow::Node valueArgNode; -// DataFlow::Node resultNode; -// Expr valueArgExpr; -// Expr resultExpr; -// EVPCipherGetterCall() { -// resultExpr = this and -// resultNode.asExpr() = this and -// isPossibleOpenSSLFunction(this.getTarget()) and -// ( -// this.getTarget().getName() in ["EVP_get_cipherbyname", "EVP_get_cipherbyobj"] and -// valueArgExpr = this.getArgument(0) and -// valueArgNode.asExpr() = valueArgExpr -// or -// this.getTarget().getName() = "EVP_CIPHER_fetch" and -// valueArgExpr = this.getArgument(1) and -// valueArgNode.asExpr() = valueArgExpr -// or -// this.getTarget().getName() = "EVP_get_cipherbynid" and -// valueArgExpr = this.getArgument(0) and -// valueArgNode.asExpr() = valueArgExpr -// ) -// } -// override DataFlow::Node getValueArgNode() { result = valueArgNode } -// override DataFlow::Node getResultNode() { result = resultNode } -// override Expr getValueArgExpr() { result = valueArgExpr } -// override Expr getResultExpr() { result = resultExpr } -// } -// class EVPAsymCipherGetterCall extends OpenSSLAlgorithmGetterCall { -// DataFlow::Node valueArgNode; -// DataFlow::Node resultNode; -// Expr valueArgExpr; -// Expr resultExpr; -// EVPAsymCipherGetterCall() { -// isPossibleOpenSSLFunction(this.getTarget()) and -// resultExpr = this and -// resultNode.asExpr() = this and -// this.getTarget().getName() = "EVP_ASYM_CIPHER_fetch" and -// valueArgExpr = this.getArgument(1) and -// valueArgNode.asExpr() = valueArgExpr -// } -// override DataFlow::Node getValueArgNode() { result = valueArgNode } -// override DataFlow::Node getResultNode() { result = resultNode } -// override Expr getValueArgExpr() { result = valueArgExpr } -// override Expr getResultExpr() { result = resultExpr } -// } -// class EVPDigestGetterCall extends OpenSSLAlgorithmGetterCall { -// DataFlow::Node valueArgNode; -// DataFlow::Node resultNode; -// Expr valueArgExpr; -// Expr resultExpr; -// EVPDigestGetterCall() { -// resultExpr = this and -// resultNode.asExpr() = this and -// isPossibleOpenSSLFunction(this.getTarget()) and -// ( -// this.getTarget().getName() in [ -// "EVP_get_digestbyname", "EVP_get_digestbyobj", "EVP_get_digestbynid" -// ] and -// valueArgExpr = this.getArgument(0) and -// valueArgNode.asExpr() = valueArgExpr -// or -// this.getTarget().getName() = "EVP_MD_fetch" and -// valueArgExpr = this.getArgument(1) and -// valueArgNode.asExpr() = valueArgExpr -// ) -// } -// override DataFlow::Node getValueArgNode() { result = valueArgNode } -// override DataFlow::Node getResultNode() { result = resultNode } -// override Expr getValueArgExpr() { result = valueArgExpr } -// override Expr getResultExpr() { result = resultExpr } -// } -// class EVPKDFFetch extends OpenSSLAlgorithmGetterCall { -// DataFlow::Node valueArgNode; -// DataFlow::Node resultNode; -// Expr valueArgExpr; -// Expr resultExpr; -// EVPKDFFetch() { -// resultExpr = this and -// resultNode.asExpr() = this and -// isPossibleOpenSSLFunction(this.getTarget()) and -// this.getTarget().getName() in ["EVP_KDF_fetch"] and -// valueArgExpr = this.getArgument(1) and -// valueArgNode.asExpr() = valueArgExpr -// } -// override DataFlow::Node getValueArgNode() { result = valueArgNode } -// override DataFlow::Node getResultNode() { result = resultNode } -// override Expr getValueArgExpr() { result = valueArgExpr } -// override Expr getResultExpr() { result = resultExpr } -// } -// // /** -// // * Predicates/classes for identifying algorithm sinks. -// // * An Algorithm Sink is a function that takes an algorithm as an argument. -// // * In particular, any function that takes in an algorithm that until the call -// // * the algorithm is not definitely known to be an algorithm (e.g., an integer used as an identifier to fetch an algorithm) -// // */ -// // //TODO: enforce a hierarchy of AlgorithmSinkArgument, e.g., so I can get all Asymmetric SinkArguments that includes all the strictly RSA etc. -// // import cpp -// // // import experimental.cryptography.utils.OpenSSL.LibraryFunction -// // // import experimental.cryptography.CryptoAlgorithmNames -// // predicate isAlgorithmSink(AlgorithmSinkArgument arg, string algType) { arg.algType() = algType } -// // abstract class AlgorithmSinkArgument extends Expr { -// // AlgorithmSinkArgument() { -// // exists(Call c | c.getAnArgument() = this and openSSLLibraryFunc(c.getTarget())) -// // } -// // /** -// // * Gets the function call in which the argument exists -// // */ -// // Call getSinkCall() { result.getAnArgument() = this } -// // abstract string algType(); -// // } -// // // https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html -// // predicate cipherAlgorithmSink(string funcName, int argInd) { -// // funcName in ["EVP_get_cipherbyname", "EVP_get_cipherbynid", "EVP_get_cipherbyobj"] and argInd = 0 -// // or -// // funcName = "EVP_CIPHER_fetch" and argInd = 1 -// // } -// // class CipherAlgorithmSink extends AlgorithmSinkArgument { -// // CipherAlgorithmSink() { -// // exists(Call c, string funcName, int argInd | -// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// // | -// // cipherAlgorithmSink(funcName, argInd) -// // ) -// // } -// // override string algType() { result = getSymmetricEncryptionType() } -// // } -// // // https://www.openssl.org/docs/manmaster/man3/EVP_MAC_fetch -// // predicate macAlgorithmSink(string funcName, int argInd) { -// // (funcName = "EVP_MAC_fetch" and argInd = 1) -// // } -// // class MACAlgorithmSink extends AlgorithmSinkArgument { -// // MACAlgorithmSink() { -// // exists(Call c, string funcName, int argInd | -// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// // | -// // macAlgorithmSink(funcName, argInd) -// // ) -// // } -// // override string algType() { result = "TBD" } -// // } -// // // https://www.openssl.org/docs/manmaster/man3/EVP_MD_fetch -// // predicate messageDigestAlgorithmSink(string funcName, int argInd) { -// // funcName in ["EVP_get_digestbyname", "EVP_get_digestbynid", "EVP_get_digestbyobj"] and argInd = 0 -// // or -// // funcName = "EVP_MD_fetch" and argInd = 1 -// // } -// // class MessageDigestAlgorithmSink extends AlgorithmSinkArgument { -// // MessageDigestAlgorithmSink() { -// // exists(Call c, string funcName, int argInd | -// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// // | -// // messageDigestAlgorithmSink(funcName, argInd) -// // ) -// // } -// // override string algType() { result = getHashType() } -// // } -// // // https://www.openssl.org/docs/manmaster/man3/EVP_KEYEXCH_fetch -// // // https://www.openssl.org/docs/manmaster/man3/EVP_KEM_fetch -// // predicate keyExchangeAlgorithmSink(string funcName, int argInd) { -// // funcName = "EVP_KEYEXCH_fetch" and argInd = 1 -// // or -// // funcName = "EVP_KEM_fetch" and argInd = 1 -// // } -// // class KeyExchangeAlgorithmSink extends AlgorithmSinkArgument { -// // KeyExchangeAlgorithmSink() { -// // exists(Call c, string funcName, int argInd | -// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// // | -// // keyExchangeAlgorithmSink(funcName, argInd) -// // ) -// // } -// // override string algType() { result = getKeyExchangeType() } -// // } -// // // https://www.openssl.org/docs/manmaster/man3/EVP_KEYMGMT_fetch -// // predicate keyManagementAlgorithmSink(string funcName, int argInd) { -// // funcName = "EVP_KEYMGMT_fetch" and argInd = 1 -// // } -// // class KeyManagementAlgorithmSink extends AlgorithmSinkArgument { -// // KeyManagementAlgorithmSink() { -// // exists(Call c, string funcName, int argInd | -// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// // | -// // keyManagementAlgorithmSink(funcName, argInd) -// // ) -// // } -// // override string algType() { result = "TBD" } -// // } -// // // https://www.openssl.org/docs/manmaster/man3/EVP_KDF -// // predicate keyDerivationAlgorithmSink(string funcName, int argInd) { -// // funcName = "EVP_KDF_fetch" and argInd = 1 -// // } -// // class KeyDerivationAlgorithmSink extends AlgorithmSinkArgument { -// // KeyDerivationAlgorithmSink() { -// // exists(Call c, string funcName, int argInd | -// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// // | -// // keyDerivationAlgorithmSink(funcName, argInd) -// // ) -// // } -// // override string algType() { result = getKeyDerivationType() } -// // } -// // // https://www.openssl.org/docs/manmaster/man3/EVP_ASYM_CIPHER_fetch -// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_new_id -// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_new_CMAC_key.html -// // predicate asymmetricCipherAlgorithmSink(string funcName, int argInd) { -// // funcName = "EVP_ASYM_CIPHER_fetch" and argInd = 1 -// // or -// // funcName = "EVP_PKEY_new_CMAC_key" and argInd = 3 -// // // NOTE: other cases are handled by AsymmetricAlgorithmSink -// // } -// // class AsymmetricCipherAlgorithmSink extends AlgorithmSinkArgument { -// // AsymmetricCipherAlgorithmSink() { -// // exists(Call c, string funcName, int argInd | -// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// // | -// // asymmetricCipherAlgorithmSink(funcName, argInd) -// // ) -// // } -// // override string algType() { result = "ASYMMETRIC_ENCRYPTION" } -// // } -// // class AsymmetricCipherAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument { -// // AsymmetricCipherAlgorithmSink_EVP_PKEY_Q_keygen() { -// // exists(Call c, string funcName | -// // funcName = c.getTarget().getName() and -// // this = c.getArgument(3) -// // | -// // funcName = "EVP_PKEY_Q_keygen" and -// // c.getArgument(3).getType().getUnderlyingType() instanceof IntegralType -// // ) -// // } -// // override string algType() { result = "ASYMMETRIC_ENCRYPTION" } -// // } -// // // https://www.openssl.org/docs/manmaster/man3/EVP_RAND_fetch -// // predicate randomAlgorithmSink(string funcName, int argInd) { -// // funcName = "EVP_RAND_fetch" and argInd = 1 -// // } -// // class RandomAlgorithmSink extends AlgorithmSinkArgument { -// // RandomAlgorithmSink() { -// // exists(Call c, string funcName, int argInd | -// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// // | -// // randomAlgorithmSink(funcName, argInd) -// // ) -// // } -// // override string algType() { result = "TBD" } -// // } -// // // https://www.openssl.org/docs/manmaster/man3/EVP_SIGNATURE_fetch -// // predicate signatureAlgorithmSink(string funcName, int argInd) { -// // funcName = "EVP_SIGNATURE_fetch" and argInd = 1 -// // } -// // class SignatureAlgorithmSink extends AlgorithmSinkArgument { -// // SignatureAlgorithmSink() { -// // exists(Call c, string funcName, int argInd | -// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// // | -// // signatureAlgorithmSink(funcName, argInd) -// // ) -// // } -// // override string algType() { result = getSignatureType() } -// // } -// // // https://www.openssl.org/docs/manmaster/man3/EC_KEY_new_by_curve_name.html -// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_ec_paramgen_curve_nid.html -// // predicate ellipticCurveAlgorithmSink(string funcName, int argInd) { -// // funcName in ["EC_KEY_new_by_curve_name", "EVP_EC_gen"] and argInd = 0 -// // or -// // funcName = "EC_KEY_new_by_curve_name_ex" and argInd = 2 -// // or -// // funcName in ["EVP_PKEY_CTX_set_ec_paramgen_curve_nid"] and argInd = 1 -// // } -// // class EllipticCurveAlgorithmSink extends AlgorithmSinkArgument { -// // EllipticCurveAlgorithmSink() { -// // exists(Call c, string funcName, int argInd | -// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// // | -// // ellipticCurveAlgorithmSink(funcName, argInd) -// // ) -// // } -// // override string algType() { result = getEllipticCurveType() } -// // } -// // /** -// // * Special cased to address the fact that arg index 3 (zero offset based) is the curve name. -// // * ASSUMPTION: if the arg ind 3 is a char* assume it is an elliptic curve -// // */ -// // class EllipticCurveAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument { -// // EllipticCurveAlgorithmSink_EVP_PKEY_Q_keygen() { -// // exists(Call c, string funcName | -// // funcName = c.getTarget().getName() and -// // this = c.getArgument(3) -// // | -// // funcName = "EVP_PKEY_Q_keygen" and -// // c.getArgument(3).getType().getUnderlyingType() instanceof PointerType and -// // c.getArgument(3).getType().getUnderlyingType().stripType() instanceof CharType -// // ) -// // } -// // override string algType() { result = getEllipticCurveType() } -// // } -// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_new_id.html -// // // https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_new_raw_private_key.html -// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_new.html -// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_ctrl.html -// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_Q_keygen.html -// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_ctrl.html -// // predicate asymmetricAlgorithmSink(string funcName, int argInd) { -// // funcName = "EVP_PKEY_CTX_new_id" and argInd = 0 -// // or -// // funcName = "EVP_PKEY_CTX_new_from_name" and argInd = 1 -// // or -// // funcName in [ -// // "EVP_PKEY_new_raw_private_key", "EVP_PKEY_new_raw_public_key", "EVP_PKEY_new_mac_key" -// // ] and -// // argInd = 0 -// // or -// // funcName in ["EVP_PKEY_new_raw_private_key_ex", "EVP_PKEY_new_raw_public_key_ex"] and argInd = 1 -// // or -// // // special casing this as arg index 3 must be specified depending on if RSA or ECC, and otherwise not specified for other algs -// // // funcName = "EVP_PKEY_Q_keygen" and argInd = 2 -// // funcName in ["EVP_PKEY_CTX_ctrl", "EVP_PKEY_CTX_set_group_name"] and argInd = 1 -// // // TODO consider void cases EVP_PKEY_new -// // } -// // class AsymmetricAlgorithmSink extends AlgorithmSinkArgument { -// // AsymmetricAlgorithmSink() { -// // exists(Call c, string funcName, int argInd | -// // funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// // | -// // asymmetricAlgorithmSink(funcName, argInd) -// // ) -// // } -// // override string algType() { result = getAsymmetricType() } -// // } -// // class AsymmetricAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument { -// // AsymmetricAlgorithmSink_EVP_PKEY_Q_keygen() { -// // exists(Call c, string funcName | -// // funcName = c.getTarget().getName() and -// // this = c.getArgument(2) -// // | -// // funcName = "EVP_PKEY_Q_keygen" and -// // not exists(c.getArgument(3)) -// // ) -// // } -// // override string algType() { result = getAsymmetricType() } -// // } From 0a0be41527ac3cbbdfa09d2ccb1722ed840b9696 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Fri, 2 May 2025 16:33:52 -0400 Subject: [PATCH 252/336] Intermediate progress towards getting hashing upgraded. Still need to handle the final and update mechanics, matching the JCA. Similarly need to update cipher to follow the JCA for update/final as well. --- .../OpenSSLAlgorithmInstances.qll | 1 + .../OpenSSLAlgorithmValueConsumers.qll | 1 + .../Quantum/OpenSSL/EVPCipherConsumers.qll | 25 ------ .../OpenSSL/EVPHashAlgorithmSource.qll | 81 ------------------ .../Quantum/OpenSSL/EVPHashConsumers.qll | 30 ------- .../Quantum/OpenSSL/EVPHashInitializer.qll | 25 ------ .../Quantum/OpenSSL/EVPHashOperation.qll | 83 ------------------- .../OpenSSL/Operations/EVPCipherOperation.qll | 10 ++- .../OpenSSL/Operations/OpenSSLOperations.qll | 2 + java/ql/lib/experimental/Quantum/JCA.qll | 6 +- .../codeql/cryptography/Model.qll | 27 +++++- 11 files changed, 37 insertions(+), 254 deletions(-) delete mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll delete mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll delete mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll delete mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashInitializer.qll delete mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashOperation.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstances.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstances.qll index 2a3f136f117a..7a77a4c3e13e 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstances.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstances.qll @@ -2,3 +2,4 @@ import OpenSSLAlgorithmInstanceBase import CipherAlgorithmInstance import PaddingAlgorithmInstance import BlockAlgorithmInstance +import HashAlgorithmInstance diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumers.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumers.qll index 46021269d71d..0638595afb88 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumers.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumers.qll @@ -2,3 +2,4 @@ import OpenSSLAlgorithmValueConsumerBase import CipherAlgorithmValueConsumer import DirectAlgorithmValueConsumer import PaddingAlgorithmValueConsumer +import HashAlgorithmValueConsumer diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll deleted file mode 100644 index e2f5bc0e8380..000000000000 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll +++ /dev/null @@ -1,25 +0,0 @@ -import EVPCipherInitializer -import EVPCipherOperation -import EVPCipherAlgorithmSource - -class EVP_Cipher_Initializer_Algorithm_Consumer extends Crypto::AlgorithmConsumer instanceof EVPCipherInitializerAlgorithmArgument -{ - override DataFlow::Node getInputNode() { result.asExpr() = this } - - override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { - result.(KnownOpenSSLCipherConstantAlgorithmInstance).getConsumer() = this - } -} - -// //TODO: need a key consumer -// class EVP_Initializer_Key_Consumer extends Crypto::KeyConsumer instanceof EVP_Cipher_Inititalizer isntanceof InitializerKeyArgument{ -// } -class EVP_Cipher_Initializer_IV_Consumer extends Crypto::NonceArtifactConsumer instanceof EVPCipherInitializerIVArgument -{ - override DataFlow::Node getInputNode() { result.asExpr() = this } -} - -class EVP_Cipher_Input_Consumer extends Crypto::CipherInputConsumer instanceof EVPCipherInputArgument -{ - override DataFlow::Node getInputNode() { result.asExpr() = this } -} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll deleted file mode 100644 index d269658c8aab..000000000000 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashAlgorithmSource.qll +++ /dev/null @@ -1,81 +0,0 @@ -import cpp -import experimental.Quantum.Language -import OpenSSLAlgorithmGetter - -predicate knownOpenSSLConstantToHashFamilyType(KnownOpenSSLAlgorithmConstant e, Crypto::THashType type) { - exists(string name | e.getAlgType().toLowerCase().matches("hash") | - name = e.getNormalizedName() and - ( - name.matches("BLAKE2B") and type instanceof Crypto::BLAKE2B - or - name.matches("BLAKE2S") and type instanceof Crypto::BLAKE2S - or - name.matches("GOST%") and type instanceof Crypto::GOSTHash - or - name.matches("MD2") and type instanceof Crypto::MD2 - or - name.matches("MD4") and type instanceof Crypto::MD4 - or - name.matches("MD5") and type instanceof Crypto::MD5 - or - name.matches("MDC2") and type instanceof Crypto::MDC2 - or - name.matches("POLY1305") and type instanceof Crypto::POLY1305 - or - name.matches(["SHA", "SHA1"]) and type instanceof Crypto::SHA1 - or - name.matches("SHA+%") and not name.matches(["SHA1", "SHA3-"]) and type instanceof Crypto::SHA2 - or - name.matches("SHA3-%") and type instanceof Crypto::SHA3 - or - name.matches(["SHAKE"]) and type instanceof Crypto::SHAKE - or - name.matches("SM3") and type instanceof Crypto::SM3 - or - name.matches("RIPEMD160") and type instanceof Crypto::RIPEMD160 - or - name.matches("WHIRLPOOL") and type instanceof Crypto::WHIRLPOOL - ) - ) -} - -class KnownOpenSSLHashConstantAlgorithmInstance extends Crypto::HashAlgorithmInstance instanceof KnownOpenSSLAlgorithmConstant -{ - OpenSSLAlgorithmGetterCall getterCall; - - KnownOpenSSLHashConstantAlgorithmInstance() { - // Not just any known value, but specifically a known hash - this.(KnownOpenSSLAlgorithmConstant).getAlgType().toLowerCase().matches("hash") and - ( - // Two possibilities: - // 1) The source is a literal and flows to a getter, then we know we have an instance - // 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that - // Possibility 1: - this instanceof Literal and - exists(DataFlow::Node src, DataFlow::Node sink | - // Sink is an argument to a CipherGetterCall - sink = getterCall.(OpenSSLAlgorithmGetterCall).getValueArgNode() and - // Source is `this` - src.asExpr() = this and - // This traces to a getter - KnownOpenSSLAlgorithmToAlgorithmGetterFlow::flow(src, sink) - ) - or - // Possibility 2: - this instanceof DirectGetterCall and getterCall = this - ) - } - - Crypto::AlgorithmConsumer getConsumer() { - AlgGetterToAlgConsumerFlow::flow(getterCall.getResultNode(), DataFlow::exprNode(result)) - } - - override Crypto::THashType getHashFamily() { - knownOpenSSLConstantToHashFamilyType(this, result) or - not knownOpenSSLConstantToHashFamilyType(this, _) and result = Crypto::OtherHashType() - } - - override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } - - // override int getHashSize() { none() } //TODO -} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll deleted file mode 100644 index 82bf331546f7..000000000000 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll +++ /dev/null @@ -1,30 +0,0 @@ -import EVPHashInitializer -import EVPHashOperation -import EVPHashAlgorithmSource - -class EVP_Digest_Initializer_Algorithm_Consumer extends Crypto::AlgorithmValueConsumer instanceof EVPDigestInitializerAlgorithmArgument -{ - override DataFlow::Node getInputNode() { result.asExpr() = this } - - override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { - result.(KnownOpenSSLHashConstantAlgorithmInstance).getConsumer() = this - } -} - -class EVP_Q_Digest_Algorithm_Consumer extends Crypto::AlgorithmValueConsumer instanceof EVP_Q_Digest_Algorithm_Argument -{ - override DataFlow::Node getInputNode() { result.asExpr() = this } - - override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { - result.(KnownOpenSSLHashConstantAlgorithmInstance).getConsumer() = this - } -} - -class EVP_Digest_Algorithm_Consumer extends Crypto::AlgorithmValueConsumer instanceof EVP_Digest_Algorithm_Argument -{ - override DataFlow::Node getInputNode() { result.asExpr() = this } - - override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { - result.(KnownOpenSSLHashConstantAlgorithmInstance).getConsumer() = this - } -} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashInitializer.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashInitializer.qll deleted file mode 100644 index 16a9234d68ca..000000000000 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashInitializer.qll +++ /dev/null @@ -1,25 +0,0 @@ -import cpp - -abstract class EVP_Hash_Inititalizer extends Call { - Expr getContextArg() { result = this.(Call).getArgument(0) } - - abstract Expr getAlgorithmArg(); -} - -class EVP_DigestInit_Variant_Calls extends EVP_Hash_Inititalizer { - EVP_DigestInit_Variant_Calls() { - this.(Call).getTarget().getName() in [ - "EVP_DigestInit", "EVP_DigestInit_ex", "EVP_DigestInit_ex2" - ] - } - - override Expr getAlgorithmArg() { result = this.(Call).getArgument(1) } - -} - - -class EVPDigestInitializerAlgorithmArgument extends Expr { - EVPDigestInitializerAlgorithmArgument() { - exists(EVP_Hash_Inititalizer initCall | this = initCall.getAlgorithmArg()) - } -} \ No newline at end of file diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashOperation.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashOperation.qll deleted file mode 100644 index 7db90c4eccc0..000000000000 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashOperation.qll +++ /dev/null @@ -1,83 +0,0 @@ -import experimental.Quantum.Language -import CtxFlow as CTXFlow -import LibraryDetector -import EVPHashInitializer -import EVPHashConsumers - -abstract class EVP_Hash_Operation extends Crypto::HashOperationInstance instanceof Call { - Expr getContextArg() { result = this.(Call).getArgument(0) } - - EVP_Hash_Inititalizer getInitCall() { - CTXFlow::ctxFlowsTo(result.getContextArg(), this.getContextArg()) - } -} - -//https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis -class EVP_Q_Digest_Operation extends EVP_Hash_Operation { - EVP_Q_Digest_Operation() { - this.(Call).getTarget().getName() = "EVP_Q_digest" and - isPossibleOpenSSLFunction(this.(Call).getTarget()) - } - - override Crypto::AlgorithmConsumer getAlgorithmConsumer() { this.(Call).getArgument(1) = result } - - override EVP_Hash_Inititalizer getInitCall() { - // This variant of digest does not use an init - // and even if it were used, the init would be ignored/undefined - none() - } -} - -class EVP_Q_Digest_Algorithm_Argument extends Expr { - EVP_Q_Digest_Algorithm_Argument() { - exists(EVP_Q_Digest_Operation op | this = op.(Call).getArgument(1)) - } -} - -class EVP_Digest_Operation extends EVP_Hash_Operation { - EVP_Digest_Operation() { - this.(Call).getTarget().getName() = "EVP_Digest" and - isPossibleOpenSSLFunction(this.(Call).getTarget()) - } - - // There is no context argument for this function - override Expr getContextArg() { none() } - - override Crypto::AlgorithmConsumer getAlgorithmConsumer() { this.(Call).getArgument(4) = result } - - override EVP_Hash_Inititalizer getInitCall() { - // This variant of digest does not use an init - // and even if it were used, the init would be ignored/undefined - none() - } -} - -class EVP_Digest_Algorithm_Argument extends Expr { - EVP_Digest_Algorithm_Argument() { - exists(EVP_Digest_Operation op | this = op.(Call).getArgument(4)) - } -} - -class EVP_DigestUpdate_Operation extends EVP_Hash_Operation { - EVP_DigestUpdate_Operation() { - this.(Call).getTarget().getName() = "EVP_DigestUpdate" and - isPossibleOpenSSLFunction(this.(Call).getTarget()) - } - - override Crypto::AlgorithmConsumer getAlgorithmConsumer() { - this.getInitCall().getAlgorithmArg() = result - } -} - -class EVP_DigestFinal_Variants_Operation extends EVP_Hash_Operation { - EVP_DigestFinal_Variants_Operation() { - this.(Call).getTarget().getName() in [ - "EVP_DigestFinal", "EVP_DigestFinal_ex", "EVP_DigestFinalXOF" - ] and - isPossibleOpenSSLFunction(this.(Call).getTarget()) - } - - override Crypto::AlgorithmConsumer getAlgorithmConsumer() { - this.getInitCall().getAlgorithmArg() = result - } -} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherOperation.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherOperation.qll index 56288e6acb75..ae05798ea1f4 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherOperation.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherOperation.qll @@ -4,9 +4,7 @@ import EVPCipherInitializer import OpenSSLOperationBase import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers -// import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.AlgorithmValueConsumers -// import OpenSSLOperation -module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig { +private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { exists(OpenSSLAlgorithmValueConsumer c | c.getResultNode() = source) } @@ -16,8 +14,10 @@ module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig { } } -module AlgGetterToAlgConsumerFlow = DataFlow::Global; +private module AlgGetterToAlgConsumerFlow = DataFlow::Global; +// import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.AlgorithmValueConsumers +// import OpenSSLOperation // class EVPCipherOutput extends CipherOutputArtifact { // EVPCipherOutput() { exists(EVP_Cipher_Operation op | op.getOutputArg() = this) } // override DataFlow::Node getOutputNode() { result.asDefiningArgument() = this } @@ -81,6 +81,8 @@ class EVP_Cipher_Call extends EVP_Cipher_Operation { override Expr getInputArg() { result = this.(Call).getArgument(2) } } +// ******* TODO NEED to model UPDATE but not as the coree operation, rather a step towards final, +// see the JCA // class EVP_Encrypt_Decrypt_or_Cipher_Update_Call extends EVP_Update_Call { // EVP_Encrypt_Decrypt_or_Cipher_Update_Call() { // this.(Call).getTarget().getName() in [ diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperations.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperations.qll index 76a60b064e55..819e964878c3 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperations.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperations.qll @@ -1 +1,3 @@ +import OpenSSLOperationBase import EVPCipherOperation +import EVPHashOperation diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 6589cbbc9d5d..ceca0e45464b 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -386,7 +386,7 @@ module JCAModel { override Crypto::THashType getHashFamily() { result = hash_name_to_type_known(hashName, _) } - override int getDigestLength() { exists(hash_name_to_type_known(hashName, result)) } + override int getFixedDigestLength() { exists(hash_name_to_type_known(hashName, result)) } } class OAEPPaddingAlgorithmInstance extends Crypto::OAEPPaddingAlgorithmInstance, @@ -829,7 +829,7 @@ module JCAModel { result = hash_name_to_type_known(this.getRawHashAlgorithmName(), _) } - override int getDigestLength() { + override int getFixedDigestLength() { exists(hash_name_to_type_known(this.getRawHashAlgorithmName(), result)) } } @@ -1237,7 +1237,7 @@ module JCAModel { result = hash_name_to_type_known(this.getRawHashAlgorithmName(), _) } - override int getDigestLength() { + override int getFixedDigestLength() { exists(hash_name_to_type_known(this.getRawHashAlgorithmName(), result)) } diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 8fcc304e9ef9..69a4fd75acfa 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -983,9 +983,27 @@ module CryptographyBase Input> { abstract string getRawHashAlgorithmName(); /** - * Gets the length of the hash digest in bits. + * Gets the length of the hash digest in bits if it is not an implicit size + * and is not fixed by the algorithm. + * For example, SHA-256 has a fixed length of 256 bits. + * SHA-1 should not be modled with digest length as it is always 160 bits. + * Fixed length digests are modeled with `fixedImplicitDigestLength` and + * are used at the node level. */ - abstract int getDigestLength(); + abstract int getFixedDigestLength(); + } + + predicate fixedImplicitDigestLength(THashType type, int digestLength) { + type instanceof SHA1 and digestLength = 160 + or + type instanceof MD5 and + digestLength = 128 + or + type instanceof RIPEMD160 and + digestLength = 160 + or + type instanceof WHIRLPOOL and + digestLength = 512 // TODO: verify } abstract private class KeyCreationOperationInstance extends OperationInstance { @@ -2398,7 +2416,10 @@ module CryptographyBase Input> { override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashFamily(), result) } - int getDigestLength() { result = instance.asAlg().getDigestLength() } + int getDigestLength() { + result = instance.asAlg().getFixedDigestLength() or + fixedImplicitDigestLength(instance.asAlg().getHashFamily(), result) + } final override predicate properties(string key, string value, Location location) { super.properties(key, value, location) From 4042081539ac17b7a163f7a24ae76e907b0066d6 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Fri, 2 May 2025 16:35:27 -0400 Subject: [PATCH 253/336] Missing files, should have been part of last commit. --- .../CipherAlgorithmInstance.qll | 35 ++-- .../HashAlgorithmInstance.qll | 83 +++++++++ .../KnownAlgorithmConstants.qll | 160 +++++++++++------- .../HashAlgorithmValueConsumer.qll | 35 ++++ .../OpenSSL/Operations/EVPHashInitializer.qll | 17 ++ .../OpenSSL/Operations/EVPHashOperation.qll | 117 +++++++++++++ 6 files changed, 365 insertions(+), 82 deletions(-) create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/HashAlgorithmInstance.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/HashAlgorithmValueConsumer.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashInitializer.qll create mode 100644 cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashOperation.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll index 03f2643d46d2..0dd948c9fae2 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll @@ -66,28 +66,25 @@ predicate knownOpenSSLConstantToCipherFamilyType( class KnownOpenSSLCipherConstantAlgorithmInstance extends OpenSSLAlgorithmInstance, Crypto::KeyOperationAlgorithmInstance instanceof KnownOpenSSLCipherAlgorithmConstant { - //OpenSSLAlgorithmInstance, OpenSSLAlgorithmValueConsumer getterCall; KnownOpenSSLCipherConstantAlgorithmInstance() { - ( - // Two possibilities: - // 1) The source is a literal and flows to a getter, then we know we have an instance - // 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that - // Possibility 1: - this instanceof Literal and - exists(DataFlow::Node src, DataFlow::Node sink | - // Sink is an argument to a CipherGetterCall - sink = getterCall.(OpenSSLAlgorithmValueConsumer).getInputNode() and - // Source is `this` - src.asExpr() = this and - // This traces to a getter - KnownOpenSSLAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink) - ) - or - // Possibility 2: - this instanceof DirectAlgorithmValueConsumer and getterCall = this + // Two possibilities: + // 1) The source is a literal and flows to a getter, then we know we have an instance + // 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that + // Possibility 1: + this instanceof Literal and + exists(DataFlow::Node src, DataFlow::Node sink | + // Sink is an argument to a CipherGetterCall + sink = getterCall.(OpenSSLAlgorithmValueConsumer).getInputNode() and + // Source is `this` + src.asExpr() = this and + // This traces to a getter + KnownOpenSSLAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink) ) + or + // Possibility 2: + this instanceof DirectAlgorithmValueConsumer and getterCall = this } override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { @@ -101,7 +98,7 @@ class KnownOpenSSLCipherConstantAlgorithmInstance extends OpenSSLAlgorithmInstan //TODO: the padding is either self, or it flows through getter ctx to a set padding call // like EVP_PKEY_CTX_set_rsa_padding result = this - // or trace through getter ctx to set padding + // TODO or trace through getter ctx to set padding } override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() } diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/HashAlgorithmInstance.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/HashAlgorithmInstance.qll new file mode 100644 index 000000000000..4b412da9b55b --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/HashAlgorithmInstance.qll @@ -0,0 +1,83 @@ +import cpp +import experimental.Quantum.Language +import KnownAlgorithmConstants +import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers +import AlgToAVCFlow + +predicate knownOpenSSLConstantToHashFamilyType( + KnownOpenSSLHashAlgorithmConstant e, Crypto::THashType type +) { + exists(string name | + name = e.getNormalizedName() and + ( + name.matches("BLAKE2B") and type instanceof Crypto::BLAKE2B + or + name.matches("BLAKE2S") and type instanceof Crypto::BLAKE2S + or + name.matches("GOST%") and type instanceof Crypto::GOSTHash + or + name.matches("MD2") and type instanceof Crypto::MD2 + or + name.matches("MD4") and type instanceof Crypto::MD4 + or + name.matches("MD5") and type instanceof Crypto::MD5 + or + name.matches("MDC2") and type instanceof Crypto::MDC2 + or + name.matches("POLY1305") and type instanceof Crypto::POLY1305 + or + name.matches(["SHA", "SHA1"]) and type instanceof Crypto::SHA1 + or + name.matches("SHA+%") and not name.matches(["SHA1", "SHA3-"]) and type instanceof Crypto::SHA2 + or + name.matches("SHA3-%") and type instanceof Crypto::SHA3 + or + name.matches(["SHAKE"]) and type instanceof Crypto::SHAKE + or + name.matches("SM3") and type instanceof Crypto::SM3 + or + name.matches("RIPEMD160") and type instanceof Crypto::RIPEMD160 + or + name.matches("WHIRLPOOL") and type instanceof Crypto::WHIRLPOOL + ) + ) +} + +class KnownOpenSSLHashConstantAlgorithmInstance extends OpenSSLAlgorithmInstance, + Crypto::HashAlgorithmInstance instanceof KnownOpenSSLHashAlgorithmConstant +{ + OpenSSLAlgorithmValueConsumer getterCall; + + KnownOpenSSLHashConstantAlgorithmInstance() { + // Two possibilities: + // 1) The source is a literal and flows to a getter, then we know we have an instance + // 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that + // Possibility 1: + this instanceof Literal and + exists(DataFlow::Node src, DataFlow::Node sink | + // Sink is an argument to a CipherGetterCall + sink = getterCall.(OpenSSLAlgorithmValueConsumer).getInputNode() and + // Source is `this` + src.asExpr() = this and + // This traces to a getter + KnownOpenSSLAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink) + ) + or + // Possibility 2: + this instanceof DirectAlgorithmValueConsumer and getterCall = this + } + + override OpenSSLAlgorithmValueConsumer getAVC() { result = getterCall } + + override Crypto::THashType getHashFamily() { + knownOpenSSLConstantToHashFamilyType(this, result) + or + not knownOpenSSLConstantToHashFamilyType(this, _) and result = Crypto::OtherHashType() + } + + override string getRawHashAlgorithmName() { result = this.(Literal).getValue().toString() } + + override int getFixedDigestLength() { + this.(KnownOpenSSLHashAlgorithmConstant).getExplicitDigestLength() = result + } +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll index 80bd6b422da4..a0f0107d0ac6 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll @@ -1,40 +1,69 @@ import cpp import experimental.Quantum.OpenSSL.LibraryDetector -class KnownOpenSSLAlgorithmConstant extends Expr { - string normalizedName; - string algType; +predicate resolveAlgorithmFromExpr(Expr e, string normalizedName, string algType) { + resolveAlgorithmFromCall(e, normalizedName, algType) + or + resolveAlgorithmFromLiteral(e, normalizedName, algType) +} - KnownOpenSSLAlgorithmConstant() { - resolveAlgorithmFromCall(this, normalizedName, algType) - or - resolveAlgorithmFromLiteral(this, normalizedName, algType) - } +class KnownOpenSSLAlgorithmConstant extends Expr { + KnownOpenSSLAlgorithmConstant() { resolveAlgorithmFromExpr(this, _, _) } - string getNormalizedName() { result = normalizedName } + string getNormalizedName() { resolveAlgorithmFromExpr(this, result, _) } - string getAlgType() { result = algType } + string getAlgType() { resolveAlgorithmFromExpr(this, _, result) } } class KnownOpenSSLCipherAlgorithmConstant extends KnownOpenSSLAlgorithmConstant { + string algType; + KnownOpenSSLCipherAlgorithmConstant() { - this.(KnownOpenSSLAlgorithmConstant).getAlgType().toLowerCase().matches("%encryption") + resolveAlgorithmFromExpr(this, _, algType) and + algType.toLowerCase().matches("%encryption") } int getExplicitKeySize() { - result = this.getNormalizedName().regexpCapture(".*-(\\d*)", 1).toInt() + exists(string name | + name = this.getNormalizedName() and + resolveAlgorithmFromExpr(this, name, algType) and + result = name.regexpCapture(".*-(\\d*)", 1).toInt() + ) } } class KnownOpenSSLPaddingAlgorithmConstant extends KnownOpenSSLAlgorithmConstant { + string algType; + KnownOpenSSLPaddingAlgorithmConstant() { - this.(KnownOpenSSLAlgorithmConstant).getAlgType().toLowerCase().matches("%padding") + resolveAlgorithmFromExpr(this, _, algType) and + algType.toLowerCase().matches("%padding") } } class KnownOpenSSLBlockModeAlgorithmConstant extends KnownOpenSSLAlgorithmConstant { + string algType; + KnownOpenSSLBlockModeAlgorithmConstant() { - this.(KnownOpenSSLAlgorithmConstant).getAlgType().toLowerCase().matches("block_mode") + resolveAlgorithmFromExpr(this, _, algType) and + algType.toLowerCase().matches("%block_mode") + } +} + +class KnownOpenSSLHashAlgorithmConstant extends KnownOpenSSLAlgorithmConstant { + string algType; + + KnownOpenSSLHashAlgorithmConstant() { + resolveAlgorithmFromExpr(this, _, algType) and + algType.toLowerCase().matches("%hash") + } + + int getExplicitDigestLength() { + exists(string name | + name = this.getNormalizedName() and + resolveAlgorithmFromExpr(this, name, "HASH") and + result = name.regexpCapture(".*-(\\d*)$", 1).toInt() + ) } } @@ -224,6 +253,11 @@ predicate defaultAliases(string target, string alias) { alias = "ssl3-sha1" and target = "sha1" } +predicate tbd(string normalized, string algType) { + knownOpenSSLAlgorithmLiteral(_, _, normalized, algType) and + algType = "HASH" +} + /** * Enumeration of all known crypto algorithms for openSSL * `name` is all lower case (caller's must ensure they pass in lower case) @@ -244,9 +278,9 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "gost2001" and nid = 811 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION" or - name = "gost2012_256" and nid = 979 and normalized = "GOST" and algType = "HASH" // TODO: Verify algorithm type + name = "gost2012_256" and nid = 979 and normalized = "GOST" and algType = "ELLIPTIC_CURVE" // TODO: Verify algorithm type or - name = "gost2012_512" and nid = 980 and normalized = "GOST" and algType = "HASH" // TODO: Verify algorithm type + name = "gost2012_512" and nid = 980 and normalized = "GOST" and algType = "ELLIPTIC_CURVE" // TODO: Verify algorithm type or name = "ed25519" and nid = 1087 and normalized = "ED25519" and algType = "ELLIPTIC_CURVE" or @@ -266,17 +300,17 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "md5" and nid = 4 and normalized = "MD5" and algType = "HASH" or - name = "sha224" and nid = 675 and normalized = "SHA224" and algType = "HASH" + name = "sha224" and nid = 675 and normalized = "SHA-224" and algType = "HASH" or - name = "sha256" and nid = 672 and normalized = "SHA256" and algType = "HASH" + name = "sha256" and nid = 672 and normalized = "SHA-256" and algType = "HASH" or - name = "sha384" and nid = 673 and normalized = "SHA384" and algType = "HASH" + name = "sha384" and nid = 673 and normalized = "SHA-384" and algType = "HASH" or - name = "sha512" and nid = 674 and normalized = "SHA512" and algType = "HASH" + name = "sha512" and nid = 674 and normalized = "SHA-512" and algType = "HASH" or - name = "sha512-224" and nid = 1094 and normalized = "SHA512224" and algType = "HASH" + name = "sha512-224" and nid = 1094 and normalized = "SHA-512-224" and algType = "HASH" or - name = "sha512-256" and nid = 1095 and normalized = "SHA512256" and algType = "HASH" + name = "sha512-256" and nid = 1095 and normalized = "SHA-512-256" and algType = "HASH" or name = "sha3-224" and nid = 1096 and normalized = "SHA3-224" and algType = "HASH" or @@ -286,9 +320,9 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "sha3-512" and nid = 1099 and normalized = "SHA3-512" and algType = "HASH" or - name = "shake128" and nid = 1100 and normalized = "SHAKE128" and algType = "HASH" + name = "shake128" and nid = 1100 and normalized = "SHAKE-128" and algType = "HASH" or - name = "shake256" and nid = 1101 and normalized = "SHAKE256" and algType = "HASH" + name = "shake256" and nid = 1101 and normalized = "SHAKE-256" and algType = "HASH" or name = "mdc2" and nid = 95 and normalized = "MDC2" and algType = "HASH" or @@ -1141,7 +1175,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "aes-256-cbc-hmac-sha1" and nid = 918 and normalized = "CBC" and algType = "BLOCK_MODE" or - name = "aes-128-cbc-hmac-sha256" and nid = 948 and normalized = "SHA256" and algType = "HASH" + name = "aes-128-cbc-hmac-sha256" and nid = 948 and normalized = "SHA-256" and algType = "HASH" or name = "aes-128-cbc-hmac-sha256" and nid = 948 and @@ -1150,7 +1184,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "aes-128-cbc-hmac-sha256" and nid = 948 and normalized = "CBC" and algType = "BLOCK_MODE" or - name = "aes-192-cbc-hmac-sha256" and nid = 949 and normalized = "SHA256" and algType = "HASH" + name = "aes-192-cbc-hmac-sha256" and nid = 949 and normalized = "SHA-256" and algType = "HASH" or name = "aes-192-cbc-hmac-sha256" and nid = 949 and @@ -1159,7 +1193,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "aes-192-cbc-hmac-sha256" and nid = 949 and normalized = "CBC" and algType = "BLOCK_MODE" or - name = "aes-256-cbc-hmac-sha256" and nid = 950 and normalized = "SHA256" and algType = "HASH" + name = "aes-256-cbc-hmac-sha256" and nid = 950 and normalized = "SHA-256" and algType = "HASH" or name = "aes-256-cbc-hmac-sha256" and nid = 950 and @@ -1389,11 +1423,11 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "id-dsa-with-sha384" and nid = 1106 and normalized = "DSA" and algType = "SIGNATURE" or - name = "id-dsa-with-sha384" and nid = 1106 and normalized = "SHA384" and algType = "HASH" + name = "id-dsa-with-sha384" and nid = 1106 and normalized = "SHA-384" and algType = "HASH" or name = "id-dsa-with-sha512" and nid = 1107 and normalized = "DSA" and algType = "SIGNATURE" or - name = "id-dsa-with-sha512" and nid = 1107 and normalized = "SHA512" and algType = "HASH" + name = "id-dsa-with-sha512" and nid = 1107 and normalized = "SHA-512" and algType = "HASH" or name = "id-dsa-with-sha3-224" and nid = 1108 and normalized = "DSA" and algType = "SIGNATURE" or @@ -1773,22 +1807,22 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "dhsinglepass-cofactordh-sha224kdf-scheme" and nid = 942 and - normalized = "SHA224" and + normalized = "SHA-224" and algType = "HASH" or name = "dhsinglepass-cofactordh-sha256kdf-scheme" and nid = 943 and - normalized = "SHA256" and + normalized = "SHA-256" and algType = "HASH" or name = "dhsinglepass-cofactordh-sha384kdf-scheme" and nid = 944 and - normalized = "SHA384" and + normalized = "SHA-384" and algType = "HASH" or name = "dhsinglepass-cofactordh-sha512kdf-scheme" and nid = 945 and - normalized = "SHA512" and + normalized = "SHA-512" and algType = "HASH" or name = "dhsinglepass-stddh-sha1kdf-scheme" and @@ -1798,22 +1832,22 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "dhsinglepass-stddh-sha224kdf-scheme" and nid = 937 and - normalized = "SHA224" and + normalized = "SHA-224" and algType = "HASH" or name = "dhsinglepass-stddh-sha256kdf-scheme" and nid = 938 and - normalized = "SHA256" and + normalized = "SHA-256" and algType = "HASH" or name = "dhsinglepass-stddh-sha384kdf-scheme" and nid = 939 and - normalized = "SHA384" and + normalized = "SHA-384" and algType = "HASH" or name = "dhsinglepass-stddh-sha512kdf-scheme" and nid = 940 and - normalized = "SHA512" and + normalized = "SHA-512" and algType = "HASH" or name = "dsa-old" and nid = 67 and normalized = "DSA" and algType = "SIGNATURE" @@ -1832,9 +1866,9 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "dsa_with_sha224" and nid = 802 and normalized = "DSA" and algType = "SIGNATURE" or - name = "dsa_with_sha224" and nid = 802 and normalized = "SHA224" and algType = "HASH" + name = "dsa_with_sha224" and nid = 802 and normalized = "SHA-224" and algType = "HASH" or - name = "dsa_with_sha256" and nid = 803 and normalized = "SHA256" and algType = "HASH" + name = "dsa_with_sha256" and nid = 803 and normalized = "SHA-256" and algType = "HASH" or name = "dsa_with_sha256" and nid = 803 and normalized = "DSA" and algType = "SIGNATURE" or @@ -1856,11 +1890,11 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "dsa_with_sha384" and nid = 1106 and normalized = "DSA" and algType = "SIGNATURE" or - name = "dsa_with_sha384" and nid = 1106 and normalized = "SHA384" and algType = "HASH" + name = "dsa_with_sha384" and nid = 1106 and normalized = "SHA-384" and algType = "HASH" or name = "dsa_with_sha512" and nid = 1107 and normalized = "DSA" and algType = "SIGNATURE" or - name = "dsa_with_sha512" and nid = 1107 and normalized = "SHA512" and algType = "HASH" + name = "dsa_with_sha512" and nid = 1107 and normalized = "SHA-512" and algType = "HASH" or name = "dsaencryption" and nid = 116 and normalized = "DSA" and algType = "SIGNATURE" or @@ -1906,19 +1940,19 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "ecdsa-with-sha1" and nid = 416 and normalized = "ECDSA" and algType = "SIGNATURE" or - name = "ecdsa-with-sha224" and nid = 793 and normalized = "SHA224" and algType = "HASH" + name = "ecdsa-with-sha224" and nid = 793 and normalized = "SHA-224" and algType = "HASH" or name = "ecdsa-with-sha224" and nid = 793 and normalized = "ECDSA" and algType = "SIGNATURE" or - name = "ecdsa-with-sha256" and nid = 794 and normalized = "SHA256" and algType = "HASH" + name = "ecdsa-with-sha256" and nid = 794 and normalized = "SHA-256" and algType = "HASH" or name = "ecdsa-with-sha256" and nid = 794 and normalized = "ECDSA" and algType = "SIGNATURE" or - name = "ecdsa-with-sha384" and nid = 795 and normalized = "SHA384" and algType = "HASH" + name = "ecdsa-with-sha384" and nid = 795 and normalized = "SHA-384" and algType = "HASH" or name = "ecdsa-with-sha384" and nid = 795 and normalized = "ECDSA" and algType = "SIGNATURE" or - name = "ecdsa-with-sha512" and nid = 796 and normalized = "SHA512" and algType = "HASH" + name = "ecdsa-with-sha512" and nid = 796 and normalized = "SHA-512" and algType = "HASH" or name = "ecdsa-with-sha512" and nid = 796 and normalized = "ECDSA" and algType = "SIGNATURE" or @@ -2114,17 +2148,17 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "hmacwithsha1" and nid = 163 and normalized = "SHA1" and algType = "HASH" or - name = "hmacwithsha224" and nid = 798 and normalized = "SHA224" and algType = "HASH" + name = "hmacwithsha224" and nid = 798 and normalized = "SHA-224" and algType = "HASH" or - name = "hmacwithsha256" and nid = 799 and normalized = "SHA256" and algType = "HASH" + name = "hmacwithsha256" and nid = 799 and normalized = "SHA-256" and algType = "HASH" or - name = "hmacwithsha384" and nid = 800 and normalized = "SHA384" and algType = "HASH" + name = "hmacwithsha384" and nid = 800 and normalized = "SHA-384" and algType = "HASH" or - name = "hmacwithsha512" and nid = 801 and normalized = "SHA512" and algType = "HASH" + name = "hmacwithsha512" and nid = 801 and normalized = "SHA-512" and algType = "HASH" or - name = "hmacwithsha512-224" and nid = 1193 and normalized = "SHA512224" and algType = "HASH" + name = "hmacwithsha512-224" and nid = 1193 and normalized = "SHA-512-224" and algType = "HASH" or - name = "hmacwithsha512-256" and nid = 1194 and normalized = "SHA512256" and algType = "HASH" + name = "hmacwithsha512-256" and nid = 1194 and normalized = "SHA-512-256" and algType = "HASH" or name = "hmacwithsm3" and nid = 1281 and normalized = "SM3" and algType = "HASH" or @@ -2765,11 +2799,11 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "rsa-sha224" and nid = 671 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "rsa-sha224" and nid = 671 and normalized = "SHA224" and algType = "HASH" + name = "rsa-sha224" and nid = 671 and normalized = "SHA-224" and algType = "HASH" or name = "rsa-sha256" and nid = 668 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "rsa-sha256" and nid = 668 and normalized = "SHA256" and algType = "HASH" + name = "rsa-sha256" and nid = 668 and normalized = "SHA-256" and algType = "HASH" or name = "rsa-sha3-224" and nid = 1116 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or @@ -2789,25 +2823,25 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "rsa-sha384" and nid = 669 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "rsa-sha384" and nid = 669 and normalized = "SHA384" and algType = "HASH" + name = "rsa-sha384" and nid = 669 and normalized = "SHA-384" and algType = "HASH" or name = "rsa-sha512" and nid = 670 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "rsa-sha512" and nid = 670 and normalized = "SHA512" and algType = "HASH" + name = "rsa-sha512" and nid = 670 and normalized = "SHA-512" and algType = "HASH" or name = "rsa-sha512/224" and nid = 1145 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "rsa-sha512/224" and nid = 1145 and normalized = "SHA512224" and algType = "HASH" + name = "rsa-sha512/224" and nid = 1145 and normalized = "SHA-512-224" and algType = "HASH" or name = "rsa-sha512/256" and nid = 1146 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "rsa-sha512/256" and nid = 1146 and normalized = "SHA512256" and algType = "HASH" + name = "rsa-sha512/256" and nid = 1146 and normalized = "SHA-512-256" and algType = "HASH" or name = "rsa-sm3" and nid = 1144 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or @@ -2859,21 +2893,21 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "sha224withrsaencryption" and nid = 671 and normalized = "SHA224" and algType = "HASH" + name = "sha224withrsaencryption" and nid = 671 and normalized = "SHA-224" and algType = "HASH" or name = "sha256withrsaencryption" and nid = 668 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "sha256withrsaencryption" and nid = 668 and normalized = "SHA256" and algType = "HASH" + name = "sha256withrsaencryption" and nid = 668 and normalized = "SHA-256" and algType = "HASH" or name = "sha384withrsaencryption" and nid = 669 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "sha384withrsaencryption" and nid = 669 and normalized = "SHA384" and algType = "HASH" + name = "sha384withrsaencryption" and nid = 669 and normalized = "SHA-384" and algType = "HASH" or name = "sha512-224withrsaencryption" and nid = 1145 and @@ -2882,7 +2916,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "sha512-224withrsaencryption" and nid = 1145 and - normalized = "SHA512224" and + normalized = "SHA-512-224" and algType = "HASH" or name = "sha512-256withrsaencryption" and @@ -2892,7 +2926,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, or name = "sha512-256withrsaencryption" and nid = 1146 and - normalized = "SHA512256" and + normalized = "SHA-512-256" and algType = "HASH" or name = "sha512withrsaencryption" and @@ -2900,7 +2934,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION" or - name = "sha512withrsaencryption" and nid = 670 and normalized = "SHA512" and algType = "HASH" + name = "sha512withrsaencryption" and nid = 670 and normalized = "SHA-512" and algType = "HASH" or name = "shawithrsaencryption" and nid = 42 and diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/HashAlgorithmValueConsumer.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/HashAlgorithmValueConsumer.qll new file mode 100644 index 000000000000..753bb356e7a7 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/HashAlgorithmValueConsumer.qll @@ -0,0 +1,35 @@ +// import EVPHashInitializer +// import EVPHashOperation +// import EVPHashAlgorithmSource +import cpp +import experimental.Quantum.Language +import semmle.code.cpp.dataflow.new.DataFlow +import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase +import experimental.Quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances +import experimental.Quantum.OpenSSL.LibraryDetector + +abstract class HashAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { } + +/** + * EVP_Q_Digest directly consumes algorithm constant values + */ +class EVP_Q_Digest_Algorithm_Consumer extends OpenSSLAlgorithmValueConsumer { + EVP_Q_Digest_Algorithm_Consumer() { + isPossibleOpenSSLFunction(this.(Call).getTarget()) and + this.(Call).getTarget().getName() = "EVP_Q_digest" + } + + override Crypto::ConsumerInputDataFlowNode getInputNode() { + result.asExpr() = this.(Call).getArgument(1) + } + + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + exists(OpenSSLAlgorithmInstance i | i.getAVC() = this and result = i) + } + + override DataFlow::Node getResultNode() { + // EVP_Q_Digest directly consumes the algorithm constant value and performs the operation, there is no + // algorithm result + none() + } +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashInitializer.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashInitializer.qll new file mode 100644 index 000000000000..cd0dac94001a --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashInitializer.qll @@ -0,0 +1,17 @@ +import cpp + +abstract class EVP_Hash_Inititalizer extends Call { + Expr getContextArg() { result = this.(Call).getArgument(0) } + + abstract Expr getAlgorithmArg(); +} + +class EVP_DigestInit_Variant_Calls extends EVP_Hash_Inititalizer { + EVP_DigestInit_Variant_Calls() { + this.(Call).getTarget().getName() in [ + "EVP_DigestInit", "EVP_DigestInit_ex", "EVP_DigestInit_ex2" + ] + } + + override Expr getAlgorithmArg() { result = this.(Call).getArgument(1) } +} diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashOperation.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashOperation.qll new file mode 100644 index 000000000000..b7771e240a47 --- /dev/null +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashOperation.qll @@ -0,0 +1,117 @@ +/** + * https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis + */ + +import experimental.Quantum.Language +import experimental.Quantum.OpenSSL.CtxFlow as CTXFlow +import experimental.Quantum.OpenSSL.LibraryDetector +import OpenSSLOperationBase +import EVPHashInitializer +import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers + +// import EVPHashConsumers +abstract class EVP_Hash_Operation extends OpenSSLOperation, Crypto::HashOperationInstance { + Expr getContextArg() { result = this.(Call).getArgument(0) } + + EVP_Hash_Inititalizer getInitCall() { + CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg()) + } +} + +private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + exists(OpenSSLAlgorithmValueConsumer c | c.getResultNode() = source) + } + + predicate isSink(DataFlow::Node sink) { + exists(EVP_Hash_Operation c | c.getInitCall().getAlgorithmArg() = sink.asExpr()) + } +} + +private module AlgGetterToAlgConsumerFlow = DataFlow::Global; + +//https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis +class EVP_Q_Digest_Operation extends EVP_Hash_Operation { + EVP_Q_Digest_Operation() { + this.(Call).getTarget().getName() = "EVP_Q_digest" and + isPossibleOpenSSLFunction(this.(Call).getTarget()) + } + + //override Crypto::AlgorithmConsumer getAlgorithmConsumer() { } + override EVP_Hash_Inititalizer getInitCall() { + // This variant of digest does not use an init + // and even if it were used, the init would be ignored/undefined + none() + } + + override Expr getOutputArg() { result = this.(Call).getArgument(5) } + + override Expr getInputArg() { result = this.(Call).getArgument(3) } + + override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { result = this.getOutputNode() } + + override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() } + + override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { + // The operation is a direct algorithm consumer + // NOTE: the operation itself is already modeld as a value consumer, so we can + // simply return 'this', see modeled hash algorithm consuers for EVP_Q_Digest + this = result + } +} + +class EVP_Digest_Operation extends EVP_Hash_Operation { + EVP_Digest_Operation() { + this.(Call).getTarget().getName() = "EVP_Digest" and + isPossibleOpenSSLFunction(this.(Call).getTarget()) + } + + // There is no context argument for this function + override Expr getContextArg() { none() } + + override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { + AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(), + DataFlow::exprNode(this.(Call).getArgument(4))) + } + + override EVP_Hash_Inititalizer getInitCall() { + // This variant of digest does not use an init + // and even if it were used, the init would be ignored/undefined + none() + } + + override Expr getOutputArg() { result = this.(Call).getArgument(2) } + + override Expr getInputArg() { result = this.(Call).getArgument(0) } + + override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { result = this.getOutputNode() } + + override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() } +} +// // override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { +// // AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(), +// // DataFlow::exprNode(this.getInitCall().getAlgorithmArg())) +// // } +// // ***** TODO *** complete modelinlg for hash operations, but have consideration for terminal and non-terminal (non intermedaite) steps +// // see the JCA. May need to update the cipher operations similarly +// // ALSO SEE cipher for how we currently model initialization of the algorithm through an init call +// class EVP_DigestUpdate_Operation extends EVP_Hash_Operation { +// EVP_DigestUpdate_Operation() { +// this.(Call).getTarget().getName() = "EVP_DigestUpdate" and +// isPossibleOpenSSLFunction(this.(Call).getTarget()) +// } +// override Crypto::AlgorithmConsumer getAlgorithmConsumer() { +// this.getInitCall().getAlgorithmArg() = result +// } +// } +// class EVP_DigestFinal_Variants_Operation extends EVP_Hash_Operation { +// EVP_DigestFinal_Variants_Operation() { +// this.(Call).getTarget().getName() in [ +// "EVP_DigestFinal", "EVP_DigestFinal_ex", "EVP_DigestFinalXOF" +// ] and +// isPossibleOpenSSLFunction(this.(Call).getTarget()) +// } +// override Crypto::AlgorithmConsumer getAlgorithmConsumer() { +// this.getInitCall().getAlgorithmArg() = result +// } +// } From d600eb42cf10f56705688bceb2806386f6179ff1 Mon Sep 17 00:00:00 2001 From: Sid Gawri Date: Fri, 2 May 2025 17:25:02 -0400 Subject: [PATCH 254/336] add new stubs --- csharp/ql/test/experimental/CWE-918/options | 1 + .../CookieHttpOnlyFalseSystemWeb/options | 1 + .../ConfigEmpty/options | 1 + .../ConfigFalse/options | 1 + .../HttpCookiesTrue/options | 1 + .../CWE-614/RequireSSLFalseSystemWeb/options | 1 + .../RequireSSLSystemWeb/ConfigEmpty/options | 1 + .../RequireSSLSystemWeb/ConfigFalse/options | 1 + .../RequireSSLSystemWeb/FormsTrue/options | 1 + .../HttpCookiesTrue/options | 1 + .../Security Features/CWE-020/options | 1 + .../CWE-022/TaintedPath/options | 1 + .../CWE-079/StoredXSS/options | 1 + .../Security Features/CWE-090/options | 1 + .../CWE-091/XMLInjection/options | 1 + .../Security Features/CWE-094/options | 1 + .../Security Features/CWE-099/options | 1 + .../Security Features/CWE-112/options | 1 + .../CWE-114/AssemblyPathInjection/options | 1 + .../Security Features/CWE-134/options | 1 + .../CWE-201/ExposureInTransmittedData/options | 1 + .../Security Features/CWE-209/options | 1 + .../WebConfigOff/options | 1 + .../WebConfigOffButGlobal/options | 1 + .../WebFormsTests/options | 1 + .../Security Features/CWE-312/options | 1 + .../Security Features/CWE-352/global/options | 1 + .../Security Features/CWE-352/missing/options | 1 + .../Security Features/CWE-359/options | 1 + .../Security Features/CWE-384/options | 1 + .../CodeAddedHeader/options | 1 + .../MissingXFrameOptions/NoHeader/options | 1 + .../WebConfigAddedHeader/options | 1 + .../CWE-502/UnsafeDeserialization/options | 1 + .../options | 1 + .../options | 1 + .../CWE-539/PersistentCookie/options | 1 + .../CWE-614/RequireSSL/AddedInCode/options | 1 + .../CWE-639/WebFormsTests/options | 1 + .../Security Features/CWE-643/options | 1 + .../Security Features/CWE-730/ReDoS/options | 1 + .../CWE-730/ReDoSGlobalTimeout/options | 1 + .../CWE-730/RegexInjection/options | 1 + .../Security Features/CWE-807/options | 1 + .../Security Features/CWE-838/options | 1 + .../Telemetry/SupportedExternalApis/options | 1 + .../Telemetry/SupportedExternalSinks/options | 1 + csharp/ql/test/resources/stubs/System.Net.cs | 16 +++++ csharp/ql/test/resources/stubs/System.Web.cs | 59 ++++++++++++++++++- 49 files changed, 121 insertions(+), 1 deletion(-) diff --git a/csharp/ql/test/experimental/CWE-918/options b/csharp/ql/test/experimental/CWE-918/options index 09b08bf4d270..914a0be40c93 100644 --- a/csharp/ql/test/experimental/CWE-918/options +++ b/csharp/ql/test/experimental/CWE-918/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../resources/stubs/System.Web.cs \ No newline at end of file diff --git a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieHttpOnlyFalseSystemWeb/options b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieHttpOnlyFalseSystemWeb/options index 9290f65d5b22..daca5d73f552 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieHttpOnlyFalseSystemWeb/options +++ b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieHttpOnlyFalseSystemWeb/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigEmpty/options b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigEmpty/options index 9d05f9bf06d4..dbb615bf06c0 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigEmpty/options +++ b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigEmpty/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigFalse/options b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigFalse/options index 9d05f9bf06d4..dbb615bf06c0 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigFalse/options +++ b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigFalse/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/HttpCookiesTrue/options b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/HttpCookiesTrue/options index 9d05f9bf06d4..dbb615bf06c0 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/HttpCookiesTrue/options +++ b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/HttpCookiesTrue/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLFalseSystemWeb/options b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLFalseSystemWeb/options index 9290f65d5b22..daca5d73f552 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLFalseSystemWeb/options +++ b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLFalseSystemWeb/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigEmpty/options b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigEmpty/options index 9d05f9bf06d4..dbb615bf06c0 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigEmpty/options +++ b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigEmpty/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigFalse/options b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigFalse/options index 9d05f9bf06d4..dbb615bf06c0 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigFalse/options +++ b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigFalse/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/FormsTrue/options b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/FormsTrue/options index 9d05f9bf06d4..dbb615bf06c0 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/FormsTrue/options +++ b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/FormsTrue/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/HttpCookiesTrue/options b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/HttpCookiesTrue/options index 9d05f9bf06d4..dbb615bf06c0 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/HttpCookiesTrue/options +++ b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/HttpCookiesTrue/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-020/options b/csharp/ql/test/query-tests/Security Features/CWE-020/options index 96b0b028bdd2..0ce0c6870b7c 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-020/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-020/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-022/TaintedPath/options b/csharp/ql/test/query-tests/Security Features/CWE-022/TaintedPath/options index 9290f65d5b22..daca5d73f552 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-022/TaintedPath/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-022/TaintedPath/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/options b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/options index c5b4a9586554..ebbb04324897 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/System.Data.SqlClient/4.9.0/System.Data.SqlClient.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-090/options b/csharp/ql/test/query-tests/Security Features/CWE-090/options index 20a0480c8e2f..ba17ecb5638c 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-090/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-090/options @@ -1,4 +1,5 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/System.Data.SqlClient/4.9.0/System.Data.SqlClient.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs semmle-extractor-options: ${testdir}/../../../resources/stubs/System.DirectoryServices.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-091/XMLInjection/options b/csharp/ql/test/query-tests/Security Features/CWE-091/XMLInjection/options index 9290f65d5b22..daca5d73f552 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-091/XMLInjection/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-091/XMLInjection/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-094/options b/csharp/ql/test/query-tests/Security Features/CWE-094/options index cce2f114af69..ce5d6db635af 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-094/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-094/options @@ -1,5 +1,6 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Windows.cs semmle-extractor-options: ${testdir}/../../../resources/stubs/Microsoft.CSharp.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-099/options b/csharp/ql/test/query-tests/Security Features/CWE-099/options index 7404a7573b27..595b1a2bac00 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-099/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-099/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/System.Data.SqlClient/4.9.0/System.Data.SqlClient.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-112/options b/csharp/ql/test/query-tests/Security Features/CWE-112/options index 96b0b028bdd2..0ce0c6870b7c 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-112/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-112/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-114/AssemblyPathInjection/options b/csharp/ql/test/query-tests/Security Features/CWE-114/AssemblyPathInjection/options index 9290f65d5b22..daca5d73f552 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-114/AssemblyPathInjection/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-114/AssemblyPathInjection/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-134/options b/csharp/ql/test/query-tests/Security Features/CWE-134/options index ab08ee323e2b..aff430e13cc9 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-134/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-134/options @@ -1,4 +1,5 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Windows.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-201/ExposureInTransmittedData/options b/csharp/ql/test/query-tests/Security Features/CWE-201/ExposureInTransmittedData/options index c5b4a9586554..ebbb04324897 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-201/ExposureInTransmittedData/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-201/ExposureInTransmittedData/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/System.Data.SqlClient/4.9.0/System.Data.SqlClient.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-209/options b/csharp/ql/test/query-tests/Security Features/CWE-209/options index 96b0b028bdd2..0ce0c6870b7c 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-209/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-209/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOff/options b/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOff/options index 9d05f9bf06d4..dbb615bf06c0 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOff/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOff/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOffButGlobal/options b/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOffButGlobal/options index 9d05f9bf06d4..dbb615bf06c0 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOffButGlobal/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOffButGlobal/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-285/MissingAccessControl/WebFormsTests/options b/csharp/ql/test/query-tests/Security Features/CWE-285/MissingAccessControl/WebFormsTests/options index fb93d69d6b43..d43edf41c562 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-285/MissingAccessControl/WebFormsTests/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-285/MissingAccessControl/WebFormsTests/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-312/options b/csharp/ql/test/query-tests/Security Features/CWE-312/options index ab08ee323e2b..aff430e13cc9 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-312/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-312/options @@ -1,4 +1,5 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Windows.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-352/global/options b/csharp/ql/test/query-tests/Security Features/CWE-352/global/options index 9290f65d5b22..daca5d73f552 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-352/global/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-352/global/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-352/missing/options b/csharp/ql/test/query-tests/Security Features/CWE-352/missing/options index 9290f65d5b22..daca5d73f552 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-352/missing/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-352/missing/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-359/options b/csharp/ql/test/query-tests/Security Features/CWE-359/options index ab08ee323e2b..aff430e13cc9 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-359/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-359/options @@ -1,4 +1,5 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Windows.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-384/options b/csharp/ql/test/query-tests/Security Features/CWE-384/options index 96b0b028bdd2..0ce0c6870b7c 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-384/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-384/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/CodeAddedHeader/options b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/CodeAddedHeader/options index 9d05f9bf06d4..dbb615bf06c0 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/CodeAddedHeader/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/CodeAddedHeader/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/NoHeader/options b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/NoHeader/options index 9d05f9bf06d4..dbb615bf06c0 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/NoHeader/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/NoHeader/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeader/options b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeader/options index 9d05f9bf06d4..dbb615bf06c0 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeader/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeader/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/options b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/options index 9290f65d5b22..daca5d73f552 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/options b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/options index 9290f65d5b22..daca5d73f552 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/options b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/options index 750b4e671894..62b643d45cbf 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/Newtonsoft.Json/13.0.3/Newtonsoft.Json.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-539/PersistentCookie/options b/csharp/ql/test/query-tests/Security Features/CWE-539/PersistentCookie/options index 9290f65d5b22..daca5d73f552 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-539/PersistentCookie/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-539/PersistentCookie/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-614/RequireSSL/AddedInCode/options b/csharp/ql/test/query-tests/Security Features/CWE-614/RequireSSL/AddedInCode/options index 9d05f9bf06d4..dbb615bf06c0 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-614/RequireSSL/AddedInCode/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-614/RequireSSL/AddedInCode/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-639/WebFormsTests/options b/csharp/ql/test/query-tests/Security Features/CWE-639/WebFormsTests/options index a5d7077ef37a..1fcc7e1cf48f 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-639/WebFormsTests/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-639/WebFormsTests/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-643/options b/csharp/ql/test/query-tests/Security Features/CWE-643/options index 7404a7573b27..595b1a2bac00 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-643/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-643/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/System.Data.SqlClient/4.9.0/System.Data.SqlClient.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoS/options b/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoS/options index 9290f65d5b22..daca5d73f552 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoS/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoS/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoSGlobalTimeout/options b/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoSGlobalTimeout/options index 9290f65d5b22..daca5d73f552 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoSGlobalTimeout/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoSGlobalTimeout/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/options b/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/options index 9290f65d5b22..daca5d73f552 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-807/options b/csharp/ql/test/query-tests/Security Features/CWE-807/options index 96b0b028bdd2..0ce0c6870b7c 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-807/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-807/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-838/options b/csharp/ql/test/query-tests/Security Features/CWE-838/options index 5e2b8b8284e2..0af895004012 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-838/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-838/options @@ -1,4 +1,5 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/System.Data.SqlClient/4.9.0/System.Data.SqlClient.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs ${testdir}/../../../resources/stubs/System.Windows.cs diff --git a/csharp/ql/test/query-tests/Telemetry/SupportedExternalApis/options b/csharp/ql/test/query-tests/Telemetry/SupportedExternalApis/options index 96b0b028bdd2..0ce0c6870b7c 100644 --- a/csharp/ql/test/query-tests/Telemetry/SupportedExternalApis/options +++ b/csharp/ql/test/query-tests/Telemetry/SupportedExternalApis/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Telemetry/SupportedExternalSinks/options b/csharp/ql/test/query-tests/Telemetry/SupportedExternalSinks/options index 96b0b028bdd2..0ce0c6870b7c 100644 --- a/csharp/ql/test/query-tests/Telemetry/SupportedExternalSinks/options +++ b/csharp/ql/test/query-tests/Telemetry/SupportedExternalSinks/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/resources/stubs/System.Net.cs b/csharp/ql/test/resources/stubs/System.Net.cs index 939c70c792e8..d0f03f3af553 100644 --- a/csharp/ql/test/resources/stubs/System.Net.cs +++ b/csharp/ql/test/resources/stubs/System.Net.cs @@ -49,6 +49,22 @@ public class StringContent { public StringContent(string s) { } } + + public class HttpResponseMessage : IDisposable + { + public HttpResponseMessage() { } + public HttpResponseMessage(HttpStatusCode statusCode) { } + + + public Version Version { get; set; } + public HttpContent Content { get; set; } + public HttpStatusCode StatusCode { get; set; } + public HttpResponseHeaders Headers { get; } + public HttpRequestMessage RequestMessage { get; set; } + public bool IsSuccessStatusCode { get; } + } + + } namespace System.Net.Mail diff --git a/csharp/ql/test/resources/stubs/System.Web.cs b/csharp/ql/test/resources/stubs/System.Web.cs index d1942c07dc1d..56f51208e540 100644 --- a/csharp/ql/test/resources/stubs/System.Web.cs +++ b/csharp/ql/test/resources/stubs/System.Web.cs @@ -19,6 +19,15 @@ public class HttpRequestBase public class HttpResponseBase { public void Write(object obj) { } + public virtual void AppendHeader(string name, string value) { } + public virtual void Redirect(string url) { } + public virtual void RedirectPermanent(string url) { } + public virtual int StatusCode { get; set; } + public virtual void AddHeader(string name, string value) { } + public virtual void End() { } + public virtual string RedirectLocation { get; set; } + public virtual NameValueCollection Headers => null; + } public class HttpContextBase @@ -55,7 +64,15 @@ namespace System.Web.Http { public class ApiController { + public Microsoft.AspNetCore.Http.HttpContext Context => null; + public virtual Microsoft.AspNetCore.Mvc.RedirectResult Redirect(Uri location) => null; + public virtual Microsoft.AspNetCore.Mvc.RedirectResult Redirect(string location) => null; + public virtual ResponseMessageResult ResponseMessage(System.Net.Http.HttpResponseMessage response) => null; + public virtual Microsoft.AspNetCore.Mvc.RedirectToRouteResult RedirectToRoute(string routeName, object routeValues) => null; + public Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; set; } } + + public class ResponseMessageResult { } } namespace System.Web.Mvc @@ -63,14 +80,35 @@ namespace System.Web.Mvc public class Controller { public ViewResult View() => null; + public HttpRequestBase Request => null; + public HttpResponseBase Response => null; + protected internal virtual RedirectResult RedirectPermanent(string url) => null; + protected internal RedirectToRouteResult RedirectToRoute(string routeName) => null; + public UrlHelper Url { get; set; } + protected internal virtual RedirectResult Redirect(string url) => null; } public class MvcHtmlString : HtmlString { public MvcHtmlString(string s) : base(s) { } } + + public class RoutePrefixAttribute : Attribute + { + public virtual string Prefix { get; private set; } + public RoutePrefixAttribute(string prefix) { } + } + + public sealed class RouteAttribute : Attribute + { + + public RouteAttribute(string template) { } + } + + public class RedirectToRouteResult : ActionResult { } } + namespace System.Web.UI { public class Control @@ -81,6 +119,7 @@ public class Page { public System.Security.Principal.IPrincipal User { get; } public System.Web.HttpRequest Request { get; } + public HttpResponse Response => null; } interface IPostBackDataHandler @@ -153,6 +192,7 @@ public class HttpRequest public UnvalidatedRequestValues Unvalidated { get; } public string RawUrl { get; set; } public HttpCookieCollection Cookies => null; + public bool IsAuthenticated { get; set; } } public class HttpRequestWrapper : System.Web.HttpRequestBase @@ -169,6 +209,13 @@ public void WriteFile(string s) { } public void AddHeader(string name, string value) { } public void Redirect(string url) { } public void AppendHeader(string name, string value) { } + public void End() { } + public string RedirectLocation { get; set; } + public int StatusCode { get; set; } + public void RedirectPermanent(string url) { } + public virtual NameValueCollection Headers { get; set; } + + } public class HttpContext : IServiceProvider @@ -177,6 +224,7 @@ public class HttpContext : IServiceProvider public HttpResponse Response => null; public SessionState.HttpSessionState Session => null; public HttpServerUtility Server => null; + public static HttpContext Current => null; } public class HttpCookie @@ -301,6 +349,15 @@ public class UrlHelper public UrlHelper(Routing.RequestContext requestContext) { } public virtual bool IsLocalUrl(string url) => false; } + + public class RedirectResult : ActionResult + { + public bool Permanent { get; set; } + public string Url => null; + + public RedirectResult(string url) : this(url, permanent: false) { } + public RedirectResult(string url, bool permanent) { } + } } namespace System.Web.Routing @@ -390,7 +447,7 @@ public class JavaScriptSerializer public JavaScriptSerializer() => throw null; public JavaScriptSerializer(System.Web.Script.Serialization.JavaScriptTypeResolver resolver) => throw null; public object DeserializeObject(string input) => throw null; - public T Deserialize (string input) => throw null; + public T Deserialize(string input) => throw null; public object Deserialize(string input, Type targetType) => throw null; } From c7026c03dfb090b5f3b1f740c2a8235ef5b2ef50 Mon Sep 17 00:00:00 2001 From: Florin Coada Date: Mon, 5 May 2025 11:13:42 -0400 Subject: [PATCH 255/336] Update changelogs for CodeQL CLI 2.21.2 and adjust query reporting for unversioned immutable actions --- .../codeql-changelog/codeql-cli-2.21.2.rst | 122 ++++++++++++++++++ .../codeql-changelog/index.rst | 1 + 2 files changed, 123 insertions(+) create mode 100644 docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.2.rst diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.2.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.2.rst new file mode 100644 index 000000000000..8d9c20cfbb5c --- /dev/null +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.2.rst @@ -0,0 +1,122 @@ +.. _codeql-cli-2.21.2: + +========================== +CodeQL 2.21.2 (2025-05-01) +========================== + +.. 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.21.2 runs a total of 452 security queries when configured with the Default suite (covering 168 CWE). The Extended suite enables an additional 136 queries (covering 35 more CWE). + +CodeQL CLI +---------- + +Bug Fixes +~~~~~~~~~ + +* :code:`codeql generate log-summary` now correctly includes :code:`dependencies` maps in predicate events for :code:`COMPUTED_EXTENSIONAL` predicates. + +Query Packs +----------- + +Bug Fixes +~~~~~~~~~ + +GitHub Actions +"""""""""""""" + +* Assigned a :code:`security-severity` to the query :code:`actions/excessive-secrets-exposure`. + +Breaking Changes +~~~~~~~~~~~~~~~~ + +GitHub Actions +"""""""""""""" + +* The following queries have been removed from the :code:`security-and-quality` suite. + They are not intended to produce user-facing alerts describing vulnerabilities. + Any existing alerts for these queries will be closed automatically. + + * :code:`actions/composite-action-sinks` + * :code:`actions/composite-action-sources` + * :code:`actions/composite-action-summaries` + * :code:`actions/reusable-workflow-sinks` (renamed from :code:`actions/reusable-wokflow-sinks`) + * :code:`actions/reusable-workflow-sources` + * :code:`actions/reusable-workflow-summaries` + +Minor Analysis Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +C# +"" + +* Changes to the MaD model generation infrastructure: + + * Changed the query :code:`cs/utils/modelgenerator/summary-models` to use the implementation from :code:`cs/utils/modelgenerator/mixed-summary-models`. + * Removed the now-redundant :code:`cs/utils/modelgenerator/mixed-summary-models` query. + * A similar replacement was made for :code:`cs/utils/modelgenerator/neutral-models`. That is, if :code:`GenerateFlowModel.py` is provided with :code:`--with-summaries`, combined/mixed models are now generated instead of heuristic models (and similar for :code:`--with-neutrals`). + +* Improved detection of authorization checks in the :code:`cs/web/missing-function-level-access-control` query. The query now recognizes authorization attributes inherited from base classes and interfaces. +* The precision of the query :code:`cs/invalid-string-formatting` has been improved. More methods and more overloads of existing format like methods are taken into account by the query. + +Java/Kotlin +""""""""""" + +* Changes to the MaD model generation infrastructure: + + * Changed the query :code:`java/utils/modelgenerator/summary-models` to use the implementation from :code:`java/utils/modelgenerator/mixed-summary-models`. + * Removed the now-redundant :code:`java/utils/modelgenerator/mixed-summary-models` query. + * A similar replacement was made for :code:`java/utils/modelgenerator/neutral-models`. That is, if :code:`GenerateFlowModel.py` is provided with :code:`--with-summaries`, combined/mixed models are now generated instead of heuristic models (and similar for :code:`--with-neutrals`). + +Rust +"""" + +* Changes to the MaD model generation infrastructure: + + * Changed the query :code:`rust/utils/modelgenerator/summary-models` to use the implementation from :code:`rust/utils/modelgenerator/mixed-summary-models`. + * Removed the now-redundant :code:`rust/utils/modelgenerator/mixed-summary-models` query. + * A similar replacement was made for :code:`rust/utils/modelgenerator/neutral-models`. That is, if :code:`GenerateFlowModel.py` is provided with :code:`--with-summaries`, combined/mixed models are now generated instead of heuristic models (and similar for :code:`--with-neutrals`). + +Language Libraries +------------------ + +Major Analysis Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Swift +""""" + +* Upgraded to allow analysis of Swift 6.1. + +Minor Analysis Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +C# +"" + +* Improved autobuilder logic for detecting whether a project references a SDK (and should be built using :code:`dotnet`). + +Swift +""""" + +* Added AST nodes :code:`ActorIsolationErasureExpr`, :code:`CurrentContextIsolationExpr`, + :code:`ExtracFunctionIsolationExpr` and :code:`UnreachableExpr` that correspond to new nodes added by Swift 6.0. + +New Features +~~~~~~~~~~~~ + +C/C++ +""""" + +* New classes :code:`TypeofType`, :code:`TypeofExprType`, and :code:`TypeofTypeType` were introduced, which represent the C23 :code:`typeof` and :code:`typeof_unqual` operators. The :code:`TypeofExprType` class represents the variant taking an expression as its argument. The :code:`TypeofTypeType` class represents the variant taking a type as its argument. +* A new class :code:`IntrinsicTransformedType` was introduced, which represents the type transforming intrinsics supported by clang, gcc, and MSVC. +* Introduced :code:`hasDesignator()` predicates to distinguish between designated and positional initializations for both struct/union fields and array elements. +* Added the :code:`isVla()` predicate to the :code:`ArrayType` class. This allows queries to identify variable-length arrays (VLAs). diff --git a/docs/codeql/codeql-overview/codeql-changelog/index.rst b/docs/codeql/codeql-overview/codeql-changelog/index.rst index 137185c94db2..92781448af86 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, 5 May 2025 11:30:15 -0400 Subject: [PATCH 256/336] Update codeql-cli-2.21.2.rst --- .../codeql-overview/codeql-changelog/codeql-cli-2.21.2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.2.rst b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.2.rst index 8d9c20cfbb5c..636cf2fe63d5 100644 --- a/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.2.rst +++ b/docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.21.2.rst @@ -108,7 +108,7 @@ Swift """"" * Added AST nodes :code:`ActorIsolationErasureExpr`, :code:`CurrentContextIsolationExpr`, - :code:`ExtracFunctionIsolationExpr` and :code:`UnreachableExpr` that correspond to new nodes added by Swift 6.0. + :code:`ExtractFunctionIsolationExpr` and :code:`UnreachableExpr` that correspond to new nodes added by Swift 6.0. New Features ~~~~~~~~~~~~ From 7231f53b6ee98780cd6626ab5a3e6855e8767d93 Mon Sep 17 00:00:00 2001 From: Sid Gawri Date: Mon, 5 May 2025 21:59:37 -0400 Subject: [PATCH 257/336] revert system.net stubs --- csharp/ql/test/resources/stubs/System.Net.cs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/csharp/ql/test/resources/stubs/System.Net.cs b/csharp/ql/test/resources/stubs/System.Net.cs index d0f03f3af553..49ad43b1d394 100644 --- a/csharp/ql/test/resources/stubs/System.Net.cs +++ b/csharp/ql/test/resources/stubs/System.Net.cs @@ -50,21 +50,6 @@ public class StringContent public StringContent(string s) { } } - public class HttpResponseMessage : IDisposable - { - public HttpResponseMessage() { } - public HttpResponseMessage(HttpStatusCode statusCode) { } - - - public Version Version { get; set; } - public HttpContent Content { get; set; } - public HttpStatusCode StatusCode { get; set; } - public HttpResponseHeaders Headers { get; } - public HttpRequestMessage RequestMessage { get; set; } - public bool IsSuccessStatusCode { get; } - } - - } namespace System.Net.Mail From 824271a84a2c872a366a27f2956648373c072946 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 May 2025 03:58:02 +0000 Subject: [PATCH 258/336] Bump golang.org/x/tools Bumps the extractor-dependencies group in /go/extractor with 1 update: [golang.org/x/tools](https://github.com/golang/tools). Updates `golang.org/x/tools` from 0.32.0 to 0.33.0 - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.32.0...v0.33.0) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-version: 0.33.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: extractor-dependencies ... Signed-off-by: dependabot[bot] --- go/extractor/go.mod | 4 ++-- go/extractor/go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go/extractor/go.mod b/go/extractor/go.mod index 737af893993f..cfdc82cbd2b4 100644 --- a/go/extractor/go.mod +++ b/go/extractor/go.mod @@ -10,7 +10,7 @@ toolchain go1.24.0 // bazel mod tidy require ( golang.org/x/mod v0.24.0 - golang.org/x/tools v0.32.0 + golang.org/x/tools v0.33.0 ) -require golang.org/x/sync v0.13.0 // indirect +require golang.org/x/sync v0.14.0 // indirect diff --git a/go/extractor/go.sum b/go/extractor/go.sum index 0fbc8831fb33..3341c6aa4ddc 100644 --- a/go/extractor/go.sum +++ b/go/extractor/go.sum @@ -2,7 +2,7 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= -golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= From 228c45aaf893e04a5d8704dce371def49cb87413 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 5 May 2025 17:42:55 +0100 Subject: [PATCH 259/336] Look through aliases when identifying method receivers --- go/extractor/trap/labels.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/go/extractor/trap/labels.go b/go/extractor/trap/labels.go index 79ac9192e026..2822da61ff14 100644 --- a/go/extractor/trap/labels.go +++ b/go/extractor/trap/labels.go @@ -169,11 +169,12 @@ func (l *Labeler) ScopedObjectID(object types.Object, getTypeLabel func() Label) // findMethodWithGivenReceiver finds a method with `object` as its receiver, if one exists func findMethodWithGivenReceiver(object types.Object) *types.Func { - meth := findMethodOnTypeWithGivenReceiver(object.Type(), object) + unaliasedType := types.Unalias(object.Type()) + meth := findMethodOnTypeWithGivenReceiver(unaliasedType, object) if meth != nil { return meth } - if pointerType, ok := object.Type().(*types.Pointer); ok { + if pointerType, ok := unaliasedType.(*types.Pointer); ok { meth = findMethodOnTypeWithGivenReceiver(pointerType.Elem(), object) } return meth From c781f98bdcb76558a25802c82c27ed66889976f3 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 5 May 2025 16:13:25 +0100 Subject: [PATCH 260/336] (unrelated tidy up) `resolveTypeAlias` not needed `types.Unalias` already does the same thing --- go/extractor/extractor.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/go/extractor/extractor.go b/go/extractor/extractor.go index f687f54c9777..c45443907530 100644 --- a/go/extractor/extractor.go +++ b/go/extractor/extractor.go @@ -1582,18 +1582,10 @@ func isAlias(tp types.Type) bool { return ok } -// If the given type is a type alias, this function resolves it to its underlying type. -func resolveTypeAlias(tp types.Type) types.Type { - if isAlias(tp) { - return types.Unalias(tp) // tp.Underlying() - } - return tp -} - // extractType extracts type information for `tp` and returns its associated label; // types are only extracted once, so the second time `extractType` is invoked it simply returns the label func extractType(tw *trap.Writer, tp types.Type) trap.Label { - tp = resolveTypeAlias(tp) + tp = types.Unalias(tp) lbl, exists := getTypeLabel(tw, tp) if !exists { var kind int @@ -1771,7 +1763,7 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label { // is constructed from their globally unique ID. This prevents cyclic type keys // since type recursion in Go always goes through defined types. func getTypeLabel(tw *trap.Writer, tp types.Type) (trap.Label, bool) { - tp = resolveTypeAlias(tp) + tp = types.Unalias(tp) lbl, exists := tw.Labeler.TypeLabels[tp] if !exists { switch tp := tp.(type) { From 310c02f1fb67c8d025e7abe6d88c77d055e90811 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 6 May 2025 23:02:52 +0100 Subject: [PATCH 261/336] Rust: Add a dataflow sources test for the Poem web fraemework. --- .../dataflow/sources/TaintSources.expected | 5 ++ .../dataflow/sources/options.yml | 2 + .../dataflow/sources/web_frameworks.rs | 81 +++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index ba7eeae00081..7a5fd2d000f5 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -47,3 +47,8 @@ | test.rs:369:25:369:43 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:377:22:377:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | | test.rs:386:16:386:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | +| web_frameworks.rs:13:31:13:31 | a | Flow source 'RemoteSource' of type remote (DEFAULT). | +| web_frameworks.rs:22:31:22:36 | TuplePat | Flow source 'RemoteSource' of type remote (DEFAULT). | +| web_frameworks.rs:44:31:44:45 | MyStruct {...} | Flow source 'RemoteSource' of type remote (DEFAULT). | +| web_frameworks.rs:52:31:52:32 | ms | Flow source 'RemoteSource' of type remote (DEFAULT). | +| web_frameworks.rs:61:15:61:15 | a | Flow source 'RemoteSource' of type remote (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/options.yml b/rust/ql/test/library-tests/dataflow/sources/options.yml index 9b4565f1e1ad..d351460c8a7c 100644 --- a/rust/ql/test/library-tests/dataflow/sources/options.yml +++ b/rust/ql/test/library-tests/dataflow/sources/options.yml @@ -7,3 +7,5 @@ qltest_dependencies: - http = { version = "1.2.0" } - tokio = { version = "1.43.0", features = ["full"] } - futures = { version = "0.3" } + - poem = { version = "3.1.10" } + - serde = { version = "1.0.219" } diff --git a/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs new file mode 100644 index 000000000000..2fd067a0583e --- /dev/null +++ b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs @@ -0,0 +1,81 @@ +#![allow(deprecated)] + +fn sink(_: T) { } + +// --- tests --- + +mod poem_test { + use poem::{get, handler, web::Path, web::Query, Route, Server, listener::TcpListener}; + use serde::Deserialize; + use crate::web_frameworks::sink; + + #[handler] + fn my_poem_handler_1(Path(a): Path) -> String { // $ Alert[rust/summary/taint-sources] + sink(a.as_str()); // $ MISSING: hasTaintFlow + sink(a.as_bytes()); // $ MISSING: hasTaintFlow + sink(a); // $ MISSING: hasTaintFlow + + "".to_string() + } + + #[handler] + fn my_poem_handler_2(Path((a, b)): Path<(String, String)>) -> String { // $ Alert[rust/summary/taint-sources] + sink(a); // $ MISSING: hasTaintFlow + sink(b); // $ MISSING: hasTaintFlow + + "".to_string() + } + + #[handler] + fn my_poem_handler_3(path: Path<(String, String)>) -> String { // $ MISSING: Alert[rust/summary/taint-sources] + sink(&path.0); // $ MISSING: hasTaintFlow + sink(&path.1); // $ MISSING: hasTaintFlow + + "".to_string() + } + + #[derive(Deserialize)] + struct MyStruct { + a: String, + b: String, + } + + #[handler] + fn my_poem_handler_4(Path(MyStruct {a, b}): Path) -> String { // $ Alert[rust/summary/taint-sources] + sink(a); // $ MISSING: hasTaintFlow + sink(b); // $ MISSING: hasTaintFlow + + "".to_string() + } + + #[handler] + fn my_poem_handler_5(Path(ms): Path) -> String { // $ Alert[rust/summary/taint-sources] + sink(ms.a); // $ MISSING: hasTaintFlow + sink(ms.b); // $ MISSING: hasTaintFlow + + "".to_string() + } + + #[handler] + fn my_poem_handler_6( + Query(a): Query, // $ Alert[rust/summary/taint-sources] + ) -> String { + sink(a); // $ MISSING: hasTaintFlow + + "".to_string() + } + + async fn test_poem() { + let app = Route::new() + .at("/1/:a", get(my_poem_handler_1)) + .at("/2/:a/:b", get(my_poem_handler_2)) + .at("/3/:a/:b", get(my_poem_handler_3)) + .at("/4/:a/:b", get(my_poem_handler_4)) + .at("/4/:a/:b", get(my_poem_handler_5)) + .at("/5/:a/", get(my_poem_handler_6)); + + _ = Server::new(TcpListener::bind("0.0.0.0:3000")).run(app).await.unwrap(); + + // ... + } +} From e56519d959e9f966e2f11d6273669d5b14a82b46 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 6 May 2025 23:30:42 +0100 Subject: [PATCH 262/336] Rust: Add a dataflow sources test for the Actix web fraemework. --- .../dataflow/sources/options.yml | 1 + .../dataflow/sources/web_frameworks.rs | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/rust/ql/test/library-tests/dataflow/sources/options.yml b/rust/ql/test/library-tests/dataflow/sources/options.yml index d351460c8a7c..1f1dbdec49d4 100644 --- a/rust/ql/test/library-tests/dataflow/sources/options.yml +++ b/rust/ql/test/library-tests/dataflow/sources/options.yml @@ -9,3 +9,4 @@ qltest_dependencies: - futures = { version = "0.3" } - poem = { version = "3.1.10" } - serde = { version = "1.0.219" } + - actix-web = { version = "4.10.2" } diff --git a/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs index 2fd067a0583e..0f27d57639ba 100644 --- a/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs +++ b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs @@ -79,3 +79,50 @@ mod poem_test { // ... } } + +mod actix_test { + use actix_web::{get, web, App, HttpServer}; + use crate::web_frameworks::sink; + + async fn my_actix_handler_1(path: web::Path) -> String { // $ MISSING: Alert[rust/summary/taint-sources] + let a = path.into_inner(); + sink(a.as_str()); // $ MISSING: hasTaintFlow + sink(a.as_bytes()); // $ MISSING: hasTaintFlow + sink(a); // $ MISSING: hasTaintFlow + + "".to_string() + } + + async fn my_actix_handler_2(path: web::Path<(String, String)>) -> String { // $ MISSING: Alert[rust/summary/taint-sources] + let (a, b) = path.into_inner(); + + sink(a); // $ MISSING: hasTaintFlow + sink(b); // $ MISSING: hasTaintFlow + + "".to_string() + } + + async fn my_actix_handler_3(web::Query(a): web::Query) -> String { // $ MISSING: Alert[rust/summary/taint-sources] + sink(a); // $ MISSING: hasTaintFlow + + "".to_string() + } + + #[get("/4/{a}")] + async fn my_actix_handler_4(path: web::Path) -> String { // $ MISSING: Alert[rust/summary/taint-sources] + let a = path.into_inner(); + sink(a); // $ MISSING: hasTaintFlow + + "".to_string() + } + + async fn test_actix() { + let app = App::new() + .route("/1/{a}", web::get().to(my_actix_handler_1)) + .route("/2/{a}/{b}", web::get().to(my_actix_handler_2)) + .route("/3/{a}", web::get().to(my_actix_handler_3)) + .service(my_actix_handler_4); + + // ... + } +} From 49ff96746525a81caddb53d73d41602b09a98e26 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 7 May 2025 09:24:47 +0100 Subject: [PATCH 263/336] Rust: Add a dataflow sources test for the Axum web fraemework. --- .../dataflow/sources/options.yml | 2 + .../dataflow/sources/web_frameworks.rs | 71 +++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/rust/ql/test/library-tests/dataflow/sources/options.yml b/rust/ql/test/library-tests/dataflow/sources/options.yml index 1f1dbdec49d4..5b3ef166b15e 100644 --- a/rust/ql/test/library-tests/dataflow/sources/options.yml +++ b/rust/ql/test/library-tests/dataflow/sources/options.yml @@ -10,3 +10,5 @@ qltest_dependencies: - poem = { version = "3.1.10" } - serde = { version = "1.0.219" } - actix-web = { version = "4.10.2" } + - axum = { version = "0.8.4" } + - serde_json = { version = "1.0.140" } diff --git a/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs index 0f27d57639ba..395010e7ef78 100644 --- a/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs +++ b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs @@ -126,3 +126,74 @@ mod actix_test { // ... } } + +mod axum_test { + use axum::Router; + use axum::routing::get; + use axum::extract::{Path, Query, Request, Json}; + use std::collections::HashMap; + use crate::web_frameworks::sink; + + async fn my_axum_handler_1(Path(a): Path) -> &'static str { // $ MISSING: Alert[rust/summary/taint-sources] + sink(a.as_str()); // $ MISSING: hasTaintFlow + sink(a.as_bytes()); // $ MISSING: hasTaintFlow + sink(a); // $ MISSING: hasTaintFlow + + "" + } + + async fn my_axum_handler_2(Path((a, b)): Path<(String, String)>) -> &'static str { // $ MISSING: Alert[rust/summary/taint-sources] + sink(a); // $ MISSING: hasTaintFlow + sink(b); // $ MISSING: hasTaintFlow + + "" + } + + async fn my_axum_handler_3(Query(params): Query>) -> &'static str { // $ MISSING: Alert[rust/summary/taint-sources] + for (key, value) in params { + sink(key); // $ MISSING: hasTaintFlow + sink(value); // $ MISSING: hasTaintFlow + } + + "" + } + + async fn my_axum_handler_4(request: Request) -> &'static str { // $ MISSING: Alert[rust/summary/taint-sources] + sink(request.body()); // $ MISSING: hasTaintFlow + request.headers().get("header").unwrap(); // $ MISSING: hasTaintFlow + sink(request.into_body()); // $ MISSING: hasTaintFlow + + "" + } + + async fn my_axum_handler_5(Json(payload): Json) -> &'static str { // $ MISSING: Alert[rust/summary/taint-sources] + sink(payload.as_str()); // $ MISSING: hasTaintFlow + sink(payload); // $ MISSING: hasTaintFlow + + "" + } + + async fn my_axum_handler_6(body: String) -> &'static str { // $ MISSING: Alert[rust/summary/taint-sources] + sink(body); // $ MISSING: hasTaintFlow + + "" + } + + async fn my_axum_handler_7(body: String) -> &'static str { // $ MISSING: Alert[rust/summary/taint-sources] + sink(body); // $ MISSING: hasTaintFlow + + "" + } + + async fn test_axum() { + let app = Router::<()>::new() + .route("/foo/{a}", get(my_axum_handler_1)) + .route("/bar/{a}/{b}", get(my_axum_handler_2)) + .route("/1/:a", get(my_axum_handler_3)) + .route("/2/:a", get(my_axum_handler_4)) + .route("/3/:a", get(my_axum_handler_5)) + .route("/4/:a", get(my_axum_handler_6).get(my_axum_handler_7)); + + // ... + } +} From 19f86fd67f5bdcf9846117d5d932277e419f7aad Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 7 May 2025 10:45:27 +0100 Subject: [PATCH 264/336] Rust: Address confusing / typo'd paths. --- .../dataflow/sources/web_frameworks.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs index 395010e7ef78..e3ab61274d23 100644 --- a/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs +++ b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs @@ -71,8 +71,8 @@ mod poem_test { .at("/2/:a/:b", get(my_poem_handler_2)) .at("/3/:a/:b", get(my_poem_handler_3)) .at("/4/:a/:b", get(my_poem_handler_4)) - .at("/4/:a/:b", get(my_poem_handler_5)) - .at("/5/:a/", get(my_poem_handler_6)); + .at("/5/:a/:b", get(my_poem_handler_5)) + .at("/6/:a/", get(my_poem_handler_6)); _ = Server::new(TcpListener::bind("0.0.0.0:3000")).run(app).await.unwrap(); @@ -187,12 +187,12 @@ mod axum_test { async fn test_axum() { let app = Router::<()>::new() - .route("/foo/{a}", get(my_axum_handler_1)) - .route("/bar/{a}/{b}", get(my_axum_handler_2)) - .route("/1/:a", get(my_axum_handler_3)) - .route("/2/:a", get(my_axum_handler_4)) - .route("/3/:a", get(my_axum_handler_5)) - .route("/4/:a", get(my_axum_handler_6).get(my_axum_handler_7)); + .route("/1/{a}", get(my_axum_handler_1)) + .route("/2/{a}/{b}", get(my_axum_handler_2)) + .route("/3/:a", get(my_axum_handler_3)) + .route("/4/:a", get(my_axum_handler_4)) + .route("/5/:a", get(my_axum_handler_5)) + .route("/67/:a", get(my_axum_handler_6).get(my_axum_handler_7)); // ... } From 56670c66f14d5b8e324baf1b661d3ee4292b9481 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 00:26:13 +0200 Subject: [PATCH 265/336] Revert Python changes and delete implementation --- python/ql/lib/experimental/Quantum/Base.qll | 250 ------------------ .../ql/lib/experimental/Quantum/Language.qll | 12 - .../experimental/Quantum/PycaCryptography.qll | 55 ---- python/ql/lib/semmle/python/Files.qll | 37 --- 4 files changed, 354 deletions(-) delete mode 100644 python/ql/lib/experimental/Quantum/Base.qll delete mode 100644 python/ql/lib/experimental/Quantum/Language.qll delete mode 100644 python/ql/lib/experimental/Quantum/PycaCryptography.qll diff --git a/python/ql/lib/experimental/Quantum/Base.qll b/python/ql/lib/experimental/Quantum/Base.qll deleted file mode 100644 index 9be24ca6efaa..000000000000 --- a/python/ql/lib/experimental/Quantum/Base.qll +++ /dev/null @@ -1,250 +0,0 @@ -/** - * A language-independent library for reasoning about cryptography. - */ - -import codeql.util.Location -import codeql.util.Option - -signature module InputSig { - class LocatableElement { - Location getLocation(); - } - - class UnknownLocation instanceof Location; -} - -module CryptographyBase Input> { - final class LocatableElement = Input::LocatableElement; - - final class UnknownLocation = Input::UnknownLocation; - - final class UnknownPropertyValue extends string { - UnknownPropertyValue() { this = "" } - } - - abstract class NodeBase instanceof LocatableElement { - /** - * Returns a string representation of this node, usually the name of the operation/algorithm/property. - */ - abstract string toString(); - - /** - * Returns the location of this node in the code. - */ - Location getLocation() { result = super.getLocation() } - - /** - * Gets the origin of this node, e.g., a string literal in source describing it. - */ - LocatableElement getOrigin(string value) { none() } - - /** - * Returns the child of this node with the given edge name. - * - * This predicate is used by derived classes to construct the graph of cryptographic operations. - */ - NodeBase getChild(string edgeName) { none() } - - /** - * Defines properties of this node by name and either a value or location or both. - * - * This predicate is used by derived classes to construct the graph of cryptographic operations. - */ - predicate properties(string key, string value, Location location) { - key = "origin" and location = this.getOrigin(value).getLocation() - } - - /** - * Returns the parent of this node. - */ - final NodeBase getAParent() { result.getChild(_) = this } - } - - class Asset = NodeBase; - - /** - * A cryptographic operation, such as hashing or encryption. - */ - abstract class Operation extends Asset { - /** - * Gets the algorithm associated with this operation. - */ - abstract Algorithm getAlgorithm(); - - /** - * Gets the name of this operation, e.g., "hash" or "encrypt". - */ - abstract string getOperationName(); - - final override string toString() { result = this.getOperationName() } - - override NodeBase getChild(string edgeName) { - result = super.getChild(edgeName) - or - edgeName = "uses" and - if exists(this.getAlgorithm()) then result = this.getAlgorithm() else result = this - } - } - - abstract class Algorithm extends Asset { - /** - * Gets the name of this algorithm, e.g., "AES" or "SHA". - */ - abstract string getAlgorithmName(); - - /** - * Gets the raw name of this algorithm from source (no parsing or formatting) - */ - abstract string getRawAlgorithmName(); - - final override string toString() { result = this.getAlgorithmName() } - } - - /** - * A hashing operation that processes data to generate a hash value. - * This operation takes an input message of arbitrary content and length and produces a fixed-size - * hash value as the output using a specified hashing algorithm. - */ - abstract class HashOperation extends Operation { - abstract override HashAlgorithm getAlgorithm(); - - override string getOperationName() { result = "HASH" } - } - - // Rule: no newtype representing a type of algorithm should be modelled with multiple interfaces - // - // Example: HKDF and PKCS12KDF are both key derivation algorithms. - // However, PKCS12KDF also has a property: the iteration count. - // - // If we have HKDF and PKCS12KDF under TKeyDerivationType, - // someone modelling a library might try to make a generic identification of both of those algorithms. - // - // They will therefore not use the specialized type for PKCS12KDF, - // meaning "from PKCS12KDF algo select algo" will have no results. - // - newtype THashType = - // We're saying by this that all of these have an identical interface / properties / edges - MD5() or - SHA1() or - SHA256() or - SHA512() or - OtherHashType() - - /** - * A hashing algorithm that transforms variable-length input into a fixed-size hash value. - */ - abstract class HashAlgorithm extends Algorithm { - final predicate hashTypeToNameMapping(THashType type, string name) { - type instanceof MD5 and name = "MD5" - or - type instanceof SHA1 and name = "SHA-1" - or - type instanceof SHA256 and name = "SHA-256" - or - type instanceof SHA512 and name = "SHA-512" - or - type instanceof OtherHashType and name = this.getRawAlgorithmName() - } - - abstract THashType getHashType(); - - override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashType(), result) } - - } - - /** - * An operation that derives one or more keys from an input value. - */ - abstract class KeyDerivationOperation extends Operation { - override string getOperationName() { result = "KEY_DERIVATION" } - } - - /** - * An algorithm that derives one or more keys from an input value. - */ - abstract class KeyDerivationAlgorithm extends Algorithm { - abstract override string getAlgorithmName(); - } - - /** - * HKDF key derivation function - */ - abstract class HKDF extends KeyDerivationAlgorithm { - final override string getAlgorithmName() { result = "HKDF" } - - abstract HashAlgorithm getHashAlgorithm(); - - override NodeBase getChild(string edgeName) { - result = super.getChild(edgeName) - or - edgeName = "digest" and result = this.getHashAlgorithm() - } - } - - /** - * PKCS #12 key derivation function - */ - abstract class PKCS12KDF extends KeyDerivationAlgorithm { - final override string getAlgorithmName() { result = "PKCS12KDF" } - - abstract HashAlgorithm getHashAlgorithm(); - - override NodeBase getChild(string edgeName) { - result = super.getChild(edgeName) - or - edgeName = "digest" and result = this.getHashAlgorithm() - } - } - - newtype TEllipticCurveFamilyType = - // We're saying by this that all of these have an identical interface / properties / edges - NIST() or - SEC() or - NUMS() or - PRIME() or - BRAINPOOL() or - CURVE25519() or - CURVE448() or - C2() or - SM2() or - ES() or - OtherEllipticCurveFamilyType() - - - /** - * Elliptic curve algorithm - */ - abstract class EllipticCurve extends Algorithm { - - - abstract string getKeySize(Location location); - - abstract TEllipticCurveFamilyType getCurveFamilyType(); - - override predicate properties(string key, string value, Location location) { - super.properties(key, value, location) - or - key = "key_size" and - if exists(this.getKeySize(location)) - then value = this.getKeySize(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - // other properties, like field type are possible, but not modeled until considered necessary - } - - override string getAlgorithmName() { result = this.getRawAlgorithmName().toUpperCase()} - - /** - * Mandating that for Elliptic Curves specifically, users are responsible - * for providing as the 'raw' name, the official name of the algorithm. - * Casing doesn't matter, we will enforce further naming restrictions on - * `getAlgorithmName` by default. - * Rationale: elliptic curve names can have a lot of variation in their components - * (e.g., "secp256r1" vs "P-256"), trying to produce generalized set of properties - * is possible to capture all cases, but such modeling is likely not necessary. - * if all properties need to be captured, we can reassess how names are generated. - */ - override abstract string getRawAlgorithmName(); - } -} diff --git a/python/ql/lib/experimental/Quantum/Language.qll b/python/ql/lib/experimental/Quantum/Language.qll deleted file mode 100644 index 9abf3e7fa7e4..000000000000 --- a/python/ql/lib/experimental/Quantum/Language.qll +++ /dev/null @@ -1,12 +0,0 @@ -private import Base -private import python as Lang - -module CryptoInput implements InputSig { - class LocatableElement = Lang::Expr; - - class UnknownLocation = Lang::UnknownDefaultLocation; -} - -module Crypto = CryptographyBase; - -import PycaCryptography diff --git a/python/ql/lib/experimental/Quantum/PycaCryptography.qll b/python/ql/lib/experimental/Quantum/PycaCryptography.qll deleted file mode 100644 index 802ad23cf9d9..000000000000 --- a/python/ql/lib/experimental/Quantum/PycaCryptography.qll +++ /dev/null @@ -1,55 +0,0 @@ -import python -import semmle.python.ApiGraphs - -module PycaCryptographyModule { - import Language - - /** - * Gets a predefined curve class constructor call from - * `cryptography.hazmat.primitives.asymmetric.ec` - * https://cryptography.io/en/latest/hazmat/primitives/asymmetric/ec/#elliptic-curves - */ - DataFlow::Node predefinedCurveClass(string rawName, string curveName, Crypto::TEllipticCurveFamilyType family, int keySize) { - // getACall since the typical case is to construct the curve with initialization values, - // not to pass the mode uninitialized - result = - API::moduleImport("cryptography") - .getMember("hazmat") - .getMember("primitives") - .getMember("asymmetric") - .getMember("ec") - .getMember(rawName) - .getACall() - and - curveName = rawName.toUpperCase() - and - curveName.matches("SEC%") and family instanceof Crypto::SEC - and - curveName.matches("BRAINPOOL%") and family instanceof Crypto::BRAINPOOL - and - // Enumerating all key sizes known in the API - // TODO: should we dynamically extract them through a regex? - keySize in [160, 163, 192, 224, 233, 256, 283, 320, 384, 409, 512, 571] - and - curveName.matches("%" + keySize + "%") - } - - - class EllipticCurve extends Crypto::EllipticCurve instanceof Expr{ - int keySize; - string rawName; - string curveName; - Crypto::TEllipticCurveFamilyType family; - EllipticCurve() { - this = predefinedCurveClass(rawName, curveName, family, keySize).asExpr() - } - - override string getRawAlgorithmName() { result = rawName } - override string getAlgorithmName() { result = curveName } - Crypto::TEllipticCurveFamilyType getFamily() { result = family } - - override string getKeySize(Location location) { - location = this and - result = keySize.toString() } - } -} diff --git a/python/ql/lib/semmle/python/Files.qll b/python/ql/lib/semmle/python/Files.qll index 67f21ad0b249..2da0dd61f885 100644 --- a/python/ql/lib/semmle/python/Files.qll +++ b/python/ql/lib/semmle/python/Files.qll @@ -368,40 +368,3 @@ class EncodingError extends SyntaxError { override string toString() { result = "Encoding Error" } } - - - -/** - * A dummy location which is used when something doesn't have a location in - * the source code but needs to have a `Location` associated with it. There - * may be several distinct kinds of unknown locations. For example: one for - * expressions, one for statements and one for other program elements. - */ -class UnknownLocation extends Location { - UnknownLocation() { this.getFile().getAbsolutePath() = "" } -} - -/** - * A dummy location which is used when something doesn't have a location in - * the source code but needs to have a `Location` associated with it. - */ -class UnknownDefaultLocation extends UnknownLocation { - UnknownDefaultLocation() { locations_default(this, _, 0, 0, 0, 0) } -} - -/** - * A dummy location which is used when an expression doesn't have a - * location in the source code but needs to have a `Location` associated - * with it. - */ -class UnknownExprLocation extends UnknownLocation { - UnknownExprLocation() { locations_default(this, _, 0, 0, 0, 0) } -} - -/** - * A dummy location which is used when a statement doesn't have a location - * in the source code but needs to have a `Location` associated with it. - */ -class UnknownStmtLocation extends UnknownLocation { - UnknownStmtLocation() { locations_default(this, _, 0, 0, 0, 0) } -} From 314f1ff93f75b87a323a3e62358209fbec4fa49b Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 00:28:32 +0200 Subject: [PATCH 266/336] Refactor Java directory structure --- .../Quantum/{InventoryFilters => Analysis}/ArtifactReuse.qll | 0 .../experimental/Quantum/{ => Analysis}/InsecureNonceSource.ql | 0 .../{InventoryFilters => Analysis}/KnownWeakKDFIterationCount.ql | 0 .../Quantum/{InventoryFilters => Analysis}/ReusedNonce.ql | 0 .../{InventoryFilters => Analysis}/UnknownKDFIterationCount.ql | 0 java/ql/src/experimental/Quantum/{ => Examples}/BrokenCrypto.ql | 0 .../Quantum/{ => Examples}/InsecureOrUnknownNonceAtOperation.ql | 0 .../ql/src/experimental/Quantum/{ => Examples}/TestAESGCMNonce.ql | 0 java/ql/src/experimental/Quantum/{ => Examples}/TestCipher.ql | 0 java/ql/src/experimental/Quantum/{ => Examples}/TestCipherKey.ql | 0 java/ql/src/experimental/Quantum/{ => Examples}/TestHash.ql | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename java/ql/src/experimental/Quantum/{InventoryFilters => Analysis}/ArtifactReuse.qll (100%) rename java/ql/src/experimental/Quantum/{ => Analysis}/InsecureNonceSource.ql (100%) rename java/ql/src/experimental/Quantum/{InventoryFilters => Analysis}/KnownWeakKDFIterationCount.ql (100%) rename java/ql/src/experimental/Quantum/{InventoryFilters => Analysis}/ReusedNonce.ql (100%) rename java/ql/src/experimental/Quantum/{InventoryFilters => Analysis}/UnknownKDFIterationCount.ql (100%) rename java/ql/src/experimental/Quantum/{ => Examples}/BrokenCrypto.ql (100%) rename java/ql/src/experimental/Quantum/{ => Examples}/InsecureOrUnknownNonceAtOperation.ql (100%) rename java/ql/src/experimental/Quantum/{ => Examples}/TestAESGCMNonce.ql (100%) rename java/ql/src/experimental/Quantum/{ => Examples}/TestCipher.ql (100%) rename java/ql/src/experimental/Quantum/{ => Examples}/TestCipherKey.ql (100%) rename java/ql/src/experimental/Quantum/{ => Examples}/TestHash.ql (100%) diff --git a/java/ql/src/experimental/Quantum/InventoryFilters/ArtifactReuse.qll b/java/ql/src/experimental/Quantum/Analysis/ArtifactReuse.qll similarity index 100% rename from java/ql/src/experimental/Quantum/InventoryFilters/ArtifactReuse.qll rename to java/ql/src/experimental/Quantum/Analysis/ArtifactReuse.qll diff --git a/java/ql/src/experimental/Quantum/InsecureNonceSource.ql b/java/ql/src/experimental/Quantum/Analysis/InsecureNonceSource.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InsecureNonceSource.ql rename to java/ql/src/experimental/Quantum/Analysis/InsecureNonceSource.ql diff --git a/java/ql/src/experimental/Quantum/InventoryFilters/KnownWeakKDFIterationCount.ql b/java/ql/src/experimental/Quantum/Analysis/KnownWeakKDFIterationCount.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventoryFilters/KnownWeakKDFIterationCount.ql rename to java/ql/src/experimental/Quantum/Analysis/KnownWeakKDFIterationCount.ql diff --git a/java/ql/src/experimental/Quantum/InventoryFilters/ReusedNonce.ql b/java/ql/src/experimental/Quantum/Analysis/ReusedNonce.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventoryFilters/ReusedNonce.ql rename to java/ql/src/experimental/Quantum/Analysis/ReusedNonce.ql diff --git a/java/ql/src/experimental/Quantum/InventoryFilters/UnknownKDFIterationCount.ql b/java/ql/src/experimental/Quantum/Analysis/UnknownKDFIterationCount.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventoryFilters/UnknownKDFIterationCount.ql rename to java/ql/src/experimental/Quantum/Analysis/UnknownKDFIterationCount.ql diff --git a/java/ql/src/experimental/Quantum/BrokenCrypto.ql b/java/ql/src/experimental/Quantum/Examples/BrokenCrypto.ql similarity index 100% rename from java/ql/src/experimental/Quantum/BrokenCrypto.ql rename to java/ql/src/experimental/Quantum/Examples/BrokenCrypto.ql diff --git a/java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql b/java/ql/src/experimental/Quantum/Examples/InsecureOrUnknownNonceAtOperation.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InsecureOrUnknownNonceAtOperation.ql rename to java/ql/src/experimental/Quantum/Examples/InsecureOrUnknownNonceAtOperation.ql diff --git a/java/ql/src/experimental/Quantum/TestAESGCMNonce.ql b/java/ql/src/experimental/Quantum/Examples/TestAESGCMNonce.ql similarity index 100% rename from java/ql/src/experimental/Quantum/TestAESGCMNonce.ql rename to java/ql/src/experimental/Quantum/Examples/TestAESGCMNonce.ql diff --git a/java/ql/src/experimental/Quantum/TestCipher.ql b/java/ql/src/experimental/Quantum/Examples/TestCipher.ql similarity index 100% rename from java/ql/src/experimental/Quantum/TestCipher.ql rename to java/ql/src/experimental/Quantum/Examples/TestCipher.ql diff --git a/java/ql/src/experimental/Quantum/TestCipherKey.ql b/java/ql/src/experimental/Quantum/Examples/TestCipherKey.ql similarity index 100% rename from java/ql/src/experimental/Quantum/TestCipherKey.ql rename to java/ql/src/experimental/Quantum/Examples/TestCipherKey.ql diff --git a/java/ql/src/experimental/Quantum/TestHash.ql b/java/ql/src/experimental/Quantum/Examples/TestHash.ql similarity index 100% rename from java/ql/src/experimental/Quantum/TestHash.ql rename to java/ql/src/experimental/Quantum/Examples/TestHash.ql From c19291be8872ffa1ae559079c968d86fd75939d2 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 01:38:53 +0200 Subject: [PATCH 267/336] Refactor 'cryptography' and 'Quantum' to 'quantum' --- cpp/ql/lib/experimental/Quantum/Language.qll | 4 +- .../AlgorithmInstances/AlgToAVCFlow.qll | 4 +- .../BlockAlgorithmInstance.qll | 6 +- .../CipherAlgorithmInstance.qll | 4 +- .../HashAlgorithmInstance.qll | 4 +- .../KnownAlgorithmConstants.qll | 2 +- .../OpenSSLAlgorithmInstanceBase.qll | 4 +- .../PaddingAlgorithmInstance.qll | 6 +- .../CipherAlgorithmValueConsumer.qll | 8 +- .../DirectAlgorithmValueConsumer.qll | 6 +- .../HashAlgorithmValueConsumer.qll | 8 +- .../OpenSSLAlgorithmValueConsumerBase.qll | 2 +- .../PaddingAlgorithmValueConsumer.qll | 8 +- .../experimental/Quantum/OpenSSL/OpenSSL.qll | 8 +- .../Operations/EVPCipherInitializer.qll | 4 +- .../OpenSSL/Operations/EVPCipherOperation.qll | 8 +- .../OpenSSL/Operations/EVPHashOperation.qll | 8 +- .../Operations/OpenSSLOperationBase.qll | 2 +- .../experimental/Quantum/OpenSSL/Random.qll | 7 +- cpp/ql/lib/qlpack.yml | 2 +- .../experimental/Quantum/PrintCBOMGraph.ql | 2 +- java/ql/lib/experimental/Quantum/Language.qll | 2 +- java/ql/lib/qlpack.yml | 2 +- .../Quantum/Analysis/ArtifactReuse.qll | 2 +- .../Quantum/Analysis/InsecureNonceSource.ql | 2 +- .../Analysis/KnownWeakKDFIterationCount.ql | 2 +- .../Analysis/UnknownKDFIterationCount.ql | 2 +- .../Quantum/Examples/BrokenCrypto.ql | 102 +++++++++--------- .../InsecureOrUnknownNonceAtOperation.ql | 2 +- .../Quantum/Examples/TestAESGCMNonce.ql | 2 +- .../Quantum/Examples/TestCipher.ql | 2 +- .../Quantum/Examples/TestCipherKey.ql | 2 +- .../experimental/Quantum/Examples/TestHash.ql | 2 +- .../KnownAsymmetricAlgorithm.ql | 2 +- .../KnownAsymmetricCipherAlgorithm.ql | 2 +- .../KnownAsymmetricOperationAlgorithm.ql | 2 +- .../InventorySlices/KnownCipherAlgorithm.ql | 2 +- .../KnownEllipticCurveAlgorithm.ql | 2 +- .../InventorySlices/KnownHashingAlgorithm.ql | 2 +- .../InventorySlices/KnownHashingOperation.ql | 2 +- .../KnownHashingOperationAlgorithm.ql | 2 +- .../KnownKeyDerivationAlgorithm.ql | 2 +- .../KnownKeyDerivationOperation.ql | 2 +- .../KnownKeyDerivationOperationAlgorithm.ql | 5 +- .../KnownSymmetricCipherAlgorithm.ql | 2 +- .../LikelyCryptoAPIFunction.ql | 2 +- .../UnknownOperationAlgorithm.ql | 2 +- .../experimental/Quantum/PrintCBOMGraph.ql | 2 +- .../codeql/quantum}/Model.qll | 0 .../{cryptography => experimental}/qlpack.yml | 2 +- 50 files changed, 130 insertions(+), 136 deletions(-) rename shared/{cryptography/codeql/cryptography => experimental/codeql/quantum}/Model.qll (100%) rename shared/{cryptography => experimental}/qlpack.yml (81%) diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index 2d076a1323c0..c3e2e3ad55f4 100644 --- a/cpp/ql/lib/experimental/Quantum/Language.qll +++ b/cpp/ql/lib/experimental/Quantum/Language.qll @@ -1,6 +1,4 @@ -private import codeql.cryptography.Model -import semmle.code.cpp.ir.IR -import semmle.code.cpp.security.FlowSources as FlowSources +import codeql.quantum.Model import semmle.code.cpp.dataflow.new.DataFlow private import cpp as Lang diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/AlgToAVCFlow.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/AlgToAVCFlow.qll index 25cdea6accf7..72c3ffcfad44 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/AlgToAVCFlow.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/AlgToAVCFlow.qll @@ -1,7 +1,7 @@ import cpp import semmle.code.cpp.dataflow.new.DataFlow -import experimental.Quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants -import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers // import all known alg value consummers +import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants +import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers /** * Traces 'known algorithms' to AVCs, specifically diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/BlockAlgorithmInstance.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/BlockAlgorithmInstance.qll index 1e17c64f34ca..2566c1188a6c 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/BlockAlgorithmInstance.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/BlockAlgorithmInstance.qll @@ -1,8 +1,8 @@ import cpp -import experimental.Quantum.Language +import experimental.quantum.Language import OpenSSLAlgorithmInstanceBase -import experimental.Quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants -import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer +import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants +import experimental.quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer import AlgToAVCFlow /** diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll index 0dd948c9fae2..7483572848eb 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll @@ -1,10 +1,10 @@ import cpp -import experimental.Quantum.Language +import experimental.quantum.Language import KnownAlgorithmConstants import Crypto::KeyOpAlg as KeyOpAlg import OpenSSLAlgorithmInstanceBase import PaddingAlgorithmInstance -import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers +import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers import AlgToAVCFlow import BlockAlgorithmInstance diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/HashAlgorithmInstance.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/HashAlgorithmInstance.qll index 4b412da9b55b..985e36dbdd71 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/HashAlgorithmInstance.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/HashAlgorithmInstance.qll @@ -1,7 +1,7 @@ import cpp -import experimental.Quantum.Language +import experimental.quantum.Language import KnownAlgorithmConstants -import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers +import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers import AlgToAVCFlow predicate knownOpenSSLConstantToHashFamilyType( diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll index a0f0107d0ac6..77caf0bb378c 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll @@ -1,5 +1,5 @@ import cpp -import experimental.Quantum.OpenSSL.LibraryDetector +import experimental.quantum.OpenSSL.LibraryDetector predicate resolveAlgorithmFromExpr(Expr e, string normalizedName, string algType) { resolveAlgorithmFromCall(e, normalizedName, algType) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstanceBase.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstanceBase.qll index 6a206773bfb8..dc49c139cf05 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstanceBase.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstanceBase.qll @@ -1,5 +1,5 @@ -import experimental.Quantum.Language -import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase +import experimental.quantum.Language +import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase abstract class OpenSSLAlgorithmInstance extends Crypto::AlgorithmInstance { abstract OpenSSLAlgorithmValueConsumer getAVC(); diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/PaddingAlgorithmInstance.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/PaddingAlgorithmInstance.qll index 219289c7da08..4fb4d0818697 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/PaddingAlgorithmInstance.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/PaddingAlgorithmInstance.qll @@ -1,9 +1,9 @@ import cpp -import experimental.Quantum.Language +import experimental.quantum.Language import OpenSSLAlgorithmInstanceBase -import experimental.Quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants +import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants import AlgToAVCFlow -import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer +import experimental.quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer /** * Given a `KnownOpenSSLPaddingAlgorithmConstant`, converts this to a padding family type. diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/CipherAlgorithmValueConsumer.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/CipherAlgorithmValueConsumer.qll index 19777bc06d1e..8fa65860b60c 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/CipherAlgorithmValueConsumer.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/CipherAlgorithmValueConsumer.qll @@ -1,8 +1,8 @@ import cpp -import experimental.Quantum.Language -import experimental.Quantum.OpenSSL.LibraryDetector -import experimental.Quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants -import experimental.Quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase +import experimental.quantum.Language +import experimental.quantum.OpenSSL.LibraryDetector +import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants +import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase import OpenSSLAlgorithmValueConsumerBase abstract class CipherAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { } diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/DirectAlgorithmValueConsumer.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/DirectAlgorithmValueConsumer.qll index cebe7a86a129..ffc9a7c3991e 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/DirectAlgorithmValueConsumer.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/DirectAlgorithmValueConsumer.qll @@ -1,7 +1,7 @@ import cpp -import experimental.Quantum.Language -import experimental.Quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants -import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase +import experimental.quantum.Language +import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants +import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase // TODO: can self referential to itself, which is also an algorithm (Known algorithm) /** diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/HashAlgorithmValueConsumer.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/HashAlgorithmValueConsumer.qll index 753bb356e7a7..b041b986754c 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/HashAlgorithmValueConsumer.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/HashAlgorithmValueConsumer.qll @@ -2,11 +2,11 @@ // import EVPHashOperation // import EVPHashAlgorithmSource import cpp -import experimental.Quantum.Language +import experimental.quantum.Language import semmle.code.cpp.dataflow.new.DataFlow -import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase -import experimental.Quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances -import experimental.Quantum.OpenSSL.LibraryDetector +import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase +import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances +import experimental.quantum.OpenSSL.LibraryDetector abstract class HashAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { } diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumerBase.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumerBase.qll index dddcf14c7134..3f6e2bd4dc89 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumerBase.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumerBase.qll @@ -1,4 +1,4 @@ -import experimental.Quantum.Language +import experimental.quantum.Language import semmle.code.cpp.dataflow.new.DataFlow abstract class OpenSSLAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer instanceof Call { diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/PaddingAlgorithmValueConsumer.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/PaddingAlgorithmValueConsumer.qll index 009b22cf1b86..3f7ce20d6b3a 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/PaddingAlgorithmValueConsumer.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/PaddingAlgorithmValueConsumer.qll @@ -1,8 +1,8 @@ import cpp -import experimental.Quantum.Language -import experimental.Quantum.OpenSSL.LibraryDetector -import experimental.Quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants -import experimental.Quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase +import experimental.quantum.Language +import experimental.quantum.OpenSSL.LibraryDetector +import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants +import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase import OpenSSLAlgorithmValueConsumerBase abstract class PaddingAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { } diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll index 6b28c4ee8e4b..f53812093c42 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll @@ -2,8 +2,8 @@ import cpp import semmle.code.cpp.dataflow.new.DataFlow module OpenSSLModel { - import experimental.Quantum.Language - import experimental.Quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances - import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers - import experimental.Quantum.OpenSSL.Operations.OpenSSLOperations + import experimental.quantum.Language + import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances + import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers + import experimental.quantum.OpenSSL.Operations.OpenSSLOperations } diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherInitializer.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherInitializer.qll index 584fd18a64c2..fdf60ef757e8 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherInitializer.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherInitializer.qll @@ -3,8 +3,8 @@ * Models cipher initialization for EVP cipher operations. */ -import experimental.Quantum.Language -import experimental.Quantum.OpenSSL.CtxFlow as CTXFlow +import experimental.quantum.Language +import experimental.quantum.OpenSSL.CtxFlow as CTXFlow module EncValToInitEncArgConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source.asExpr().getValue().toInt() in [0, 1] } diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherOperation.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherOperation.qll index ae05798ea1f4..45c7d41b029b 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherOperation.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherOperation.qll @@ -1,8 +1,8 @@ -import experimental.Quantum.Language -import experimental.Quantum.OpenSSL.CtxFlow as CTXFlow +import experimental.quantum.Language +import experimental.quantum.OpenSSL.CtxFlow as CTXFlow import EVPCipherInitializer import OpenSSLOperationBase -import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers +import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { @@ -16,7 +16,7 @@ private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig { private module AlgGetterToAlgConsumerFlow = DataFlow::Global; -// import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.AlgorithmValueConsumers +// import experimental.quantum.OpenSSL.AlgorithmValueConsumers.AlgorithmValueConsumers // import OpenSSLOperation // class EVPCipherOutput extends CipherOutputArtifact { // EVPCipherOutput() { exists(EVP_Cipher_Operation op | op.getOutputArg() = this) } diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashOperation.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashOperation.qll index b7771e240a47..45776b6668b3 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashOperation.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashOperation.qll @@ -2,12 +2,12 @@ * https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis */ -import experimental.Quantum.Language -import experimental.Quantum.OpenSSL.CtxFlow as CTXFlow -import experimental.Quantum.OpenSSL.LibraryDetector +import experimental.quantum.Language +import experimental.quantum.OpenSSL.CtxFlow as CTXFlow +import experimental.quantum.OpenSSL.LibraryDetector import OpenSSLOperationBase import EVPHashInitializer -import experimental.Quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers +import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers // import EVPHashConsumers abstract class EVP_Hash_Operation extends OpenSSLOperation, Crypto::HashOperationInstance { diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperationBase.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperationBase.qll index 851d7a4b7e99..4798f5650a9b 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperationBase.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperationBase.qll @@ -1,4 +1,4 @@ -import experimental.Quantum.Language +import experimental.quantum.Language abstract class OpenSSLOperation extends Crypto::OperationInstance instanceof Call { abstract Expr getInputArg(); diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Random.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/Random.qll index eceff8748743..e599ed82169b 100644 --- a/cpp/ql/lib/experimental/Quantum/OpenSSL/Random.qll +++ b/cpp/ql/lib/experimental/Quantum/OpenSSL/Random.qll @@ -1,6 +1,5 @@ import cpp -private import experimental.Quantum.Language -private import codeql.cryptography.Model +private import experimental.quantum.Language private import LibraryDetector private import semmle.code.cpp.dataflow.new.DataFlow @@ -15,7 +14,5 @@ class OpenSSLRandomNumberGeneratorInstance extends Crypto::RandomNumberGeneratio result.asDefiningArgument() = this.(Call).getArgument(0) } - override predicate flowsTo(Crypto::FlowAwareElement other) { - ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) - } + override string getGeneratorName() { result = this.(Call).getTarget().getName() } } diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index 6bb19968c824..335360caeb26 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -6,8 +6,8 @@ extractor: cpp library: true upgrades: upgrades dependencies: - codeql/cryptography: ${workspace} codeql/dataflow: ${workspace} + codeql/experimental: ${workspace} codeql/mad: ${workspace} codeql/rangeanalysis: ${workspace} codeql/ssa: ${workspace} diff --git a/cpp/ql/src/experimental/Quantum/PrintCBOMGraph.ql b/cpp/ql/src/experimental/Quantum/PrintCBOMGraph.ql index d9658105aebf..f741e3c9f947 100644 --- a/cpp/ql/src/experimental/Quantum/PrintCBOMGraph.ql +++ b/cpp/ql/src/experimental/Quantum/PrintCBOMGraph.ql @@ -6,7 +6,7 @@ * @id cpp/print-cbom-graph */ -import experimental.Quantum.Language +import experimental.quantum.Language query predicate nodes(Crypto::NodeBase node, string key, string value) { Crypto::nodes_graph_impl(node, key, value) diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 6f7dc88157b2..572d5716e02a 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -1,4 +1,4 @@ -private import codeql.cryptography.Model +private import codeql.quantum.Model private import java as Language private import semmle.code.java.security.InsecureRandomnessQuery private import semmle.code.java.security.RandomQuery diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index 52fa4620b462..036218757a84 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -6,8 +6,8 @@ extractor: java library: true upgrades: upgrades dependencies: - codeql/cryptography: ${workspace} codeql/dataflow: ${workspace} + codeql/experimental: ${workspace} codeql/mad: ${workspace} codeql/rangeanalysis: ${workspace} codeql/regex: ${workspace} diff --git a/java/ql/src/experimental/Quantum/Analysis/ArtifactReuse.qll b/java/ql/src/experimental/Quantum/Analysis/ArtifactReuse.qll index de283f89775e..88598e615896 100644 --- a/java/ql/src/experimental/Quantum/Analysis/ArtifactReuse.qll +++ b/java/ql/src/experimental/Quantum/Analysis/ArtifactReuse.qll @@ -1,6 +1,6 @@ import java import semmle.code.java.dataflow.DataFlow -import experimental.Quantum.Language +import experimental.quantum.Language /** * Flow from any function that appears to return a value diff --git a/java/ql/src/experimental/Quantum/Analysis/InsecureNonceSource.ql b/java/ql/src/experimental/Quantum/Analysis/InsecureNonceSource.ql index 9c06884328bb..b2c6f919d5fe 100644 --- a/java/ql/src/experimental/Quantum/Analysis/InsecureNonceSource.ql +++ b/java/ql/src/experimental/Quantum/Analysis/InsecureNonceSource.ql @@ -8,7 +8,7 @@ * vulnerabilities such as replay attacks or key recovery. */ -import experimental.Quantum.Language +import experimental.quantum.Language predicate isInsecureNonceSource(Crypto::NonceArtifactNode n, Crypto::NodeBase src) { src = n.getSourceNode() and diff --git a/java/ql/src/experimental/Quantum/Analysis/KnownWeakKDFIterationCount.ql b/java/ql/src/experimental/Quantum/Analysis/KnownWeakKDFIterationCount.ql index 439295f74e36..701f3064e92a 100644 --- a/java/ql/src/experimental/Quantum/Analysis/KnownWeakKDFIterationCount.ql +++ b/java/ql/src/experimental/Quantum/Analysis/KnownWeakKDFIterationCount.ql @@ -5,7 +5,7 @@ */ import java -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::KeyDerivationOperationNode op, Literal l where diff --git a/java/ql/src/experimental/Quantum/Analysis/UnknownKDFIterationCount.ql b/java/ql/src/experimental/Quantum/Analysis/UnknownKDFIterationCount.ql index 0c91e66d52bc..4ce404f01b08 100644 --- a/java/ql/src/experimental/Quantum/Analysis/UnknownKDFIterationCount.ql +++ b/java/ql/src/experimental/Quantum/Analysis/UnknownKDFIterationCount.ql @@ -5,7 +5,7 @@ */ import java -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::KeyDerivationOperationNode op, Element e, string msg where diff --git a/java/ql/src/experimental/Quantum/Examples/BrokenCrypto.ql b/java/ql/src/experimental/Quantum/Examples/BrokenCrypto.ql index 020ac1b8925a..b4e9de9ac945 100644 --- a/java/ql/src/experimental/Quantum/Examples/BrokenCrypto.ql +++ b/java/ql/src/experimental/Quantum/Examples/BrokenCrypto.ql @@ -1,58 +1,55 @@ /** -* @name Use of a broken or risky cryptographic algorithm -* @description Using broken or weak cryptographic algorithms can allow an attacker to compromise security. -* @kind problem -* @problem.severity warning -* @security-severity 7.5 -* @precision high -* @id java/weak-cryptographic-algorithm-new-model -* @tags security -* external/cwe/cwe-327 -* external/cwe/cwe-328 -*/ - - + * @name Use of a broken or risky cryptographic algorithm + * @description Using broken or weak cryptographic algorithms can allow an attacker to compromise security. + * @kind problem + * @problem.severity warning + * @security-severity 7.5 + * @precision high + * @id java/weak-cryptographic-algorithm-new-model + * @tags security + * external/cwe/cwe-327 + * external/cwe/cwe-328 + */ //THIS QUERY IS A REPLICA OF: https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql //but uses the **NEW MODELLING** -import experimental.Quantum.Language - +import experimental.quantum.Language /** * Gets the name of an algorithm that is known to be insecure. */ string getAnInsecureAlgorithmName() { - result = - [ - "DES", "RC2", "RC4", "RC5", - // ARCFOUR is a variant of RC4 - "ARCFOUR", - // Encryption mode ECB like AES/ECB/NoPadding is vulnerable to replay and other attacks - "ECB", - // CBC mode of operation with PKCS#5 or PKCS#7 padding is vulnerable to padding oracle attacks - "AES/CBC/PKCS[57]Padding" - ] - } - - private string rankedInsecureAlgorithm(int i) { - result = rank[i](string s | s = getAnInsecureAlgorithmName()) - } - - private string insecureAlgorithmString(int i) { - i = 1 and result = rankedInsecureAlgorithm(i) - or - result = rankedInsecureAlgorithm(i) + "|" + insecureAlgorithmString(i - 1) - } - - /** - * Gets the regular expression used for matching strings that look like they - * contain an algorithm that is known to be insecure. - */ - string getInsecureAlgorithmRegex() { - result = algorithmRegex(insecureAlgorithmString(max(int i | exists(rankedInsecureAlgorithm(i))))) - } + result = + [ + "DES", "RC2", "RC4", "RC5", + // ARCFOUR is a variant of RC4 + "ARCFOUR", + // Encryption mode ECB like AES/ECB/NoPadding is vulnerable to replay and other attacks + "ECB", + // CBC mode of operation with PKCS#5 or PKCS#7 padding is vulnerable to padding oracle attacks + "AES/CBC/PKCS[57]Padding" + ] +} + +private string rankedInsecureAlgorithm(int i) { + result = rank[i](string s | s = getAnInsecureAlgorithmName()) +} + +private string insecureAlgorithmString(int i) { + i = 1 and result = rankedInsecureAlgorithm(i) + or + result = rankedInsecureAlgorithm(i) + "|" + insecureAlgorithmString(i - 1) +} + +/** + * Gets the regular expression used for matching strings that look like they + * contain an algorithm that is known to be insecure. + */ +string getInsecureAlgorithmRegex() { + result = algorithmRegex(insecureAlgorithmString(max(int i | exists(rankedInsecureAlgorithm(i))))) +} - bindingset[algorithmString] +bindingset[algorithmString] private string algorithmRegex(string algorithmString) { // Algorithms usually appear in names surrounded by characters that are not // alphabetical characters in the same case. This handles the upper and lower @@ -67,11 +64,12 @@ private string algorithmRegex(string algorithmString) { "((^|.*[A-Z]{2}|.*[^a-zA-Z])(" + algorithmString.toLowerCase() + ")([^a-z].*|$))" } -from Crypto::Algorithm alg -where alg.getAlgorithmName().regexpMatch(getInsecureAlgorithmRegex()) and -// Exclude RSA/ECB/.* ciphers. -not alg.getAlgorithmName().regexpMatch("RSA/ECB.*") and -// Exclude German and French sentences. -not alg.getAlgorithmName().regexpMatch(".*\\p{IsLowercase} des \\p{IsLetter}.*") +from Crypto::Algorithm alg +where + alg.getAlgorithmName().regexpMatch(getInsecureAlgorithmRegex()) and + // Exclude RSA/ECB/.* ciphers. + not alg.getAlgorithmName().regexpMatch("RSA/ECB.*") and + // Exclude German and French sentences. + not alg.getAlgorithmName().regexpMatch(".*\\p{IsLowercase} des \\p{IsLetter}.*") select alg, "Cryptographic algorithm $@ is weak and should not be used.", alg, -alg.getAlgorithmName() + alg.getAlgorithmName() diff --git a/java/ql/src/experimental/Quantum/Examples/InsecureOrUnknownNonceAtOperation.ql b/java/ql/src/experimental/Quantum/Examples/InsecureOrUnknownNonceAtOperation.ql index a9eb70076a0a..fc2387fda374 100644 --- a/java/ql/src/experimental/Quantum/Examples/InsecureOrUnknownNonceAtOperation.ql +++ b/java/ql/src/experimental/Quantum/Examples/InsecureOrUnknownNonceAtOperation.ql @@ -4,7 +4,7 @@ * @kind problem */ -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::NonceArtifactNode n, Crypto::KeyOperationNode op, Crypto::FlowAwareElement src, string msg diff --git a/java/ql/src/experimental/Quantum/Examples/TestAESGCMNonce.ql b/java/ql/src/experimental/Quantum/Examples/TestAESGCMNonce.ql index 985527318ffa..096cfa822161 100644 --- a/java/ql/src/experimental/Quantum/Examples/TestAESGCMNonce.ql +++ b/java/ql/src/experimental/Quantum/Examples/TestAESGCMNonce.ql @@ -2,7 +2,7 @@ * @name "PQC Test" */ -import experimental.Quantum.Language +import experimental.quantum.Language class AESGCMAlgorithmNode extends Crypto::KeyOperationAlgorithmNode { AESGCMAlgorithmNode() { diff --git a/java/ql/src/experimental/Quantum/Examples/TestCipher.ql b/java/ql/src/experimental/Quantum/Examples/TestCipher.ql index 503d60039229..2b1d6ebcf06e 100644 --- a/java/ql/src/experimental/Quantum/Examples/TestCipher.ql +++ b/java/ql/src/experimental/Quantum/Examples/TestCipher.ql @@ -2,7 +2,7 @@ * @name "Key operation slice table demo query" */ -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::KeyOperationNode op, Crypto::KeyOperationAlgorithmNode a, diff --git a/java/ql/src/experimental/Quantum/Examples/TestCipherKey.ql b/java/ql/src/experimental/Quantum/Examples/TestCipherKey.ql index c489320528d0..9408aac7e3ba 100644 --- a/java/ql/src/experimental/Quantum/Examples/TestCipherKey.ql +++ b/java/ql/src/experimental/Quantum/Examples/TestCipherKey.ql @@ -2,7 +2,7 @@ * @name "PQC Test" */ -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::KeyOperationNode op, Crypto::CipherAlgorithmNode a, Crypto::KeyArtifactNode k where diff --git a/java/ql/src/experimental/Quantum/Examples/TestHash.ql b/java/ql/src/experimental/Quantum/Examples/TestHash.ql index 76ef6951a7e8..b319c95a62b1 100644 --- a/java/ql/src/experimental/Quantum/Examples/TestHash.ql +++ b/java/ql/src/experimental/Quantum/Examples/TestHash.ql @@ -2,7 +2,7 @@ * @name "Hash operation slice table demo query" */ -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::HashOperationNode op, Crypto::HashAlgorithmNode alg where alg = op.getAKnownAlgorithm() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricAlgorithm.ql index 1e5a7c5bced1..7ae2a0f08880 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricAlgorithm.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricAlgorithm.ql @@ -5,7 +5,7 @@ */ import java -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::AlgorithmNode a where Crypto::isKnownAsymmetricAlgorithm(a) diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql index 962a6b720159..c7242ed11c50 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql @@ -5,7 +5,7 @@ */ import java -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::KeyOperationAlgorithmNode a where a.getAlgorithmType() instanceof Crypto::KeyOpAlg::AsymmetricCipherAlgorithm diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql index 0900401b80d7..a14a0dfbaba7 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql @@ -5,7 +5,7 @@ */ import java -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::OperationNode op, Crypto::AlgorithmNode a where a = op.getAKnownAlgorithm() and Crypto::isKnownAsymmetricAlgorithm(a) diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownCipherAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownCipherAlgorithm.ql index 4096fe16d29c..f126c3d9ae11 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/KnownCipherAlgorithm.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownCipherAlgorithm.ql @@ -5,7 +5,7 @@ */ import java -import experimental.Quantum.Language +import experimental.quantum.Language // TODO: should there be a cipher algorithm node? from Crypto::KeyOperationAlgorithmNode a diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql index 048bcd8182ce..c3f69d91cb70 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql @@ -5,7 +5,7 @@ */ import java -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::EllipticCurveNode a select a, "Instance of elliptic curve algorithm " + a.getAlgorithmName() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingAlgorithm.ql index 632872725e71..ed24b62364dd 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingAlgorithm.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingAlgorithm.ql @@ -5,7 +5,7 @@ */ import java -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::HashAlgorithmNode a select a, "Instance of hashing algorithm " + a.getAlgorithmName() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperation.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperation.ql index b3556393173d..23fc6235e802 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperation.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperation.ql @@ -5,7 +5,7 @@ */ import java -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::HashOperationNode op select op, "Known hashing operation" diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperationAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperationAlgorithm.ql index ce0f4d37d4d1..8af3c09dd10e 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperationAlgorithm.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperationAlgorithm.ql @@ -5,7 +5,7 @@ */ import java -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::OperationNode op, Crypto::HashAlgorithmNode a where a = op.getAKnownAlgorithm() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql index 584ffef0bbfa..e0970353a987 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql @@ -5,7 +5,7 @@ */ import java -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::KeyDerivationAlgorithmNode alg select alg, "Known key derivation algorithm " + alg.getAlgorithmName() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperation.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperation.ql index 8c77b2aa984d..240a4ea3fc54 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperation.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperation.ql @@ -5,7 +5,7 @@ */ import java -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::KeyDerivationOperationNode op select op, "Known key derivation operation" diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql index cf9a4e96f4da..9afbd7d7f2f7 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql @@ -1,11 +1,12 @@ /** * @name Detects operations where the algorithm applied is a known key derivation algorithm - * @id java/crypto_inventory_slices/operation_with_known_key_derivation_algorithm + * @id java/cryptography-inventory-slices/operation-known-key-derivation-algorithm + * @description This query identifies operations that utilize a known key derivation algorithm. * @kind problem */ import java -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::OperationNode op, Crypto::KeyDerivationAlgorithmNode a where a = op.getAKnownAlgorithm() diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql index 21949f1c8c6d..d8467305df97 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql @@ -5,7 +5,7 @@ */ import java -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::KeyOperationAlgorithmNode a where a.getAlgorithmType() instanceof Crypto::KeyOpAlg::SymmetricCipherAlgorithm diff --git a/java/ql/src/experimental/Quantum/InventorySlices/LikelyCryptoAPIFunction.ql b/java/ql/src/experimental/Quantum/InventorySlices/LikelyCryptoAPIFunction.ql index 0076c478dec9..d02524a7df37 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/LikelyCryptoAPIFunction.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/LikelyCryptoAPIFunction.ql @@ -5,7 +5,7 @@ */ import java -import experimental.Quantum.Language +import experimental.quantum.Language from Callable f, Parameter p, Crypto::OperationNode op where diff --git a/java/ql/src/experimental/Quantum/InventorySlices/UnknownOperationAlgorithm.ql b/java/ql/src/experimental/Quantum/InventorySlices/UnknownOperationAlgorithm.ql index 61a27c75dac2..7559579d863f 100644 --- a/java/ql/src/experimental/Quantum/InventorySlices/UnknownOperationAlgorithm.ql +++ b/java/ql/src/experimental/Quantum/InventorySlices/UnknownOperationAlgorithm.ql @@ -5,7 +5,7 @@ */ import java -import experimental.Quantum.Language +import experimental.quantum.Language //TODO: can we have an unknown node concept? from Crypto::OperationNode op, Element e, string msg diff --git a/java/ql/src/experimental/Quantum/PrintCBOMGraph.ql b/java/ql/src/experimental/Quantum/PrintCBOMGraph.ql index 063cda564b60..bc79d5d4ce6a 100644 --- a/java/ql/src/experimental/Quantum/PrintCBOMGraph.ql +++ b/java/ql/src/experimental/Quantum/PrintCBOMGraph.ql @@ -6,7 +6,7 @@ * @id java/print-cbom-graph */ -import experimental.Quantum.Language +import experimental.quantum.Language query predicate nodes(Crypto::NodeBase node, string key, string value) { Crypto::nodes_graph_impl(node, key, value) diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/experimental/codeql/quantum/Model.qll similarity index 100% rename from shared/cryptography/codeql/cryptography/Model.qll rename to shared/experimental/codeql/quantum/Model.qll diff --git a/shared/cryptography/qlpack.yml b/shared/experimental/qlpack.yml similarity index 81% rename from shared/cryptography/qlpack.yml rename to shared/experimental/qlpack.yml index 768c64a0704e..2976c56ba492 100644 --- a/shared/cryptography/qlpack.yml +++ b/shared/experimental/qlpack.yml @@ -1,4 +1,4 @@ -name: codeql/cryptography +name: codeql/experimental version: 0.0.0-dev groups: shared library: true From ac72abd3a69d69d37701c0622f837460a2a115ed Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 02:35:09 +0200 Subject: [PATCH 268/336] Refactor directory structure (shared experimental) --- cpp/ql/lib/experimental/Quantum/Language.qll | 2 +- cpp/ql/src/experimental/Quantum/Test2.ql | 2 +- java/ql/lib/experimental/Quantum/Language.qll | 2 +- shared/experimental/codeql/{ => experimental}/quantum/Model.qll | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename shared/experimental/codeql/{ => experimental}/quantum/Model.qll (100%) diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index c3e2e3ad55f4..176db9736adb 100644 --- a/cpp/ql/lib/experimental/Quantum/Language.qll +++ b/cpp/ql/lib/experimental/Quantum/Language.qll @@ -1,4 +1,4 @@ -import codeql.quantum.Model +import codeql.experimental.quantum.Model import semmle.code.cpp.dataflow.new.DataFlow private import cpp as Lang diff --git a/cpp/ql/src/experimental/Quantum/Test2.ql b/cpp/ql/src/experimental/Quantum/Test2.ql index 3f48f156a430..98a35d2a9e9f 100644 --- a/cpp/ql/src/experimental/Quantum/Test2.ql +++ b/cpp/ql/src/experimental/Quantum/Test2.ql @@ -2,7 +2,7 @@ * @name "PQC Test" */ -import experimental.Quantum.Language +import experimental.quantum.Language from Crypto::NodeBase node select node diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 572d5716e02a..eaf63aa5be25 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -1,4 +1,4 @@ -private import codeql.quantum.Model +private import codeql.experimental.quantum.Model private import java as Language private import semmle.code.java.security.InsecureRandomnessQuery private import semmle.code.java.security.RandomQuery diff --git a/shared/experimental/codeql/quantum/Model.qll b/shared/experimental/codeql/experimental/quantum/Model.qll similarity index 100% rename from shared/experimental/codeql/quantum/Model.qll rename to shared/experimental/codeql/experimental/quantum/Model.qll From 7339dd0077664ae41728488667df1f7368eef996 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 02:39:40 +0200 Subject: [PATCH 269/336] Rename "Quantum" to "quantum" in dir structure --- cpp/ql/lib/experimental/{Quantum => quantum}/Language.qll | 0 .../OpenSSL/AlgorithmInstances/AlgToAVCFlow.qll | 0 .../OpenSSL/AlgorithmInstances/BlockAlgorithmInstance.qll | 0 .../OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll | 0 .../OpenSSL/AlgorithmInstances/HashAlgorithmInstance.qll | 0 .../OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll | 0 .../OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstanceBase.qll | 0 .../OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstances.qll | 0 .../OpenSSL/AlgorithmInstances/PaddingAlgorithmInstance.qll | 0 .../AlgorithmValueConsumers/CipherAlgorithmValueConsumer.qll | 0 .../AlgorithmValueConsumers/DirectAlgorithmValueConsumer.qll | 0 .../AlgorithmValueConsumers/HashAlgorithmValueConsumer.qll | 0 .../AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumerBase.qll | 0 .../AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumers.qll | 0 .../AlgorithmValueConsumers/PaddingAlgorithmValueConsumer.qll | 0 cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/CtxFlow.qll | 0 .../experimental/{Quantum => quantum}/OpenSSL/LibraryDetector.qll | 0 cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/OpenSSL.qll | 0 .../OpenSSL/Operations/EVPCipherInitializer.qll | 0 .../OpenSSL/Operations/EVPCipherOperation.qll | 0 .../OpenSSL/Operations/EVPHashInitializer.qll | 0 .../{Quantum => quantum}/OpenSSL/Operations/EVPHashOperation.qll | 0 .../OpenSSL/Operations/OpenSSLOperationBase.qll | 0 .../{Quantum => quantum}/OpenSSL/Operations/OpenSSLOperations.qll | 0 cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/Random.qll | 0 cpp/ql/src/experimental/{Quantum => quantum}/PrintCBOMGraph.ql | 0 cpp/ql/src/experimental/{Quantum => quantum}/Test2.ql | 0 java/ql/lib/experimental/{Quantum => quantum}/JCA.qll | 0 java/ql/lib/experimental/{Quantum => quantum}/Language.qll | 0 .../experimental/{Quantum => quantum}/Analysis/ArtifactReuse.qll | 0 .../{Quantum => quantum}/Analysis/InsecureNonceSource.ql | 0 .../{Quantum => quantum}/Analysis/KnownWeakKDFIterationCount.ql | 0 .../src/experimental/{Quantum => quantum}/Analysis/ReusedNonce.ql | 0 .../{Quantum => quantum}/Analysis/UnknownKDFIterationCount.ql | 0 .../experimental/{Quantum => quantum}/Examples/BrokenCrypto.ql | 0 .../Examples/InsecureOrUnknownNonceAtOperation.ql | 0 .../experimental/{Quantum => quantum}/Examples/TestAESGCMNonce.ql | 0 .../src/experimental/{Quantum => quantum}/Examples/TestCipher.ql | 0 .../experimental/{Quantum => quantum}/Examples/TestCipherKey.ql | 0 .../ql/src/experimental/{Quantum => quantum}/Examples/TestHash.ql | 0 .../InventorySlices/KnownAsymmetricAlgorithm.ql | 0 .../InventorySlices/KnownAsymmetricCipherAlgorithm.ql | 0 .../InventorySlices/KnownAsymmetricOperationAlgorithm.ql | 0 .../{Quantum => quantum}/InventorySlices/KnownCipherAlgorithm.ql | 0 .../InventorySlices/KnownEllipticCurveAlgorithm.ql | 0 .../{Quantum => quantum}/InventorySlices/KnownHashingAlgorithm.ql | 0 .../{Quantum => quantum}/InventorySlices/KnownHashingOperation.ql | 0 .../InventorySlices/KnownHashingOperationAlgorithm.ql | 0 .../InventorySlices/KnownKeyDerivationAlgorithm.ql | 0 .../InventorySlices/KnownKeyDerivationOperation.ql | 0 .../InventorySlices/KnownKeyDerivationOperationAlgorithm.ql | 0 .../InventorySlices/KnownSymmetricCipherAlgorithm.ql | 0 .../InventorySlices/LikelyCryptoAPIFunction.ql | 0 .../InventorySlices/UnknownOperationAlgorithm.ql | 0 java/ql/src/experimental/{Quantum => quantum}/PrintCBOMGraph.ql | 0 55 files changed, 0 insertions(+), 0 deletions(-) rename cpp/ql/lib/experimental/{Quantum => quantum}/Language.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/AlgorithmInstances/AlgToAVCFlow.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/AlgorithmInstances/BlockAlgorithmInstance.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/AlgorithmInstances/HashAlgorithmInstance.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstanceBase.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstances.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/AlgorithmInstances/PaddingAlgorithmInstance.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/AlgorithmValueConsumers/CipherAlgorithmValueConsumer.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/AlgorithmValueConsumers/DirectAlgorithmValueConsumer.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/AlgorithmValueConsumers/HashAlgorithmValueConsumer.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumerBase.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumers.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/AlgorithmValueConsumers/PaddingAlgorithmValueConsumer.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/CtxFlow.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/LibraryDetector.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/OpenSSL.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/Operations/EVPCipherInitializer.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/Operations/EVPCipherOperation.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/Operations/EVPHashInitializer.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/Operations/EVPHashOperation.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/Operations/OpenSSLOperationBase.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/Operations/OpenSSLOperations.qll (100%) rename cpp/ql/lib/experimental/{Quantum => quantum}/OpenSSL/Random.qll (100%) rename cpp/ql/src/experimental/{Quantum => quantum}/PrintCBOMGraph.ql (100%) rename cpp/ql/src/experimental/{Quantum => quantum}/Test2.ql (100%) rename java/ql/lib/experimental/{Quantum => quantum}/JCA.qll (100%) rename java/ql/lib/experimental/{Quantum => quantum}/Language.qll (100%) rename java/ql/src/experimental/{Quantum => quantum}/Analysis/ArtifactReuse.qll (100%) rename java/ql/src/experimental/{Quantum => quantum}/Analysis/InsecureNonceSource.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/Analysis/KnownWeakKDFIterationCount.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/Analysis/ReusedNonce.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/Analysis/UnknownKDFIterationCount.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/Examples/BrokenCrypto.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/Examples/InsecureOrUnknownNonceAtOperation.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/Examples/TestAESGCMNonce.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/Examples/TestCipher.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/Examples/TestCipherKey.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/Examples/TestHash.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/InventorySlices/KnownAsymmetricAlgorithm.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/InventorySlices/KnownAsymmetricCipherAlgorithm.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/InventorySlices/KnownAsymmetricOperationAlgorithm.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/InventorySlices/KnownCipherAlgorithm.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/InventorySlices/KnownEllipticCurveAlgorithm.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/InventorySlices/KnownHashingAlgorithm.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/InventorySlices/KnownHashingOperation.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/InventorySlices/KnownHashingOperationAlgorithm.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/InventorySlices/KnownKeyDerivationAlgorithm.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/InventorySlices/KnownKeyDerivationOperation.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/InventorySlices/KnownSymmetricCipherAlgorithm.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/InventorySlices/LikelyCryptoAPIFunction.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/InventorySlices/UnknownOperationAlgorithm.ql (100%) rename java/ql/src/experimental/{Quantum => quantum}/PrintCBOMGraph.ql (100%) diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/quantum/Language.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/Language.qll rename to cpp/ql/lib/experimental/quantum/Language.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/AlgToAVCFlow.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/AlgToAVCFlow.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/AlgToAVCFlow.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/AlgToAVCFlow.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/BlockAlgorithmInstance.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/BlockAlgorithmInstance.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/BlockAlgorithmInstance.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/BlockAlgorithmInstance.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/HashAlgorithmInstance.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/HashAlgorithmInstance.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/HashAlgorithmInstance.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/HashAlgorithmInstance.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstanceBase.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstanceBase.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstanceBase.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstanceBase.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstances.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstances.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstances.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/OpenSSLAlgorithmInstances.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/PaddingAlgorithmInstance.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/PaddingAlgorithmInstance.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmInstances/PaddingAlgorithmInstance.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/PaddingAlgorithmInstance.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/CipherAlgorithmValueConsumer.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmValueConsumers/CipherAlgorithmValueConsumer.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/CipherAlgorithmValueConsumer.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmValueConsumers/CipherAlgorithmValueConsumer.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/DirectAlgorithmValueConsumer.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmValueConsumers/DirectAlgorithmValueConsumer.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/DirectAlgorithmValueConsumer.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmValueConsumers/DirectAlgorithmValueConsumer.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/HashAlgorithmValueConsumer.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmValueConsumers/HashAlgorithmValueConsumer.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/HashAlgorithmValueConsumer.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmValueConsumers/HashAlgorithmValueConsumer.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumerBase.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumerBase.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumerBase.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumerBase.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumers.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumers.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumers.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmValueConsumers/OpenSSLAlgorithmValueConsumers.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/PaddingAlgorithmValueConsumer.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmValueConsumers/PaddingAlgorithmValueConsumer.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/AlgorithmValueConsumers/PaddingAlgorithmValueConsumer.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmValueConsumers/PaddingAlgorithmValueConsumer.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/CtxFlow.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/CtxFlow.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/LibraryDetector.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/LibraryDetector.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/LibraryDetector.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/LibraryDetector.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/OpenSSL.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSL.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/OpenSSL.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherInitializer.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherInitializer.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherInitializer.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherInitializer.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherOperation.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherOperation.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPCipherOperation.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherOperation.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashInitializer.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPHashInitializer.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashInitializer.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPHashInitializer.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashOperation.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPHashOperation.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/EVPHashOperation.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPHashOperation.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperationBase.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/OpenSSLOperationBase.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperationBase.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/Operations/OpenSSLOperationBase.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperations.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/OpenSSLOperations.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/Operations/OpenSSLOperations.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/Operations/OpenSSLOperations.qll diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/Random.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/Random.qll similarity index 100% rename from cpp/ql/lib/experimental/Quantum/OpenSSL/Random.qll rename to cpp/ql/lib/experimental/quantum/OpenSSL/Random.qll diff --git a/cpp/ql/src/experimental/Quantum/PrintCBOMGraph.ql b/cpp/ql/src/experimental/quantum/PrintCBOMGraph.ql similarity index 100% rename from cpp/ql/src/experimental/Quantum/PrintCBOMGraph.ql rename to cpp/ql/src/experimental/quantum/PrintCBOMGraph.ql diff --git a/cpp/ql/src/experimental/Quantum/Test2.ql b/cpp/ql/src/experimental/quantum/Test2.ql similarity index 100% rename from cpp/ql/src/experimental/Quantum/Test2.ql rename to cpp/ql/src/experimental/quantum/Test2.ql diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/quantum/JCA.qll similarity index 100% rename from java/ql/lib/experimental/Quantum/JCA.qll rename to java/ql/lib/experimental/quantum/JCA.qll diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/quantum/Language.qll similarity index 100% rename from java/ql/lib/experimental/Quantum/Language.qll rename to java/ql/lib/experimental/quantum/Language.qll diff --git a/java/ql/src/experimental/Quantum/Analysis/ArtifactReuse.qll b/java/ql/src/experimental/quantum/Analysis/ArtifactReuse.qll similarity index 100% rename from java/ql/src/experimental/Quantum/Analysis/ArtifactReuse.qll rename to java/ql/src/experimental/quantum/Analysis/ArtifactReuse.qll diff --git a/java/ql/src/experimental/Quantum/Analysis/InsecureNonceSource.ql b/java/ql/src/experimental/quantum/Analysis/InsecureNonceSource.ql similarity index 100% rename from java/ql/src/experimental/Quantum/Analysis/InsecureNonceSource.ql rename to java/ql/src/experimental/quantum/Analysis/InsecureNonceSource.ql diff --git a/java/ql/src/experimental/Quantum/Analysis/KnownWeakKDFIterationCount.ql b/java/ql/src/experimental/quantum/Analysis/KnownWeakKDFIterationCount.ql similarity index 100% rename from java/ql/src/experimental/Quantum/Analysis/KnownWeakKDFIterationCount.ql rename to java/ql/src/experimental/quantum/Analysis/KnownWeakKDFIterationCount.ql diff --git a/java/ql/src/experimental/Quantum/Analysis/ReusedNonce.ql b/java/ql/src/experimental/quantum/Analysis/ReusedNonce.ql similarity index 100% rename from java/ql/src/experimental/Quantum/Analysis/ReusedNonce.ql rename to java/ql/src/experimental/quantum/Analysis/ReusedNonce.ql diff --git a/java/ql/src/experimental/Quantum/Analysis/UnknownKDFIterationCount.ql b/java/ql/src/experimental/quantum/Analysis/UnknownKDFIterationCount.ql similarity index 100% rename from java/ql/src/experimental/Quantum/Analysis/UnknownKDFIterationCount.ql rename to java/ql/src/experimental/quantum/Analysis/UnknownKDFIterationCount.ql diff --git a/java/ql/src/experimental/Quantum/Examples/BrokenCrypto.ql b/java/ql/src/experimental/quantum/Examples/BrokenCrypto.ql similarity index 100% rename from java/ql/src/experimental/Quantum/Examples/BrokenCrypto.ql rename to java/ql/src/experimental/quantum/Examples/BrokenCrypto.ql diff --git a/java/ql/src/experimental/Quantum/Examples/InsecureOrUnknownNonceAtOperation.ql b/java/ql/src/experimental/quantum/Examples/InsecureOrUnknownNonceAtOperation.ql similarity index 100% rename from java/ql/src/experimental/Quantum/Examples/InsecureOrUnknownNonceAtOperation.ql rename to java/ql/src/experimental/quantum/Examples/InsecureOrUnknownNonceAtOperation.ql diff --git a/java/ql/src/experimental/Quantum/Examples/TestAESGCMNonce.ql b/java/ql/src/experimental/quantum/Examples/TestAESGCMNonce.ql similarity index 100% rename from java/ql/src/experimental/Quantum/Examples/TestAESGCMNonce.ql rename to java/ql/src/experimental/quantum/Examples/TestAESGCMNonce.ql diff --git a/java/ql/src/experimental/Quantum/Examples/TestCipher.ql b/java/ql/src/experimental/quantum/Examples/TestCipher.ql similarity index 100% rename from java/ql/src/experimental/Quantum/Examples/TestCipher.ql rename to java/ql/src/experimental/quantum/Examples/TestCipher.ql diff --git a/java/ql/src/experimental/Quantum/Examples/TestCipherKey.ql b/java/ql/src/experimental/quantum/Examples/TestCipherKey.ql similarity index 100% rename from java/ql/src/experimental/Quantum/Examples/TestCipherKey.ql rename to java/ql/src/experimental/quantum/Examples/TestCipherKey.ql diff --git a/java/ql/src/experimental/Quantum/Examples/TestHash.ql b/java/ql/src/experimental/quantum/Examples/TestHash.ql similarity index 100% rename from java/ql/src/experimental/Quantum/Examples/TestHash.ql rename to java/ql/src/experimental/quantum/Examples/TestHash.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricAlgorithm.ql rename to java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql rename to java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql rename to java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownCipherAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownCipherAlgorithm.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventorySlices/KnownCipherAlgorithm.ql rename to java/ql/src/experimental/quantum/InventorySlices/KnownCipherAlgorithm.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql rename to java/ql/src/experimental/quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownHashingAlgorithm.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventorySlices/KnownHashingAlgorithm.ql rename to java/ql/src/experimental/quantum/InventorySlices/KnownHashingAlgorithm.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperation.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperation.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperation.ql rename to java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperation.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperationAlgorithm.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventorySlices/KnownHashingOperationAlgorithm.ql rename to java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperationAlgorithm.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql rename to java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperation.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperation.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperation.ql rename to java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperation.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql rename to java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql rename to java/ql/src/experimental/quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/LikelyCryptoAPIFunction.ql b/java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventorySlices/LikelyCryptoAPIFunction.ql rename to java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql diff --git a/java/ql/src/experimental/Quantum/InventorySlices/UnknownOperationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/UnknownOperationAlgorithm.ql similarity index 100% rename from java/ql/src/experimental/Quantum/InventorySlices/UnknownOperationAlgorithm.ql rename to java/ql/src/experimental/quantum/InventorySlices/UnknownOperationAlgorithm.ql diff --git a/java/ql/src/experimental/Quantum/PrintCBOMGraph.ql b/java/ql/src/experimental/quantum/PrintCBOMGraph.ql similarity index 100% rename from java/ql/src/experimental/Quantum/PrintCBOMGraph.ql rename to java/ql/src/experimental/quantum/PrintCBOMGraph.ql From 0066f74d3fe7f31665f78ae43faaf5b6a20d12c8 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 02:40:56 +0200 Subject: [PATCH 270/336] Delete development scripts --- misc/scripts/cryptography/cbom.sh | 8 -- misc/scripts/cryptography/generate_cbom.py | 117 --------------------- 2 files changed, 125 deletions(-) delete mode 100755 misc/scripts/cryptography/cbom.sh delete mode 100644 misc/scripts/cryptography/generate_cbom.py diff --git a/misc/scripts/cryptography/cbom.sh b/misc/scripts/cryptography/cbom.sh deleted file mode 100755 index ef558ccf432e..000000000000 --- a/misc/scripts/cryptography/cbom.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -CODEQL_PATH="/Users/nicolaswill/.local/share/gh/extensions/gh-codeql/dist/release/v2.20.4/codeql" -DATABASE_PATH="/Users/nicolaswill/pqc/gpt-crypto-test-cases/gpt_ai_gen_jca_test_cases_db" -QUERY_FILE="/Users/nicolaswill/pqc/codeql/java/ql/src/experimental/Quantum/PrintCBOMGraph.ql" -OUTPUT_DIR="graph_output" - -python3 generate_cbom.py -c "$CODEQL_PATH" -d "$DATABASE_PATH" -q "$QUERY_FILE" -o "$OUTPUT_DIR" diff --git a/misc/scripts/cryptography/generate_cbom.py b/misc/scripts/cryptography/generate_cbom.py deleted file mode 100644 index 6bd0d19712c5..000000000000 --- a/misc/scripts/cryptography/generate_cbom.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env python3 - -import os -import re -import sys -import argparse -import subprocess -import xml.etree.ElementTree as ET - -def run_codeql_analysis(codeql_path, database_path, query_path, output_dir): - """Runs the CodeQL analysis and generates a DGML file.""" - os.makedirs(output_dir, exist_ok=True) - command = [ - codeql_path, "database", "analyze", database_path, query_path, - "--rerun", "--format=dgml", "--output", output_dir - ] - - print(f"Running CodeQL analysis: {' '.join(command)}") - result = subprocess.run(command, capture_output=True, text=True) - - if result.returncode == 0: - print("Analysis completed successfully.") - else: - print("Analysis failed.") - print(result.stderr) - sys.exit(1) - - return result.returncode - - -def convert_dgml_to_dot(dgml_file, dot_file): - """Converts the DGML file to DOT format using the exact original implementation.""" - print(f"Processing DGML file: {dgml_file}") - - # Read source DGML - with open(dgml_file, "r", encoding="utf-8") as f: - xml_content = f.read() - - root = ET.fromstring(xml_content) - - # Form dot element sequence - body_l = ["digraph cbom {", - "node [shape=box];" - ] - - # Process nodes - for node in root.find("{http://schemas.microsoft.com/vs/2009/dgml}Nodes"): - att = node.attrib - node_id = att['Id'] - label_parts = [] - for key, value in att.items(): - if key == 'Id': - continue - elif key == 'Label': - label_parts.append(value) - else: - label_parts.append(f"{key}={value}") - label = "\\n".join(label_parts) - # Escape forward slashes and double quotes - label = label.replace("/", "\\/") - label = label.replace("\"", "\\\"") - prop_l = [f'label="{label}"'] - node_s = f'nd_{node_id} [{", ".join(prop_l)}];' - body_l.append(node_s) - - # Process edges - for edge in root.find("{http://schemas.microsoft.com/vs/2009/dgml}Links"): - att = edge.attrib - edge_label = att.get("Label", "") - edge_label = edge_label.replace("/", "\\/") - edge_label = edge_label.replace("\"", "\\\"") - edge_s = 'nd_{} -> nd_{} [label="{}"];'.format( - att["Source"], att["Target"], edge_label) - body_l.append(edge_s) - - body_l.append("}") - - # Write DOT output - with open(dot_file, "w", encoding="utf-8") as f: - f.write("\n".join(body_l)) - - print(f"DGML file successfully converted to DOT format: {dot_file}") - - -def main(): - parser = argparse.ArgumentParser(description="Run CodeQL analysis and convert DGML to DOT.") - parser.add_argument("-c", "--codeql", required=True, help="Path to CodeQL CLI executable.") - parser.add_argument("-d", "--database", required=True, help="Path to the CodeQL database.") - parser.add_argument("-q", "--query", required=True, help="Path to the .ql query file.") - parser.add_argument("--queryid", required=True, help="Query ID for the analysis.") - parser.add_argument("-o", "--output", required=True, help="Output directory for analysis results.") - - args = parser.parse_args() - - # Run CodeQL analysis - run_codeql_analysis(args.codeql, args.database, args.query, args.output) - - # Locate DGML file - ALLOWED_QUERY_ID = re.compile(r'^[a-zA-Z0-9_\-]+$') - - if not ALLOWED_QUERY_ID.match(args.queryid): - print("Invalid query_id provided: '%s'. Allowed characters: letters, digits, '_', and '-'.", args.queryid) - sys.exit(1) - - dgml_file = os.path.join(args.output, "java", '{}.dgml'.format(args.queryid)) - dot_file = dgml_file.replace(".dgml", ".dot") - - if os.path.exists(dgml_file): - # Convert DGML to DOT - convert_dgml_to_dot(dgml_file, dot_file) - else: - print(f"No DGML file found in {args.output}.") - sys.exit(1) - - -if __name__ == "__main__": - main() From a7ebe4a51a249774a0d5a48ae671a240de2e5e5f Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 02:43:29 +0200 Subject: [PATCH 271/336] Fix typo in asymmetric inventory slice query id --- .../quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql index c7242ed11c50..b903e152a299 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql @@ -1,6 +1,6 @@ /** * @name Detects known asymmetric cipher algorithms - * @id java/crypto_inventory_slices/known_symmetric_cipher_algorithm + * @id java/crypto_inventory_slices/known_asymmetric_cipher_algorithm * @kind problem */ From e956d041dc9cc405df5cc67ddf839157e14d76ab Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 02:51:53 +0200 Subject: [PATCH 272/336] Format LibraryDetector.qll --- .../lib/experimental/quantum/OpenSSL/LibraryDetector.qll | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cpp/ql/lib/experimental/quantum/OpenSSL/LibraryDetector.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/LibraryDetector.qll index 3cd359ce58b3..5ff02cd95197 100644 --- a/cpp/ql/lib/experimental/quantum/OpenSSL/LibraryDetector.qll +++ b/cpp/ql/lib/experimental/quantum/OpenSSL/LibraryDetector.qll @@ -1,10 +1,7 @@ import cpp predicate isPossibleOpenSSLFunction(Function f) { - isPossibleOpenSSLLocation(f.getADeclarationLocation()) - } - -predicate isPossibleOpenSSLLocation(Location l){ - l.toString().toLowerCase().matches("%openssl%") + isPossibleOpenSSLLocation(f.getADeclarationLocation()) } - \ No newline at end of file + +predicate isPossibleOpenSSLLocation(Location l) { l.toString().toLowerCase().matches("%openssl%") } From 1d8a57e7da529e38708480d4bc0684723ff1443f Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 02:56:52 +0200 Subject: [PATCH 273/336] Fix EVP Cipher class, predicate, and comment typos --- .../Operations/EVPCipherInitializer.qll | 28 +++++++++---------- .../OpenSSL/Operations/EVPCipherOperation.qll | 6 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherInitializer.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherInitializer.qll index fdf60ef757e8..3e8607ef8ecb 100644 --- a/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherInitializer.qll +++ b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherInitializer.qll @@ -10,14 +10,14 @@ module EncValToInitEncArgConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source.asExpr().getValue().toInt() in [0, 1] } predicate isSink(DataFlow::Node sink) { - exists(EVP_Cipher_Inititalizer initCall | sink.asExpr() = initCall.getOperataionSubtypeArg()) + exists(EVP_Cipher_Initializer initCall | sink.asExpr() = initCall.getOperationSubtypeArg()) } } module EncValToInitEncArgFlow = DataFlow::Global; int getEncConfigValue(Expr e) { - exists(EVP_Cipher_Inititalizer initCall | e = initCall.getOperataionSubtypeArg()) and + exists(EVP_Cipher_Initializer initCall | e = initCall.getOperationSubtypeArg()) and exists(DataFlow::Node a, DataFlow::Node b | EncValToInitEncArgFlow::flow(a, b) and b.asExpr() = e and result = a.asExpr().getValue().toInt() ) @@ -34,7 +34,7 @@ Crypto::KeyOperationSubtype intToCipherOperationSubtype(int i) { } // TODO: need to add key consumer -abstract class EVP_Cipher_Inititalizer extends Call { +abstract class EVP_Cipher_Initializer extends Call { Expr getContextArg() { result = this.(Call).getArgument(0) } Expr getAlgorithmArg() { result = this.(Call).getArgument(1) } @@ -44,7 +44,7 @@ abstract class EVP_Cipher_Inititalizer extends Call { abstract Expr getIVArg(); // abstract Crypto::CipherOperationSubtype getCipherOperationSubtype(); - abstract Expr getOperataionSubtypeArg(); + abstract Expr getOperationSubtypeArg(); Crypto::KeyOperationSubtype getCipherOperationSubtype() { if this.(Call).getTarget().getName().toLowerCase().matches("%encrypt%") @@ -53,19 +53,19 @@ abstract class EVP_Cipher_Inititalizer extends Call { if this.(Call).getTarget().getName().toLowerCase().matches("%decrypt%") then result instanceof Crypto::TDecryptMode else - if exists(getEncConfigValue(this.getOperataionSubtypeArg())) - then result = intToCipherOperationSubtype(getEncConfigValue(this.getOperataionSubtypeArg())) + if exists(getEncConfigValue(this.getOperationSubtypeArg())) + then result = intToCipherOperationSubtype(getEncConfigValue(this.getOperationSubtypeArg())) else result instanceof Crypto::TUnknownKeyOperationMode } } -abstract class EVP_EX_Initializer extends EVP_Cipher_Inititalizer { +abstract class EVP_EX_Initializer extends EVP_Cipher_Initializer { override Expr getKeyArg() { result = this.(Call).getArgument(3) } override Expr getIVArg() { result = this.(Call).getArgument(4) } } -abstract class EVP_EX2_Initializer extends EVP_Cipher_Inititalizer { +abstract class EVP_EX2_Initializer extends EVP_Cipher_Initializer { override Expr getKeyArg() { result = this.(Call).getArgument(2) } override Expr getIVArg() { result = this.(Call).getArgument(3) } @@ -78,7 +78,7 @@ class EVP_Cipher_EX_Init_Call extends EVP_EX_Initializer { ] } - override Expr getOperataionSubtypeArg() { + override Expr getOperationSubtypeArg() { this.(Call).getTarget().getName().toLowerCase().matches("%cipherinit%") and result = this.(Call).getArgument(5) } @@ -92,7 +92,7 @@ class EVP_Cipher_EX2_or_Simple_Init_Call extends EVP_EX2_Initializer { ] } - override Expr getOperataionSubtypeArg() { + override Expr getOperationSubtypeArg() { this.(Call).getTarget().getName().toLowerCase().matches("%cipherinit%") and result = this.(Call).getArgument(4) } @@ -101,23 +101,23 @@ class EVP_Cipher_EX2_or_Simple_Init_Call extends EVP_EX2_Initializer { class EVP_CipherInit_SKEY_Call extends EVP_EX2_Initializer { EVP_CipherInit_SKEY_Call() { this.(Call).getTarget().getName() in ["EVP_CipherInit_SKEY"] } - override Expr getOperataionSubtypeArg() { result = this.(Call).getArgument(5) } + override Expr getOperationSubtypeArg() { result = this.(Call).getArgument(5) } } class EVPCipherInitializerAlgorithmArgument extends Expr { EVPCipherInitializerAlgorithmArgument() { - exists(EVP_Cipher_Inititalizer initCall | this = initCall.getAlgorithmArg()) + exists(EVP_Cipher_Initializer initCall | this = initCall.getAlgorithmArg()) } } class EVPCipherInitializerKeyArgument extends Expr { EVPCipherInitializerKeyArgument() { - exists(EVP_Cipher_Inititalizer initCall | this = initCall.getKeyArg()) + exists(EVP_Cipher_Initializer initCall | this = initCall.getKeyArg()) } } class EVPCipherInitializerIVArgument extends Expr { EVPCipherInitializerIVArgument() { - exists(EVP_Cipher_Inititalizer initCall | this = initCall.getIVArg()) + exists(EVP_Cipher_Initializer initCall | this = initCall.getIVArg()) } } diff --git a/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherOperation.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherOperation.qll index 45c7d41b029b..b544079579af 100644 --- a/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherOperation.qll +++ b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherOperation.qll @@ -45,7 +45,7 @@ abstract class EVP_Cipher_Operation extends OpenSSLOperation, Crypto::KeyOperati this.(Call).getTarget().getName().toLowerCase().matches("%cipher%") } - EVP_Cipher_Inititalizer getInitCall() { + EVP_Cipher_Initializer getInitCall() { CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg()) } @@ -74,14 +74,14 @@ abstract class EVP_Final_Call extends EVP_Cipher_Operation { // TODO: only model Final (model final as operation and model update but not as an operation) // Updates are multiple input consumers (most important) -// PUNT assuming update doesn't ouput, otherwise it outputs arifacts, but is not an operation +// TODO: assuming update doesn't ouput, otherwise it outputs artifacts, but is not an operation class EVP_Cipher_Call extends EVP_Cipher_Operation { EVP_Cipher_Call() { this.(Call).getTarget().getName() = "EVP_Cipher" } override Expr getInputArg() { result = this.(Call).getArgument(2) } } -// ******* TODO NEED to model UPDATE but not as the coree operation, rather a step towards final, +// ******* TODO: model UPDATE but not as the core operation, rather a step towards final // see the JCA // class EVP_Encrypt_Decrypt_or_Cipher_Update_Call extends EVP_Update_Call { // EVP_Encrypt_Decrypt_or_Cipher_Update_Call() { From 1135fbe950b146bca576d7921b528a1c3ec68c20 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 02:58:43 +0200 Subject: [PATCH 274/336] Fix EVP_Hash_Initializer typo --- .../quantum/OpenSSL/Operations/EVPHashInitializer.qll | 4 ++-- .../quantum/OpenSSL/Operations/EVPHashOperation.qll | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPHashInitializer.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPHashInitializer.qll index cd0dac94001a..46d414ece6ce 100644 --- a/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPHashInitializer.qll +++ b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPHashInitializer.qll @@ -1,12 +1,12 @@ import cpp -abstract class EVP_Hash_Inititalizer extends Call { +abstract class EVP_Hash_Initializer extends Call { Expr getContextArg() { result = this.(Call).getArgument(0) } abstract Expr getAlgorithmArg(); } -class EVP_DigestInit_Variant_Calls extends EVP_Hash_Inititalizer { +class EVP_DigestInit_Variant_Calls extends EVP_Hash_Initializer { EVP_DigestInit_Variant_Calls() { this.(Call).getTarget().getName() in [ "EVP_DigestInit", "EVP_DigestInit_ex", "EVP_DigestInit_ex2" diff --git a/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPHashOperation.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPHashOperation.qll index 45776b6668b3..a187b62a7bdd 100644 --- a/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPHashOperation.qll +++ b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPHashOperation.qll @@ -13,7 +13,7 @@ import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValu abstract class EVP_Hash_Operation extends OpenSSLOperation, Crypto::HashOperationInstance { Expr getContextArg() { result = this.(Call).getArgument(0) } - EVP_Hash_Inititalizer getInitCall() { + EVP_Hash_Initializer getInitCall() { CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg()) } } @@ -38,7 +38,7 @@ class EVP_Q_Digest_Operation extends EVP_Hash_Operation { } //override Crypto::AlgorithmConsumer getAlgorithmConsumer() { } - override EVP_Hash_Inititalizer getInitCall() { + override EVP_Hash_Initializer getInitCall() { // This variant of digest does not use an init // and even if it were used, the init would be ignored/undefined none() @@ -74,7 +74,7 @@ class EVP_Digest_Operation extends EVP_Hash_Operation { DataFlow::exprNode(this.(Call).getArgument(4))) } - override EVP_Hash_Inititalizer getInitCall() { + override EVP_Hash_Initializer getInitCall() { // This variant of digest does not use an init // and even if it were used, the init would be ignored/undefined none() From 0c6e124b01a34c9ee6b286e174ae999a3d58e136 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 03:02:59 +0200 Subject: [PATCH 275/336] Delete development test query --- cpp/ql/src/experimental/quantum/Test2.ql | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 cpp/ql/src/experimental/quantum/Test2.ql diff --git a/cpp/ql/src/experimental/quantum/Test2.ql b/cpp/ql/src/experimental/quantum/Test2.ql deleted file mode 100644 index 98a35d2a9e9f..000000000000 --- a/cpp/ql/src/experimental/quantum/Test2.ql +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @name "PQC Test" - */ - -import experimental.quantum.Language - -from Crypto::NodeBase node -select node From 986c8e1aecbdc52aeca368d93c3958643ab99431 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 03:24:04 +0200 Subject: [PATCH 276/336] Change Java inventory slices to @kind table --- .../InsecureOrUnknownNonceAtOperation.ql | 70 ------------------- .../quantum/Examples/TestCipherKey.ql | 17 ----- .../KnownAsymmetricAlgorithm.ql | 2 +- .../KnownAsymmetricCipherAlgorithm.ql | 2 +- .../KnownAsymmetricOperationAlgorithm.ql | 2 +- .../InventorySlices/KnownCipherAlgorithm.ql | 2 +- .../KnownEllipticCurveAlgorithm.ql | 2 +- .../InventorySlices/KnownHashingAlgorithm.ql | 2 +- .../InventorySlices/KnownHashingOperation.ql | 2 +- .../KnownHashingOperationAlgorithm.ql | 2 +- .../KnownKeyDerivationAlgorithm.ql | 2 +- .../KnownKeyDerivationOperation.ql | 2 +- .../KnownKeyDerivationOperationAlgorithm.ql | 5 +- .../KnownSymmetricCipherAlgorithm.ql | 2 +- .../LikelyCryptoAPIFunction.ql | 2 +- .../UnknownOperationAlgorithm.ql | 2 +- 16 files changed, 15 insertions(+), 103 deletions(-) delete mode 100644 java/ql/src/experimental/quantum/Examples/InsecureOrUnknownNonceAtOperation.ql delete mode 100644 java/ql/src/experimental/quantum/Examples/TestCipherKey.ql diff --git a/java/ql/src/experimental/quantum/Examples/InsecureOrUnknownNonceAtOperation.ql b/java/ql/src/experimental/quantum/Examples/InsecureOrUnknownNonceAtOperation.ql deleted file mode 100644 index fc2387fda374..000000000000 --- a/java/ql/src/experimental/quantum/Examples/InsecureOrUnknownNonceAtOperation.ql +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @name Insecure or unknown nonce source at a cipher operation - * @id java/insecure-or-unknown-nonce-at-operation - * @kind problem - */ - -import experimental.quantum.Language - -from - Crypto::NonceArtifactNode n, Crypto::KeyOperationNode op, Crypto::FlowAwareElement src, string msg -where - op.getANonce() = n and - // Only encryption mode is relevant for insecure nonces, consder any 'unknown' subtype - // as possibly encryption. - ( - op.getKeyOperationSubtype() instanceof Crypto::EncryptionSubtype - or - op.getKeyOperationSubtype() instanceof Crypto::WrapSubtype - or - op.getKeyOperationSubtype() instanceof Crypto::UnwrapSubtype - ) and - ( - // Known sources cases that are not secure - src = n.getSourceElement() and - not src instanceof SecureRandomnessInstance and - msg = "Operation uses insecure nonce source $@" - or - // Totally unknown sources (unmodeled input sources) - not exists(n.getSourceElement()) and - msg = "Operation uses unknown nonce source" and - src = n.asElement() - ) -select n, msg, src, src.toString() -// variant using instances, does not yield the same results -// from Crypto::NonceArtifactConsumer n, Crypto::CipherOperationInstance op, Crypto::FlowAwareElement src, string msg -// where -// op.getNonceConsumer() = n and -// TODO: only perform the query on encryption -// ( -// // Known sources cases that are not secure -// src = n.getAKnownArtifactSource()and -// not src instanceof SecureRandomnessInstance and -// msg = "Operation uses insecure nonce source $@" -// or -// // Totally unknown sources (unmodeled input sources) -// // When this occurs set src to n, just to bind it, but the output message will not report any source -// not exists(n.getAKnownArtifactSource()) and msg = "Operation uses unknown nonce source" and src = n -// ) -// select n, msg, src, src.toString() -// NOTE: this will find all unknowns too, constants, and allocations, without needing to model them -// which is kinda nice, but accidental, since getSourceElement is not modeled for everything -// If users want to find constants or unallocated, they need to model those sources, and output the -// getSourceElement -// QUESTION: why isn't the source element a node? -// NOTE: when not all sources are modeled, if one source is secure, even if others do exist, you -// will see the nonce and operation are secure, regardless of potentially insecure IV sources -// resulting in False Negatives -// NOTE: need to have a query where the op has no Nonce -// // Ideal query -// from Crypto::NonceNode n, Crypto::CipherOperationNode op -// where -// n = op.getANonce() and -// // n = op.getAnUnknownNonce() -// not n.asElement() instanceof SecureRandomSource -// select op, "Operation uses insecure nonce source @", n, n.toString() -// from Crypto::Nonce n, Crypto::ArtifactLocatableElement nonceSrc -// where -// n.() = nonceSrc and -// not nonceSrc instanceof SecureRandomnessInstance -// select n, nonceSrc diff --git a/java/ql/src/experimental/quantum/Examples/TestCipherKey.ql b/java/ql/src/experimental/quantum/Examples/TestCipherKey.ql deleted file mode 100644 index 9408aac7e3ba..000000000000 --- a/java/ql/src/experimental/quantum/Examples/TestCipherKey.ql +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @name "PQC Test" - */ - -import experimental.quantum.Language - -from Crypto::KeyOperationNode op, Crypto::CipherAlgorithmNode a, Crypto::KeyArtifactNode k -where - a = op.getAKnownCipherAlgorithm() and - k = op.getAKey() -select op, op.getKeyOperationSubtype(), a, a.getRawAlgorithmName(), k, k.getSourceNode() -/* - * from Crypto::CipherOperationNode op - * where op.getLocation().getFile().getBaseName() = "AsymmetricEncryptionMacHybridCryptosystem.java" - * select op, op.getAKey().getSourceNode() - */ - diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql index 7ae2a0f08880..918be510b6c6 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql @@ -1,7 +1,7 @@ /** * @name Detects known asymmetric algorithms * @id java/crypto_inventory_slices/known_asymmetric_algorithm - * @kind problem + * @kind table */ import java diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql index b903e152a299..b40910b10f4c 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql @@ -1,7 +1,7 @@ /** * @name Detects known asymmetric cipher algorithms * @id java/crypto_inventory_slices/known_asymmetric_cipher_algorithm - * @kind problem + * @kind table */ import java diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql index a14a0dfbaba7..b3e0097ec4c4 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql @@ -1,7 +1,7 @@ /** * @name Detects operations where the algorithm applied is a known asymmetric algorithms * @id java/crypto_inventory_slices/known_asymmetric_operation_algorithm - * @kind problem + * @kind table */ import java diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownCipherAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownCipherAlgorithm.ql index f126c3d9ae11..de80f2a6d1ae 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownCipherAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownCipherAlgorithm.ql @@ -1,7 +1,7 @@ /** * @name Detects known cipher algorithms * @id java/crypto_inventory_slices/known_cipher_algorithm - * @kind problem + * @kind table */ import java diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql index c3f69d91cb70..dd204bfd54e4 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql @@ -1,7 +1,7 @@ /** * @name Detects known elliptic curve algorithms * @id java/crypto_inventory_slices/known_elliptic_curve_algorithm - * @kind problem + * @kind table */ import java diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownHashingAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownHashingAlgorithm.ql index ed24b62364dd..267625437401 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownHashingAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownHashingAlgorithm.ql @@ -1,7 +1,7 @@ /** * @name Detects algorithms that are known hashing algorithms * @id java/crypto_inventory_slices/known_hashing_algorithm - * @kind problem + * @kind table */ import java diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperation.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperation.ql index 23fc6235e802..2edfa6190eaa 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperation.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperation.ql @@ -1,7 +1,7 @@ /** * @name Detects uses of hashing operations (operations exlicitly for hashing only, irrespective of the algorithm used) * @id java/crypto_inventory_slices/known_hashing_operation - * @kind problem + * @kind table */ import java diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperationAlgorithm.ql index 8af3c09dd10e..6ee2ce9ac4d4 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperationAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperationAlgorithm.ql @@ -1,7 +1,7 @@ /** * @name Detects operations where the algorithm applied is a known hashing algorithm * @id java/crypto_inventory_slices/operation_with_known_hashing_algorithm - * @kind problem + * @kind table */ import java diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql index e0970353a987..28de1170d272 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql @@ -1,7 +1,7 @@ /** * @name Detects known key derivation algorithms * @id java/crypto_inventory_slices/known_key_derivation_algorithm - * @kind problem + * @kind table */ import java diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperation.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperation.ql index 240a4ea3fc54..c0ee9c88b2b2 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperation.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperation.ql @@ -1,7 +1,7 @@ /** * @name Detects uses of key derivation operations (operations exlicitly for key derivation only, irrespective of the algorithm used) * @id java/crypto_inventory_slices/known_key_derivation_operation - * @kind problem + * @kind table */ import java diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql index 9afbd7d7f2f7..db27630cafa6 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql @@ -1,8 +1,7 @@ /** * @name Detects operations where the algorithm applied is a known key derivation algorithm - * @id java/cryptography-inventory-slices/operation-known-key-derivation-algorithm - * @description This query identifies operations that utilize a known key derivation algorithm. - * @kind problem + * @id java/crypto_inventory_slices/operation_known_key_derivation_algorithm + * @kind table */ import java diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql index d8467305df97..6c5f9c636771 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql @@ -1,7 +1,7 @@ /** * @name Detects known symmetric cipher algorithms * @id java/crypto_inventory_slices/known_symmetric_cipher_algorithm - * @kind problem + * @kind table */ import java diff --git a/java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql b/java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql index d02524a7df37..cb16064667ac 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql @@ -1,7 +1,7 @@ /** * @name Detects functions that take in crypto configuration parameters but calls are not detected in source. * @id java/crypto_inventory_slices/likely_crypto_api_function - * @kind problem + * @kind table */ import java diff --git a/java/ql/src/experimental/quantum/InventorySlices/UnknownOperationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/UnknownOperationAlgorithm.ql index 7559579d863f..962e8945e812 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/UnknownOperationAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/UnknownOperationAlgorithm.ql @@ -1,7 +1,7 @@ /** * @name Detects operations where the algorithm applied is unknown * @id java/crypto_inventory_slices/unknown_operation_algorithm - * @kind problem + * @kind table */ import java From b558e844ffa902b6ab7b665c902ca3e1bbdaed1c Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 03:56:20 +0200 Subject: [PATCH 277/336] Update slice query metadata and output tables --- .../InventorySlices/KnownAsymmetricAlgorithm.ql | 9 ++++++--- .../InventorySlices/KnownAsymmetricCipherAlgorithm.ql | 9 ++++++--- .../KnownAsymmetricOperationAlgorithm.ql | 9 ++++++--- .../quantum/InventorySlices/KnownCipherAlgorithm.ql | 9 ++++++--- .../InventorySlices/KnownEllipticCurveAlgorithm.ql | 9 ++++++--- .../quantum/InventorySlices/KnownHashingAlgorithm.ql | 9 ++++++--- .../quantum/InventorySlices/KnownHashingOperation.ql | 9 ++++++--- .../InventorySlices/KnownHashingOperationAlgorithm.ql | 9 ++++++--- .../InventorySlices/KnownKeyDerivationAlgorithm.ql | 9 ++++++--- .../InventorySlices/KnownKeyDerivationOperation.ql | 9 ++++++--- .../KnownKeyDerivationOperationAlgorithm.ql | 9 ++++++--- .../InventorySlices/KnownSymmetricCipherAlgorithm.ql | 9 ++++++--- .../quantum/InventorySlices/LikelyCryptoAPIFunction.ql | 10 +++++++--- .../InventorySlices/UnknownOperationAlgorithm.ql | 10 +++++++--- 14 files changed, 86 insertions(+), 42 deletions(-) diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql index 918be510b6c6..a74da7d1acc3 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql @@ -1,7 +1,10 @@ /** - * @name Detects known asymmetric algorithms - * @id java/crypto_inventory_slices/known_asymmetric_algorithm + * @name Operations using known asymmetric cipher algorithms (slice) + * @description Outputs operations where the algorithm used is a known asymmetric cipher algorithm. + * @id java/quantum/slices/known-asymmetric-cipher-algorithm * @kind table + * @tags quantum + * experimental */ import java @@ -9,4 +12,4 @@ import experimental.quantum.Language from Crypto::AlgorithmNode a where Crypto::isKnownAsymmetricAlgorithm(a) -select a, "Instance of asymmetric algorithm " + a.getAlgorithmName() +select a, a.getAlgorithmName() diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql index b40910b10f4c..69643d92cd24 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql @@ -1,7 +1,10 @@ /** - * @name Detects known asymmetric cipher algorithms - * @id java/crypto_inventory_slices/known_asymmetric_cipher_algorithm + * @name Known asymmetric cipher algorithms (slice) + * @description Outputs known asymmetric cipher algorithms. + * @id java/quantum/slices/known-asymmetric-cipher-algorithm * @kind table + * @tags quantum + * experimental */ import java @@ -9,4 +12,4 @@ import experimental.quantum.Language from Crypto::KeyOperationAlgorithmNode a where a.getAlgorithmType() instanceof Crypto::KeyOpAlg::AsymmetricCipherAlgorithm -select a, "Instance of asymmetric cipher algorithm " + a.getAlgorithmName() +select a, a.getAlgorithmName() diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql index b3e0097ec4c4..224ee1161fb0 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql @@ -1,7 +1,10 @@ /** - * @name Detects operations where the algorithm applied is a known asymmetric algorithms - * @id java/crypto_inventory_slices/known_asymmetric_operation_algorithm + * @name Operations using known asymmetric algorithms (slice) + * @description Outputs operations where the algorithm used is a known asymmetric algorithm. + * @id java/quantum/slices/known-asymmetric-operation-algorithm * @kind table + * @tags quantum + * experimental */ import java @@ -9,4 +12,4 @@ import experimental.quantum.Language from Crypto::OperationNode op, Crypto::AlgorithmNode a where a = op.getAKnownAlgorithm() and Crypto::isKnownAsymmetricAlgorithm(a) -select op, "Operation using asymmetric algorithm $@", a, a.getAlgorithmName() +select op, a.getAlgorithmName() diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownCipherAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownCipherAlgorithm.ql index de80f2a6d1ae..da3371a59b34 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownCipherAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownCipherAlgorithm.ql @@ -1,7 +1,10 @@ /** - * @name Detects known cipher algorithms - * @id java/crypto_inventory_slices/known_cipher_algorithm + * @name Known cipher algorithms (slice) + * @description Outputs known cipher algorithms. + * @id java/quantum/slices/known-cipher-algorithm * @kind table + * @tags quantum + * experimental */ import java @@ -12,4 +15,4 @@ from Crypto::KeyOperationAlgorithmNode a where a.getAlgorithmType() instanceof Crypto::KeyOpAlg::AsymmetricCipherAlgorithm or a.getAlgorithmType() instanceof Crypto::KeyOpAlg::SymmetricCipherAlgorithm -select a, "Instance of cipher algorithm " + a.getAlgorithmName() +select a, a.getAlgorithmName() diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql index dd204bfd54e4..ca72e2de2517 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql @@ -1,11 +1,14 @@ /** - * @name Detects known elliptic curve algorithms - * @id java/crypto_inventory_slices/known_elliptic_curve_algorithm + * @name Known elliptic curve algorithms (slice) + * @description Outputs known elliptic curve algorithms. + * @id java/quantum/slices/known-elliptic-curve-algorithm * @kind table + * @tags quantum + * experimental */ import java import experimental.quantum.Language from Crypto::EllipticCurveNode a -select a, "Instance of elliptic curve algorithm " + a.getAlgorithmName() +select a, a.getAlgorithmName() diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownHashingAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownHashingAlgorithm.ql index 267625437401..042f3b3dc915 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownHashingAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownHashingAlgorithm.ql @@ -1,11 +1,14 @@ /** - * @name Detects algorithms that are known hashing algorithms - * @id java/crypto_inventory_slices/known_hashing_algorithm + * @name Known hashing algorithms (slice) + * @description Outputs known hashing algorithms. + * @id java/quantum/slices/known-hashing-algorithm * @kind table + * @tags quantum + * experimental */ import java import experimental.quantum.Language from Crypto::HashAlgorithmNode a -select a, "Instance of hashing algorithm " + a.getAlgorithmName() +select a, a.getAlgorithmName() diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperation.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperation.ql index 2edfa6190eaa..b004fae7fbbb 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperation.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperation.ql @@ -1,11 +1,14 @@ /** - * @name Detects uses of hashing operations (operations exlicitly for hashing only, irrespective of the algorithm used) - * @id java/crypto_inventory_slices/known_hashing_operation + * @name Known hashing operations (slice) + * @description Outputs known hashing operations. + * @id java/quantum/slices/known-hashing-operation * @kind table + * @tags quantum + * experimental */ import java import experimental.quantum.Language from Crypto::HashOperationNode op -select op, "Known hashing operation" +select op diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperationAlgorithm.ql index 6ee2ce9ac4d4..38d197bb7dd8 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperationAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperationAlgorithm.ql @@ -1,7 +1,10 @@ /** - * @name Detects operations where the algorithm applied is a known hashing algorithm - * @id java/crypto_inventory_slices/operation_with_known_hashing_algorithm + * @name Operations using known hashing algorithms (slice) + * @description Outputs operations where the algorithm used is a known hashing algorithm. + * @id java/quantum/slices/operation-with-known-hashing-algorithm * @kind table + * @tags quantum + * experimental */ import java @@ -9,4 +12,4 @@ import experimental.quantum.Language from Crypto::OperationNode op, Crypto::HashAlgorithmNode a where a = op.getAKnownAlgorithm() -select op, "Operation using hashing algorithm $@", a, a.getAlgorithmName() +select op, a.getAlgorithmName() diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql index 28de1170d272..5a9744c966b0 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql @@ -1,11 +1,14 @@ /** - * @name Detects known key derivation algorithms - * @id java/crypto_inventory_slices/known_key_derivation_algorithm + * @name Known key derivation algorithms (slice) + * @description Outputs known key derivation algorithms. + * @id java/quantum/slices/known-key-derivation-algorithm * @kind table + * @tags quantum + * experimental */ import java import experimental.quantum.Language from Crypto::KeyDerivationAlgorithmNode alg -select alg, "Known key derivation algorithm " + alg.getAlgorithmName() +select alg, alg.getAlgorithmName() diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperation.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperation.ql index c0ee9c88b2b2..95623ec7a1e8 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperation.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperation.ql @@ -1,11 +1,14 @@ /** - * @name Detects uses of key derivation operations (operations exlicitly for key derivation only, irrespective of the algorithm used) - * @id java/crypto_inventory_slices/known_key_derivation_operation + * @name Known key derivation operations (slice) + * @description Outputs known key derivation operations. + * @id java/quantum/slices/known-key-derivation-operation * @kind table + * @tags quantum + * experimental */ import java import experimental.quantum.Language from Crypto::KeyDerivationOperationNode op -select op, "Known key derivation operation" +select op diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql index db27630cafa6..efbfd9ed8658 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql @@ -1,7 +1,10 @@ /** - * @name Detects operations where the algorithm applied is a known key derivation algorithm - * @id java/crypto_inventory_slices/operation_known_key_derivation_algorithm + * @name Operations using known key derivation algorithms (slice) + * @description Outputs operations where the algorithm used is a known key derivation algorithm. + * @id java/quantum/slices/operation-with-known-kdf-algorithm * @kind table + * @tags quantum + * experimental */ import java @@ -9,4 +12,4 @@ import experimental.quantum.Language from Crypto::OperationNode op, Crypto::KeyDerivationAlgorithmNode a where a = op.getAKnownAlgorithm() -select op, "Operation using key derivation algorithm $@", a, a.getAlgorithmName() +select op, a.getAlgorithmName() diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql index 6c5f9c636771..e4a8d3ff8679 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql @@ -1,7 +1,10 @@ /** - * @name Detects known symmetric cipher algorithms - * @id java/crypto_inventory_slices/known_symmetric_cipher_algorithm + * @name Known symmetric cipher algorithms (slice) + * @description Outputs known symmetric cipher algorithms. + * @id java/quantum/slices/known-symmetric-cipher-algorithm * @kind table + * @tags quantum + * experimental */ import java @@ -9,4 +12,4 @@ import experimental.quantum.Language from Crypto::KeyOperationAlgorithmNode a where a.getAlgorithmType() instanceof Crypto::KeyOpAlg::SymmetricCipherAlgorithm -select a, "Instance of symmetric cipher algorithm " + a.getAlgorithmName() +select a, a.getAlgorithmName() diff --git a/java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql b/java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql index cb16064667ac..2b81cf22dba5 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql @@ -1,7 +1,11 @@ /** - * @name Detects functions that take in crypto configuration parameters but calls are not detected in source. - * @id java/crypto_inventory_slices/likely_crypto_api_function - * @kind table + * @name Likely crypto API function + * @description Detects functions that take in crypto configuration parameters but calls are not detected in source. + * @id java/quantum/slices/likely-crypto-api-function + * @kind problem + * @severity info + * @tags quantum + * experimental */ import java diff --git a/java/ql/src/experimental/quantum/InventorySlices/UnknownOperationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/UnknownOperationAlgorithm.ql index 962e8945e812..8469924a8501 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/UnknownOperationAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/UnknownOperationAlgorithm.ql @@ -1,7 +1,11 @@ /** - * @name Detects operations where the algorithm applied is unknown - * @id java/crypto_inventory_slices/unknown_operation_algorithm - * @kind table + * @name Operations with unknown algorithm + * @description Outputs operations where the algorithm applied is unknown + * @id java/quantum/slices/operation-with-unknown-algorithm + * @kind problem + * @severity info + * @tags quantum + * experimental */ import java From b8c3b43cc478d5fc7ff38cc85d6ba30d468fedf6 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 03:58:06 +0200 Subject: [PATCH 278/336] Fix KnownAsymmetricAlgorithm query id --- .../quantum/InventorySlices/KnownAsymmetricAlgorithm.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql index a74da7d1acc3..b4d0b908bbe1 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql @@ -1,7 +1,7 @@ /** * @name Operations using known asymmetric cipher algorithms (slice) * @description Outputs operations where the algorithm used is a known asymmetric cipher algorithm. - * @id java/quantum/slices/known-asymmetric-cipher-algorithm + * @id java/quantum/slices/known-asymmetric-algorithm * @kind table * @tags quantum * experimental From e03f57da9b956b6e2953edaeaef55ca4a95d7f8c Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 04:03:10 +0200 Subject: [PATCH 279/336] Update type name in experimental BrokenCrypto.ql --- java/ql/src/experimental/quantum/Examples/BrokenCrypto.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/experimental/quantum/Examples/BrokenCrypto.ql b/java/ql/src/experimental/quantum/Examples/BrokenCrypto.ql index b4e9de9ac945..7291ea554a58 100644 --- a/java/ql/src/experimental/quantum/Examples/BrokenCrypto.ql +++ b/java/ql/src/experimental/quantum/Examples/BrokenCrypto.ql @@ -64,7 +64,7 @@ private string algorithmRegex(string algorithmString) { "((^|.*[A-Z]{2}|.*[^a-zA-Z])(" + algorithmString.toLowerCase() + ")([^a-z].*|$))" } -from Crypto::Algorithm alg +from Crypto::AlgorithmNode alg where alg.getAlgorithmName().regexpMatch(getInsecureAlgorithmRegex()) and // Exclude RSA/ECB/.* ciphers. From a57f4a1022e7d72c92afcfdc92cdcdc0adc8ba55 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 04:13:57 +0200 Subject: [PATCH 280/336] Update Java analysis query metadata --- .../experimental/quantum/Analysis/InsecureNonceSource.ql | 8 +++++--- .../quantum/Analysis/KnownWeakKDFIterationCount.ql | 9 +++++++-- java/ql/src/experimental/quantum/Analysis/ReusedNonce.ql | 9 +++++++-- .../quantum/Analysis/UnknownKDFIterationCount.ql | 9 +++++++-- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/java/ql/src/experimental/quantum/Analysis/InsecureNonceSource.ql b/java/ql/src/experimental/quantum/Analysis/InsecureNonceSource.ql index b2c6f919d5fe..f00621d4d2b6 100644 --- a/java/ql/src/experimental/quantum/Analysis/InsecureNonceSource.ql +++ b/java/ql/src/experimental/quantum/Analysis/InsecureNonceSource.ql @@ -1,11 +1,13 @@ /** * @name Insecure nonce at a cipher operation - * @id java/insecure-nonce + * @id java/quantum/insecure-nonce + * @description A nonce is generated from a source that is not secure. This can lead to + * vulnerabilities such as replay attacks or key recovery. * @kind problem * @problem.severity error * @precision high - * @description A nonce is generated from a source that is not secure. This can lead to - * vulnerabilities such as replay attacks or key recovery. + * @tags quantum + * experimental */ import experimental.quantum.Language diff --git a/java/ql/src/experimental/quantum/Analysis/KnownWeakKDFIterationCount.ql b/java/ql/src/experimental/quantum/Analysis/KnownWeakKDFIterationCount.ql index 701f3064e92a..d8d9d125070e 100644 --- a/java/ql/src/experimental/quantum/Analysis/KnownWeakKDFIterationCount.ql +++ b/java/ql/src/experimental/quantum/Analysis/KnownWeakKDFIterationCount.ql @@ -1,7 +1,12 @@ /** - * @name Detects known weak KDf iteration counts (less than 100k and the count is statically known) - * @id java/crypto_inventory_filters/known_weak_kdf_iteration_count + * @name Weak known key derivation function iteration count + * @description Detects key derivation operations with a known weak iteration count. + * @id java/quantum/weak-kdf-iteration-count * @kind problem + * @precision high + * @severity problem + * @tags quantum + * experimental */ import java diff --git a/java/ql/src/experimental/quantum/Analysis/ReusedNonce.ql b/java/ql/src/experimental/quantum/Analysis/ReusedNonce.ql index d8adccace557..b7b7c27ec6bf 100644 --- a/java/ql/src/experimental/quantum/Analysis/ReusedNonce.ql +++ b/java/ql/src/experimental/quantum/Analysis/ReusedNonce.ql @@ -1,7 +1,12 @@ /** - * @name Detects reuse of the same nonce in multiple operations - * @id java/crypto_inventory_filter/nonce_reuse + * @name Reuse of cryptographic nonce + * @description Reuse of nonce in cryptographic operations can lead to vulnerabilities. + * @id java/quantum/reused-nonce * @kind problem + * @precision medium + * @severity problem + * @tags quantum + * experimental */ import java diff --git a/java/ql/src/experimental/quantum/Analysis/UnknownKDFIterationCount.ql b/java/ql/src/experimental/quantum/Analysis/UnknownKDFIterationCount.ql index 4ce404f01b08..21bca11cc1af 100644 --- a/java/ql/src/experimental/quantum/Analysis/UnknownKDFIterationCount.ql +++ b/java/ql/src/experimental/quantum/Analysis/UnknownKDFIterationCount.ql @@ -1,7 +1,12 @@ /** - * @name Detects unknown KDf iteration counts - * @id java/crypto_inventory_filters/unknown_kdf_iteration_count + * @name Unknown key derivation function iteration count + * @description Detects key derivation operations with an unknown iteration count. + * @id java/quantum/unknown-kdf-iteration-count * @kind problem + * @precision medium + * @severity warning + * @tags quantum + * experimental */ import java From 529128cbdec2bc02f2afaf8be3c635ffe1e50278 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 04:20:49 +0200 Subject: [PATCH 281/336] Add problem.severity for java analysis queries --- .../experimental/quantum/Analysis/KnownWeakKDFIterationCount.ql | 2 +- java/ql/src/experimental/quantum/Analysis/ReusedNonce.ql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/src/experimental/quantum/Analysis/KnownWeakKDFIterationCount.ql b/java/ql/src/experimental/quantum/Analysis/KnownWeakKDFIterationCount.ql index d8d9d125070e..2dd5b0b006be 100644 --- a/java/ql/src/experimental/quantum/Analysis/KnownWeakKDFIterationCount.ql +++ b/java/ql/src/experimental/quantum/Analysis/KnownWeakKDFIterationCount.ql @@ -3,8 +3,8 @@ * @description Detects key derivation operations with a known weak iteration count. * @id java/quantum/weak-kdf-iteration-count * @kind problem + * @problem.severity error * @precision high - * @severity problem * @tags quantum * experimental */ diff --git a/java/ql/src/experimental/quantum/Analysis/ReusedNonce.ql b/java/ql/src/experimental/quantum/Analysis/ReusedNonce.ql index b7b7c27ec6bf..ed2872bb67e1 100644 --- a/java/ql/src/experimental/quantum/Analysis/ReusedNonce.ql +++ b/java/ql/src/experimental/quantum/Analysis/ReusedNonce.ql @@ -3,8 +3,8 @@ * @description Reuse of nonce in cryptographic operations can lead to vulnerabilities. * @id java/quantum/reused-nonce * @kind problem + * @problem.severity error * @precision medium - * @severity problem * @tags quantum * experimental */ From c6077947a71c53815535f249f2ff5e0d20708cb9 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 8 May 2025 16:10:28 +0200 Subject: [PATCH 282/336] Update cpp and java not_included_in_qls.expected --- .../query-suite/not_included_in_qls.expected | 1 + .../query-suite/not_included_in_qls.expected | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/cpp/ql/integration-tests/query-suite/not_included_in_qls.expected b/cpp/ql/integration-tests/query-suite/not_included_in_qls.expected index 68b8c8b0ab46..20ffa7c40c0d 100644 --- a/cpp/ql/integration-tests/query-suite/not_included_in_qls.expected +++ b/cpp/ql/integration-tests/query-suite/not_included_in_qls.expected @@ -299,6 +299,7 @@ ql/cpp/ql/src/experimental/cryptography/inventory/new_models/SigningAlgorithms.q ql/cpp/ql/src/experimental/cryptography/inventory/new_models/SymmetricEncryptionAlgorithms.ql ql/cpp/ql/src/experimental/cryptography/inventory/new_models/SymmetricPaddingAlgorithms.ql ql/cpp/ql/src/experimental/cryptography/inventory/new_models/UnknownAsymmetricKeyGeneration.ql +ql/cpp/ql/src/experimental/quantum/PrintCBOMGraph.ql ql/cpp/ql/src/external/examples/filters/BumpMetricBy10.ql ql/cpp/ql/src/external/examples/filters/EditDefectMessage.ql ql/cpp/ql/src/external/examples/filters/ExcludeGeneratedCode.ql diff --git a/java/ql/integration-tests/java/query-suite/not_included_in_qls.expected b/java/ql/integration-tests/java/query-suite/not_included_in_qls.expected index f6e89eede03b..0fbc365c1343 100644 --- a/java/ql/integration-tests/java/query-suite/not_included_in_qls.expected +++ b/java/ql/integration-tests/java/query-suite/not_included_in_qls.expected @@ -253,6 +253,29 @@ ql/java/ql/src/experimental/Security/CWE/CWE-665/InsecureRmiJmxEnvironmentConfig ql/java/ql/src/experimental/Security/CWE/CWE-755/NFEAndroidDoS.ql ql/java/ql/src/experimental/Security/CWE/CWE-759/HashWithoutSalt.ql ql/java/ql/src/experimental/Security/CWE/CWE-939/IncorrectURLVerification.ql +ql/java/ql/src/experimental/quantum/Analysis/InsecureNonceSource.ql +ql/java/ql/src/experimental/quantum/Analysis/KnownWeakKDFIterationCount.ql +ql/java/ql/src/experimental/quantum/Analysis/ReusedNonce.ql +ql/java/ql/src/experimental/quantum/Analysis/UnknownKDFIterationCount.ql +ql/java/ql/src/experimental/quantum/Examples/BrokenCrypto.ql +ql/java/ql/src/experimental/quantum/Examples/TestAESGCMNonce.ql +ql/java/ql/src/experimental/quantum/Examples/TestCipher.ql +ql/java/ql/src/experimental/quantum/Examples/TestHash.ql +ql/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql +ql/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricCipherAlgorithm.ql +ql/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql +ql/java/ql/src/experimental/quantum/InventorySlices/KnownCipherAlgorithm.ql +ql/java/ql/src/experimental/quantum/InventorySlices/KnownEllipticCurveAlgorithm.ql +ql/java/ql/src/experimental/quantum/InventorySlices/KnownHashingAlgorithm.ql +ql/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperation.ql +ql/java/ql/src/experimental/quantum/InventorySlices/KnownHashingOperationAlgorithm.ql +ql/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationAlgorithm.ql +ql/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperation.ql +ql/java/ql/src/experimental/quantum/InventorySlices/KnownKeyDerivationOperationAlgorithm.ql +ql/java/ql/src/experimental/quantum/InventorySlices/KnownSymmetricCipherAlgorithm.ql +ql/java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql +ql/java/ql/src/experimental/quantum/InventorySlices/UnknownOperationAlgorithm.ql +ql/java/ql/src/experimental/quantum/PrintCBOMGraph.ql ql/java/ql/src/external/DuplicateAnonymous.ql ql/java/ql/src/external/DuplicateBlock.ql ql/java/ql/src/external/DuplicateMethod.ql From cd59ce5b0493df7eb5804627fcf1845ad58f3533 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Fri, 9 May 2025 14:36:12 +0200 Subject: [PATCH 283/336] Rename shared pack to quantum from experimental --- cpp/ql/lib/experimental/quantum/Language.qll | 12 ++++++------ cpp/ql/lib/qlpack.yml | 2 +- java/ql/lib/experimental/quantum/Language.qll | 2 +- java/ql/lib/qlpack.yml | 2 +- .../codeql/quantum/experimental}/Model.qll | 0 shared/{experimental => quantum}/qlpack.yml | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) rename shared/{experimental/codeql/experimental/quantum => quantum/codeql/quantum/experimental}/Model.qll (100%) rename shared/{experimental => quantum}/qlpack.yml (81%) diff --git a/cpp/ql/lib/experimental/quantum/Language.qll b/cpp/ql/lib/experimental/quantum/Language.qll index 176db9736adb..db9737cf152d 100644 --- a/cpp/ql/lib/experimental/quantum/Language.qll +++ b/cpp/ql/lib/experimental/quantum/Language.qll @@ -1,13 +1,13 @@ -import codeql.experimental.quantum.Model +private import cpp as Language import semmle.code.cpp.dataflow.new.DataFlow -private import cpp as Lang +import codeql.quantum.experimental.Model -module CryptoInput implements InputSig { +module CryptoInput implements InputSig { class DataFlowNode = DataFlow::Node; - class LocatableElement = Lang::Locatable; + class LocatableElement = Language::Locatable; - class UnknownLocation = Lang::UnknownDefaultLocation; + class UnknownLocation = Language::UnknownDefaultLocation; LocatableElement dfn_to_element(DataFlow::Node node) { result = node.asExpr() or @@ -26,7 +26,7 @@ module CryptoInput implements InputSig { } } -module Crypto = CryptographyBase; +module Crypto = CryptographyBase; module ArtifactFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index 335360caeb26..b7bf768c3f2e 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -7,8 +7,8 @@ library: true upgrades: upgrades dependencies: codeql/dataflow: ${workspace} - codeql/experimental: ${workspace} codeql/mad: ${workspace} + codeql/quantum: ${workspace} codeql/rangeanalysis: ${workspace} codeql/ssa: ${workspace} codeql/typeflow: ${workspace} diff --git a/java/ql/lib/experimental/quantum/Language.qll b/java/ql/lib/experimental/quantum/Language.qll index eaf63aa5be25..8e00f34f02b1 100644 --- a/java/ql/lib/experimental/quantum/Language.qll +++ b/java/ql/lib/experimental/quantum/Language.qll @@ -1,9 +1,9 @@ -private import codeql.experimental.quantum.Model private import java as Language private import semmle.code.java.security.InsecureRandomnessQuery private import semmle.code.java.security.RandomQuery private import semmle.code.java.dataflow.DataFlow private import semmle.code.java.dataflow.FlowSources +private import codeql.quantum.experimental.Model private class UnknownLocation extends Language::Location { UnknownLocation() { this.getFile().getAbsolutePath() = "" } diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index 036218757a84..eeaa063e4738 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -7,8 +7,8 @@ library: true upgrades: upgrades dependencies: codeql/dataflow: ${workspace} - codeql/experimental: ${workspace} codeql/mad: ${workspace} + codeql/quantum: ${workspace} codeql/rangeanalysis: ${workspace} codeql/regex: ${workspace} codeql/threat-models: ${workspace} diff --git a/shared/experimental/codeql/experimental/quantum/Model.qll b/shared/quantum/codeql/quantum/experimental/Model.qll similarity index 100% rename from shared/experimental/codeql/experimental/quantum/Model.qll rename to shared/quantum/codeql/quantum/experimental/Model.qll diff --git a/shared/experimental/qlpack.yml b/shared/quantum/qlpack.yml similarity index 81% rename from shared/experimental/qlpack.yml rename to shared/quantum/qlpack.yml index 2976c56ba492..8e34c19c1121 100644 --- a/shared/experimental/qlpack.yml +++ b/shared/quantum/qlpack.yml @@ -1,4 +1,4 @@ -name: codeql/experimental +name: codeql/quantum version: 0.0.0-dev groups: shared library: true From fbf3d7c195d38c3c07f114a302b44aced009eaf3 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Fri, 9 May 2025 14:36:55 +0200 Subject: [PATCH 284/336] Update CODEOWNERS to specify shared pack directory --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/CODEOWNERS b/CODEOWNERS index 318d9f2c6de7..96aa46df9495 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -17,6 +17,7 @@ # Experimental CodeQL cryptography **/experimental/quantum/ @github/ps-codeql +/shared/quantum/ @github/ps-codeql # CodeQL tools and associated docs /docs/codeql/codeql-cli/ @github/codeql-cli-reviewers From 48b95f3a4e2288bbd8bb07b241a80b715ed35463 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 9 May 2025 17:01:26 +0100 Subject: [PATCH 285/336] Rust: Move OperationImpl to internal/OperationImpl.qll. --- .../ql/lib/codeql/rust/elements/Operation.qll | 23 +-------------- .../rust/elements/internal/OperationImpl.qll | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 22 deletions(-) create mode 100644 rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll diff --git a/rust/ql/lib/codeql/rust/elements/Operation.qll b/rust/ql/lib/codeql/rust/elements/Operation.qll index 26486686cb20..b3615bddb33e 100644 --- a/rust/ql/lib/codeql/rust/elements/Operation.qll +++ b/rust/ql/lib/codeql/rust/elements/Operation.qll @@ -2,28 +2,7 @@ * Provides classes for operations. */ -private import rust +import internal.OperationImpl private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl -/** - * INTERNAL: This module contains the customizable definition of `Operation` and should not - * be referenced directly. - */ -module OperationImpl { - /** - * An operation, for example `&&`, `+=`, `!` or `*`. - */ - abstract class Operation extends ExprImpl::Expr { - /** - * Gets the operator name of this operation, if it exists. - */ - abstract string getOperatorName(); - - /** - * Gets an operand of this operation. - */ - abstract Expr getAnOperand(); - } -} - final class Operation = OperationImpl::Operation; diff --git a/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll new file mode 100644 index 000000000000..7b2d1a9d62e2 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll @@ -0,0 +1,29 @@ +/** + * Provides classes for operations. + * + * INTERNAL: Do not use. + */ + +private import rust +private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl + +/** + * INTERNAL: This module contains the customizable definition of `Operation` and should not + * be referenced directly. + */ +module OperationImpl { + /** + * An operation, for example `&&`, `+=`, `!` or `*`. + */ + abstract class Operation extends ExprImpl::Expr { + /** + * Gets the operator name of this operation, if it exists. + */ + abstract string getOperatorName(); + + /** + * Gets an operand of this operation. + */ + abstract Expr getAnOperand(); + } +} From 4e3ac93f70b19c7a7f96e6ea7f124a0642e0b44d Mon Sep 17 00:00:00 2001 From: Sid Gawri Date: Fri, 9 May 2025 16:24:42 -0400 Subject: [PATCH 286/336] fix unit tests part 2 --- csharp/ql/test/library-tests/asp/basic/options | 4 ++++ .../test/library-tests/dataflow/flowsources/remote/options | 3 ++- csharp/ql/test/library-tests/dataflow/global/options | 3 ++- csharp/ql/test/query-tests/Security Features/CWE-611/options | 5 ++++- csharp/ql/test/utils/modelgenerator/dataflow/options | 3 ++- 5 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 csharp/ql/test/library-tests/asp/basic/options diff --git a/csharp/ql/test/library-tests/asp/basic/options b/csharp/ql/test/library-tests/asp/basic/options new file mode 100644 index 000000000000..8b0f1661e630 --- /dev/null +++ b/csharp/ql/test/library-tests/asp/basic/options @@ -0,0 +1,4 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj +semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs \ No newline at end of file diff --git a/csharp/ql/test/library-tests/dataflow/flowsources/remote/options b/csharp/ql/test/library-tests/dataflow/flowsources/remote/options index 9290f65d5b22..1fcc7e1cf48f 100644 --- a/csharp/ql/test/library-tests/dataflow/flowsources/remote/options +++ b/csharp/ql/test/library-tests/dataflow/flowsources/remote/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj +semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs \ No newline at end of file diff --git a/csharp/ql/test/library-tests/dataflow/global/options b/csharp/ql/test/library-tests/dataflow/global/options index a2859a6265b1..8b0f1661e630 100644 --- a/csharp/ql/test/library-tests/dataflow/global/options +++ b/csharp/ql/test/library-tests/dataflow/global/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/Newtonsoft.Json/13.0.3/Newtonsoft.Json.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-611/options b/csharp/ql/test/query-tests/Security Features/CWE-611/options index d449cb3057f0..8b0f1661e630 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-611/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-611/options @@ -1 +1,4 @@ -semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs /r:System.Collections.Specialized.dll /r:System.Xml.ReaderWriter.dll /r:System.Private.Xml.dll /r:System.Runtime.Extensions.dll +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj +semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs \ No newline at end of file diff --git a/csharp/ql/test/utils/modelgenerator/dataflow/options b/csharp/ql/test/utils/modelgenerator/dataflow/options index 96b0b028bdd2..8b0f1661e630 100644 --- a/csharp/ql/test/utils/modelgenerator/dataflow/options +++ b/csharp/ql/test/utils/modelgenerator/dataflow/options @@ -1,3 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj +semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs \ No newline at end of file From 8fab235d666c3de13897f88ec5b4464d120e9a42 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 12 May 2025 09:41:49 +0200 Subject: [PATCH 287/336] DataFlow: Fix typo in a comment --- shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll b/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll index 9e6c4ff8b817..794fd340bcf8 100644 --- a/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll @@ -541,7 +541,7 @@ module Make< } /** - * Holds if `s` is a valid input stack, in the sense that we generate data flow graph + * Holds if `s` is a valid input stack, in the sense that we generate a data flow graph * that faithfully represents this flow, and lambda-tracking can be expected to track * lambdas to the relevant callbacks in practice. */ From 891b2b8335cd2b785b987ded03d4ae37378410e2 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 12 May 2025 09:42:45 +0200 Subject: [PATCH 288/336] DataFlow: Support a bare Argument[n] as a valid output stack --- .../codeql/dataflow/internal/FlowSummaryImpl.qll | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll b/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll index 794fd340bcf8..95d29153f47e 100644 --- a/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll @@ -565,8 +565,7 @@ module Make< isLocalSummaryComponent(s.head()) } - /** Like `isSupportedInputStack` but for output stacks. */ - private predicate isSupportedOutputStack(SummaryComponentStack s) { + private predicate isSupportedOutputStack1(SummaryComponentStack s) { // ReturnValue.* s.length() = 1 and s.head() instanceof TReturnSummaryComponent @@ -581,10 +580,19 @@ module Make< s.head() instanceof TParameterSummaryComponent and s.tail().head() instanceof TArgumentSummaryComponent or - isSupportedOutputStack(s.tail()) and + isSupportedOutputStack1(s.tail()) and isLocalSummaryComponent(s.head()) } + /** Like `isSupportedInputStack` but for output stacks. */ + private predicate isSupportedOutputStack(SummaryComponentStack s) { + isSupportedOutputStack1(s) + or + // `Argument[n]` not followed by anything. Needs to be outside the recursion. + s.length() = 1 and + s.head() instanceof TArgumentSummaryComponent + } + /** * Holds if `callable` has an unsupported flow `input -> output`. * From ab3f62eed171480c5b92b92bd959eeb2630c118c Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Mon, 12 May 2025 14:34:16 +0200 Subject: [PATCH 289/336] Add missing tags to PrintCBOMGraph.ql queries --- cpp/ql/src/experimental/quantum/PrintCBOMGraph.ql | 2 ++ java/ql/src/experimental/quantum/PrintCBOMGraph.ql | 2 ++ 2 files changed, 4 insertions(+) diff --git a/cpp/ql/src/experimental/quantum/PrintCBOMGraph.ql b/cpp/ql/src/experimental/quantum/PrintCBOMGraph.ql index f741e3c9f947..32979da10659 100644 --- a/cpp/ql/src/experimental/quantum/PrintCBOMGraph.ql +++ b/cpp/ql/src/experimental/quantum/PrintCBOMGraph.ql @@ -4,6 +4,8 @@ * This query only supports DGML output, as CodeQL DOT output omits properties. * @kind graph * @id cpp/print-cbom-graph + * @tags quantum + * experimental */ import experimental.quantum.Language diff --git a/java/ql/src/experimental/quantum/PrintCBOMGraph.ql b/java/ql/src/experimental/quantum/PrintCBOMGraph.ql index bc79d5d4ce6a..f9c59432846e 100644 --- a/java/ql/src/experimental/quantum/PrintCBOMGraph.ql +++ b/java/ql/src/experimental/quantum/PrintCBOMGraph.ql @@ -4,6 +4,8 @@ * This query only supports DGML output, as CodeQL DOT output omits properties. * @kind graph * @id java/print-cbom-graph + * @tags quantum + * experimental */ import experimental.quantum.Language From 8f36624171dd2dca388e5707451c4e5a53d03f24 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Mon, 12 May 2025 14:37:44 +0200 Subject: [PATCH 290/336] Add AsymmetricAlgorithmNode, refactor and address feedback --- java/ql/lib/experimental/quantum/Language.qll | 32 +++--- .../KnownAsymmetricAlgorithm.ql | 3 +- .../KnownAsymmetricOperationAlgorithm.ql | 4 +- .../LikelyCryptoAPIFunction.ql | 2 +- .../codeql/quantum/experimental/Model.qll | 101 +++++++++++------- 5 files changed, 83 insertions(+), 59 deletions(-) diff --git a/java/ql/lib/experimental/quantum/Language.qll b/java/ql/lib/experimental/quantum/Language.qll index 8e00f34f02b1..864ca6dd9317 100644 --- a/java/ql/lib/experimental/quantum/Language.qll +++ b/java/ql/lib/experimental/quantum/Language.qll @@ -42,19 +42,15 @@ module CryptoInput implements InputSig { } } -/** - * Instantiate the model - */ +// Instantiate the `CryptographyBase` module module Crypto = CryptographyBase; -/** - * Definitions of various generic data sources - */ +// Definitions of various generic sources final class DefaultFlowSource = SourceNode; final class DefaultRemoteFlowSource = RemoteFlowSource; -class GenericUnreferencedParameterSource extends Crypto::GenericUnreferencedParameterSource { +private class GenericUnreferencedParameterSource extends Crypto::GenericUnreferencedParameterSource { GenericUnreferencedParameterSource() { exists(Parameter p | this = p and not exists(p.getAnArgument())) } @@ -68,7 +64,7 @@ class GenericUnreferencedParameterSource extends Crypto::GenericUnreferencedPara override string getAdditionalDescription() { result = this.toString() } } -class GenericLocalDataSource extends Crypto::GenericLocalDataSource { +private class GenericLocalDataSource extends Crypto::GenericLocalDataSource { GenericLocalDataSource() { any(DefaultFlowSource src | not src instanceof DefaultRemoteFlowSource).asExpr() = this } @@ -82,7 +78,7 @@ class GenericLocalDataSource extends Crypto::GenericLocalDataSource { override string getAdditionalDescription() { result = this.toString() } } -class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { +private class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { GenericRemoteDataSource() { any(DefaultRemoteFlowSource src).asExpr() = this } override DataFlow::Node getOutputNode() { result.asExpr() = this } @@ -94,7 +90,7 @@ class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { override string getAdditionalDescription() { result = this.toString() } } -class ConstantDataSource extends Crypto::GenericConstantSourceInstance instanceof Literal { +private class ConstantDataSource extends Crypto::GenericConstantSourceInstance instanceof Literal { ConstantDataSource() { // TODO: this is an API specific workaround for JCA, as 'EC' is a constant that may be used // where typical algorithms are specified, but EC specifically means set up a @@ -114,14 +110,14 @@ class ConstantDataSource extends Crypto::GenericConstantSourceInstance instanceo } /** - * Random number generation, where each instance is modelled as the expression + * An instance of random number generation, modelled as the expression * tied to an output node (i.e., the result of the source of randomness) */ abstract class RandomnessInstance extends Crypto::RandomNumberGenerationInstance { override DataFlow::Node getOutputNode() { result.asExpr() = this } } -class SecureRandomnessInstance extends RandomnessInstance { +private class SecureRandomnessInstance extends RandomnessInstance { RandomDataSource source; SecureRandomnessInstance() { @@ -132,7 +128,7 @@ class SecureRandomnessInstance extends RandomnessInstance { override string getGeneratorName() { result = source.getSourceOfRandomness().getQualifiedName() } } -class InsecureRandomnessInstance extends RandomnessInstance { +private class InsecureRandomnessInstance extends RandomnessInstance { RandomDataSource source; InsecureRandomnessInstance() { @@ -143,7 +139,11 @@ class InsecureRandomnessInstance extends RandomnessInstance { } /** - * Artifact output to node input configuration + * An additional flow step in generic data-flow configurations. + * Where a step is an edge between nodes `n1` and `n2`, + * `this` = `n1` and `getOutput()` = `n2`. + * + * FOR INTERNAL MODELING USE ONLY. */ abstract class AdditionalFlowInputStep extends DataFlow::Node { abstract DataFlow::Node getOutput(); @@ -151,8 +151,6 @@ abstract class AdditionalFlowInputStep extends DataFlow::Node { final DataFlow::Node getInput() { result = this } } -module ArtifactFlow = DataFlow::Global; - /** * Generic data source to node input configuration */ @@ -214,5 +212,7 @@ module ArtifactFlowConfig implements DataFlow::ConfigSig { module GenericDataSourceFlow = TaintTracking::Global; +module ArtifactFlow = DataFlow::Global; + // Import library-specific modeling import JCA diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql index b4d0b908bbe1..e796cc9e1091 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql @@ -10,6 +10,5 @@ import java import experimental.quantum.Language -from Crypto::AlgorithmNode a -where Crypto::isKnownAsymmetricAlgorithm(a) +from Crypto::AsymmetricAlgorithmNode a select a, a.getAlgorithmName() diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql index 224ee1161fb0..98a8aa38a03e 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql @@ -10,6 +10,6 @@ import java import experimental.quantum.Language -from Crypto::OperationNode op, Crypto::AlgorithmNode a -where a = op.getAKnownAlgorithm() and Crypto::isKnownAsymmetricAlgorithm(a) +from Crypto::OperationNode op, Crypto::AsymmetricAlgorithmNode a +where a = op.getAKnownAlgorithm() select op, a.getAlgorithmName() diff --git a/java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql b/java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql index 2b81cf22dba5..14148354d0fc 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/LikelyCryptoAPIFunction.ql @@ -1,6 +1,6 @@ /** * @name Likely crypto API function - * @description Detects functions that take in crypto configuration parameters but calls are not detected in source. + * @description Outputs functions that take in crypto configuration parameters but calls are not detected in source. * @id java/quantum/slices/likely-crypto-api-function * @kind problem * @severity info diff --git a/shared/quantum/codeql/quantum/experimental/Model.qll b/shared/quantum/codeql/quantum/experimental/Model.qll index 69a4fd75acfa..54691c306bd6 100644 --- a/shared/quantum/codeql/quantum/experimental/Model.qll +++ b/shared/quantum/codeql/quantum/experimental/Model.qll @@ -3,7 +3,6 @@ */ import codeql.util.Location -import codeql.util.Either signature module InputSig { class LocatableElement { @@ -36,10 +35,20 @@ module CryptographyBase Input> { final class DataFlowNode = Input::DataFlowNode; + /** + * A `ConsumerInputDataFlowNode` is a `DataFlowNode` that represents a consumer of data. + * + * This class is equivalent to `DataFlowNode` but facilitates binding to a `ConsumerElement`. + */ class ConsumerInputDataFlowNode extends DataFlowNode { ConsumerElement getConsumer() { result.getInputNode() = this } } + /** + * An `ArtifactOutputDataFlowNode` is a `DataFlowNode` that represents the source of a created artifact. + * + * This class is equivalent to `DataFlowNode` but facilitates binding to an `OutputArtifactInstance`. + */ class ArtifactOutputDataFlowNode extends DataFlowNode { OutputArtifactInstance getArtifact() { result.getOutputNode() = this } } @@ -51,19 +60,17 @@ module CryptographyBase Input> { bindingset[root] private string getPropertyAsGraphString(NodeBase node, string key, Location root) { result = - strictconcat(any(string value, Location location, string parsed | - node.properties(key, value, location) and - ( - if location = root or location instanceof UnknownLocation - then parsed = value - else - parsed = - "(" + value + "," + Input::locationToFileBaseNameAndLineNumberString(location) + - ")" - ) - | - parsed - ), "," + strictconcat(string value, Location location, string parsed | + node.properties(key, value, location) and + ( + if location = root or location instanceof UnknownLocation + then parsed = value + else + parsed = + "(" + value + "," + Input::locationToFileBaseNameAndLineNumberString(location) + ")" + ) + | + parsed, "," ) } @@ -154,7 +161,7 @@ module CryptographyBase Input> { * CROSS PRODUCT WARNING: Modeling any *other* element that is a `FlowAwareElement` to the same * instance in the database will result in every `FlowAwareElement` sharing the output flow. */ - abstract class KnownElement extends LocatableElement { + abstract private class KnownElement extends LocatableElement { final ConsumerElement getAConsumer() { result.getAKnownSource() = this } } @@ -297,6 +304,23 @@ module CryptographyBase Input> { final override ConsumerInputDataFlowNode getInputNode() { result = input } } + /** + * An `AlgorithmValueConsumer` (_AVC_) is an element that consumes a value specifying an algorithm. + * + * Example 1: + * `arg0` of `set_algorithm` (`x`) is the AVC for the `ctx.encrypt()` operation. + * ```cpp + * x = "RSA"; + * ctx.set_algorithm(x); + * ctx.encrypt(); + * ``` + * + * Example 2: + * `encrypt_with_rsa` is concurrently an an operation, an AVC, and an algorithm. + * ```cpp + * `encrypt_with_rsa();` + * ``` + */ abstract class AlgorithmValueConsumer extends ConsumerElement { /** * DO NOT USE. @@ -324,8 +348,8 @@ module CryptographyBase Input> { * to the artifact it receives, thereby becoming the definitive contextual source for that artifact. * * Architectural Implications: - * * By directly coupling a consumer with the node that receives an artifact, - * the data flow is fully transparent with the consumer itself serving only as a transparent node. + * * By directly coupling a consumer with the node that receives an artifact, no modeling considerations have to be made + * to provide an interface for identifying the source via the consumer data-flow mechanisms. * * An artifact's properties (such as being a nonce) are not necessarily inherent; they are determined by the context in which the artifact is consumed. * The consumer node is therefore essential in defining these properties for inputs. * * This approach reduces ambiguity by avoiding separate notions of "artifact source" and "consumer", as the node itself encapsulates both roles. @@ -347,7 +371,7 @@ module CryptographyBase Input> { * A `NonceArtifactConsumer` is always the `NonceArtifactInstance` itself, since data only becomes (i.e., is determined to be) * a `NonceArtifactInstance` when it is consumed in a context that expects a nonce (e.g., an argument expecting nonce data). * - * In this case, the artifact (nonce) is fully defined by the context in which it is consumed, and the consumer embodies + * In this case, the artifact (nonce) is fully defined by the context in which it is consumed, and the consumer embodies * that identity without the need for additional differentiation. Without the context a consumer provides, that data could * otherwise be any other type of artifact or even simply random data. * @@ -604,7 +628,6 @@ module CryptographyBase Input> { type = TSymmetricCipher(SEED()) and size = 128 } - bindingset[type] predicate symmetric_cipher_to_name_and_structure( TSymmetricCipherType type, string name, CipherStructureType s ) { @@ -651,7 +674,6 @@ module CryptographyBase Input> { s = UnknownCipherStructureType() } - bindingset[type] predicate type_to_name(Algorithm type, string name) { // Symmetric cipher algorithm symmetric_cipher_to_name_and_structure(type.(SymmetricCipherAlgorithm).getType(), name, _) @@ -1551,6 +1573,20 @@ module CryptographyBase Input> { string toString() { result = super.getAlgorithmName() } } + /** + * The subset of algorithm nodes that are known asymmetric algorithm. + * + * Note: This is not an independent top-level node type. + */ + class AsymmetricAlgorithmNode extends TKeyCreationCandidateAlgorithm instanceof AlgorithmNode { + AsymmetricAlgorithmNode() { + this instanceof EllipticCurveNode or + this.(KeyOperationAlgorithmNode).isAsymmetric() + } + + string toString() { result = super.getAlgorithmName() } + } + /** * A cryptographic key, such as a symmetric key or asymmetric key pair. */ @@ -1709,7 +1745,6 @@ module CryptographyBase Input> { TMACType getMACType() { result = instance.asAlg().getMACType() } - bindingset[type] final private predicate macToNameMapping(TMACType type, string name) { type instanceof THMAC and name = "HMAC" @@ -2102,7 +2137,6 @@ module CryptographyBase Input> { */ TBlockCipherModeOfOperationType getModeType() { result = instance.getModeType() } - bindingset[type] final private predicate modeToNameMapping(TBlockCipherModeOfOperationType type, string name) { type = ECB() and name = "ECB" or @@ -2148,7 +2182,6 @@ module CryptographyBase Input> { TPaddingType getPaddingType() { result = instance.getPaddingType() } - bindingset[type] final private predicate paddingToNameMapping(TPaddingType type, string name) { type = ANSI_X9_23() and name = "ANSI_X9_23" or @@ -2454,9 +2487,9 @@ module CryptographyBase Input> { // ALL BRAINPOOL CURVES keySize in [160, 192, 224, 256, 320, 384, 512] and ( - curveName = "BRAINPOOLP" + keySize.toString() + "R1" + curveName = "BRAINPOOLP" + keySize + "R1" or - curveName = "BRAINPOOLP" + keySize.toString() + "T1" + curveName = "BRAINPOOLP" + keySize + "T1" ) } @@ -2464,8 +2497,8 @@ module CryptographyBase Input> { // ALL SEC CURVES keySize in [112, 113, 128, 131, 160, 163, 192, 193, 224, 233, 239, 256, 283, 384, 409, 521, 571] and exists(string suff | suff in ["R1", "R2", "K1"] | - curveName = "SECT" + keySize.toString() + suff or - curveName = "SECP" + keySize.toString() + suff + curveName = "SECT" + keySize + suff or + curveName = "SECP" + keySize + suff ) } @@ -2475,22 +2508,20 @@ module CryptographyBase Input> { exists(string pre, string suff | pre in ["PNB", "ONB", "TNB"] and suff in ["V1", "V2", "V3", "V4", "V5", "W1", "R1"] | - curveName = "C2" + pre + keySize.toString() + suff + curveName = "C2" + pre + keySize + suff ) } private predicate isPrimeCurve(string curveName, int keySize) { // ALL PRIME CURVES keySize in [192, 239, 256] and - exists(string suff | suff in ["V1", "V2", "V3"] | - curveName = "PRIME" + keySize.toString() + suff - ) + exists(string suff | suff in ["V1", "V2", "V3"] | curveName = "PRIME" + keySize + suff) } private predicate isNumsCurve(string curveName, int keySize) { // ALL NUMS CURVES keySize in [256, 384, 512] and - exists(string suff | suff = "T1" | curveName = "NUMSP" + keySize.toString() + suff) + exists(string suff | suff = "T1" | curveName = "NUMSP" + keySize + suff) } /** @@ -2587,10 +2618,4 @@ module CryptographyBase Input> { location = this.getLocation() } } - - predicate isKnownAsymmetricAlgorithm(AlgorithmNode node) { - node instanceof EllipticCurveNode - or - node instanceof KeyOperationAlgorithmNode and node.(KeyOperationAlgorithmNode).isAsymmetric() - } } From c66ec6333327b3430a02e166dce5fec7e5a40f88 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Mon, 12 May 2025 14:48:58 +0200 Subject: [PATCH 291/336] Fix query compilation errors --- java/ql/lib/experimental/quantum/Language.qll | 4 ++-- .../quantum/InventorySlices/KnownAsymmetricAlgorithm.ql | 2 +- .../InventorySlices/KnownAsymmetricOperationAlgorithm.ql | 2 +- shared/quantum/codeql/quantum/experimental/Model.qll | 4 +++- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/java/ql/lib/experimental/quantum/Language.qll b/java/ql/lib/experimental/quantum/Language.qll index 864ca6dd9317..59164901c10c 100644 --- a/java/ql/lib/experimental/quantum/Language.qll +++ b/java/ql/lib/experimental/quantum/Language.qll @@ -117,7 +117,7 @@ abstract class RandomnessInstance extends Crypto::RandomNumberGenerationInstance override DataFlow::Node getOutputNode() { result.asExpr() = this } } -private class SecureRandomnessInstance extends RandomnessInstance { +class SecureRandomnessInstance extends RandomnessInstance { RandomDataSource source; SecureRandomnessInstance() { @@ -128,7 +128,7 @@ private class SecureRandomnessInstance extends RandomnessInstance { override string getGeneratorName() { result = source.getSourceOfRandomness().getQualifiedName() } } -private class InsecureRandomnessInstance extends RandomnessInstance { +class InsecureRandomnessInstance extends RandomnessInstance { RandomDataSource source; InsecureRandomnessInstance() { diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql index e796cc9e1091..dbdc832c70b5 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricAlgorithm.ql @@ -11,4 +11,4 @@ import java import experimental.quantum.Language from Crypto::AsymmetricAlgorithmNode a -select a, a.getAlgorithmName() +select a, a.asAlgorithmNode().getAlgorithmName() diff --git a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql index 98a8aa38a03e..060b7df99a94 100644 --- a/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql +++ b/java/ql/src/experimental/quantum/InventorySlices/KnownAsymmetricOperationAlgorithm.ql @@ -12,4 +12,4 @@ import experimental.quantum.Language from Crypto::OperationNode op, Crypto::AsymmetricAlgorithmNode a where a = op.getAKnownAlgorithm() -select op, a.getAlgorithmName() +select op, a.asAlgorithmNode().getAlgorithmName() diff --git a/shared/quantum/codeql/quantum/experimental/Model.qll b/shared/quantum/codeql/quantum/experimental/Model.qll index 54691c306bd6..1a192e84778f 100644 --- a/shared/quantum/codeql/quantum/experimental/Model.qll +++ b/shared/quantum/codeql/quantum/experimental/Model.qll @@ -1584,7 +1584,9 @@ module CryptographyBase Input> { this.(KeyOperationAlgorithmNode).isAsymmetric() } - string toString() { result = super.getAlgorithmName() } + string toString() { result = super.toString() } + + AlgorithmNode asAlgorithmNode() { result = this } } /** From 5334e907170ec18ef4b2a538dea4dbf55d8d3a47 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Mon, 12 May 2025 14:58:04 +0200 Subject: [PATCH 292/336] Make FlowAwareElement private --- shared/quantum/codeql/quantum/experimental/Model.qll | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/shared/quantum/codeql/quantum/experimental/Model.qll b/shared/quantum/codeql/quantum/experimental/Model.qll index 1a192e84778f..a87aee2e69c4 100644 --- a/shared/quantum/codeql/quantum/experimental/Model.qll +++ b/shared/quantum/codeql/quantum/experimental/Model.qll @@ -130,7 +130,7 @@ module CryptographyBase Input> { /** * An element that is flow-aware, i.e., it has an input and output node implicitly used for data flow analysis. */ - abstract class FlowAwareElement extends LocatableElement { + abstract private class FlowAwareElementImpl extends LocatableElement { /** * Gets the output node for this element, which should usually be the same as `this`. */ @@ -155,6 +155,8 @@ module CryptographyBase Input> { abstract predicate flowsTo(FlowAwareElement other); } + final class FlowAwareElement = FlowAwareElementImpl; + /** * An element that represents a _known_ cryptographic asset with a determinable value OR an artifact. * @@ -187,7 +189,7 @@ module CryptographyBase Input> { * 1. A value (e.g., a string or integer literal) *or* * 1. An input for which a value cannot be determined (e.g., `argv`, file system reads, and web request headers) */ - abstract class GenericSourceInstance extends FlowAwareElement { + abstract class GenericSourceInstance extends FlowAwareElementImpl { final override ConsumerInputDataFlowNode getInputNode() { none() } abstract string getInternalType(); @@ -257,7 +259,7 @@ module CryptographyBase Input> { * * A consumer can consume multiple instances and types of assets at once, e.g., both a `PaddingAlgorithm` and `CipherAlgorithm`. */ - abstract private class ConsumerElement extends FlowAwareElement { + abstract private class ConsumerElement extends FlowAwareElementImpl { abstract KnownElement getAKnownSource(); override predicate flowsTo(FlowAwareElement other) { none() } @@ -337,7 +339,7 @@ module CryptographyBase Input> { /** * An element that represents a _known_ cryptographic artifact. */ - abstract class ArtifactInstance extends KnownElement, FlowAwareElement { + abstract class ArtifactInstance extends KnownElement, FlowAwareElementImpl { abstract predicate isConsumerArtifact(); // whether this is an input artifact defined by its consumer } From 08fcf6114fcae46e1044f614b61370f263a5f43f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 12 May 2025 16:01:52 +0100 Subject: [PATCH 293/336] Apply suggestions from code review Co-authored-by: Simon Friis Vindum --- .../ql/test/library-tests/dataflow/sources/web_frameworks.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs index e3ab61274d23..ec742c71459c 100644 --- a/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs +++ b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs @@ -1,4 +1,3 @@ -#![allow(deprecated)] fn sink(_: T) { } @@ -7,7 +6,7 @@ fn sink(_: T) { } mod poem_test { use poem::{get, handler, web::Path, web::Query, Route, Server, listener::TcpListener}; use serde::Deserialize; - use crate::web_frameworks::sink; + use super::sink; #[handler] fn my_poem_handler_1(Path(a): Path) -> String { // $ Alert[rust/summary/taint-sources] @@ -74,7 +73,7 @@ mod poem_test { .at("/5/:a/:b", get(my_poem_handler_5)) .at("/6/:a/", get(my_poem_handler_6)); - _ = Server::new(TcpListener::bind("0.0.0.0:3000")).run(app).await.unwrap(); + Server::new(TcpListener::bind("0.0.0.0:3000")).run(app).await.unwrap(); // ... } From bf8cdffffad96160043d9c3f67fd22070d31391c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 12 May 2025 16:06:33 +0100 Subject: [PATCH 294/336] Update rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs Co-authored-by: Simon Friis Vindum --- rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs index ec742c71459c..2e4ac22257fc 100644 --- a/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs +++ b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs @@ -80,7 +80,7 @@ mod poem_test { } mod actix_test { - use actix_web::{get, web, App, HttpServer}; + use actix_web::{get, web, App}; use crate::web_frameworks::sink; async fn my_actix_handler_1(path: web::Path) -> String { // $ MISSING: Alert[rust/summary/taint-sources] From 402a84f755082a046259d9d852999c3abd3e2c88 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 12 May 2025 16:17:26 +0100 Subject: [PATCH 295/336] Update rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs Co-authored-by: Simon Friis Vindum --- rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs index 2e4ac22257fc..a6949c569c0a 100644 --- a/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs +++ b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs @@ -81,7 +81,7 @@ mod poem_test { mod actix_test { use actix_web::{get, web, App}; - use crate::web_frameworks::sink; + use super::sink; async fn my_actix_handler_1(path: web::Path) -> String { // $ MISSING: Alert[rust/summary/taint-sources] let a = path.into_inner(); From 7c98fa87dae9c004ac32cca0c14b5669d9fe28cc Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 12 May 2025 16:18:16 +0100 Subject: [PATCH 296/336] Rust: One more bit of cleanup. --- .../dataflow/sources/TaintSources.expected | 10 +++++----- .../library-tests/dataflow/sources/web_frameworks.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index 7a5fd2d000f5..11d0df45d590 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -47,8 +47,8 @@ | test.rs:369:25:369:43 | ...::open | Flow source 'FileSource' of type file (DEFAULT). | | test.rs:377:22:377:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). | | test.rs:386:16:386:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | -| web_frameworks.rs:13:31:13:31 | a | Flow source 'RemoteSource' of type remote (DEFAULT). | -| web_frameworks.rs:22:31:22:36 | TuplePat | Flow source 'RemoteSource' of type remote (DEFAULT). | -| web_frameworks.rs:44:31:44:45 | MyStruct {...} | Flow source 'RemoteSource' of type remote (DEFAULT). | -| web_frameworks.rs:52:31:52:32 | ms | Flow source 'RemoteSource' of type remote (DEFAULT). | -| web_frameworks.rs:61:15:61:15 | a | Flow source 'RemoteSource' of type remote (DEFAULT). | +| web_frameworks.rs:12:31:12:31 | a | Flow source 'RemoteSource' of type remote (DEFAULT). | +| web_frameworks.rs:21:31:21:36 | TuplePat | Flow source 'RemoteSource' of type remote (DEFAULT). | +| web_frameworks.rs:43:31:43:45 | MyStruct {...} | Flow source 'RemoteSource' of type remote (DEFAULT). | +| web_frameworks.rs:51:31:51:32 | ms | Flow source 'RemoteSource' of type remote (DEFAULT). | +| web_frameworks.rs:60:15:60:15 | a | Flow source 'RemoteSource' of type remote (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs index a6949c569c0a..6bfee08a3d2d 100644 --- a/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs +++ b/rust/ql/test/library-tests/dataflow/sources/web_frameworks.rs @@ -131,7 +131,7 @@ mod axum_test { use axum::routing::get; use axum::extract::{Path, Query, Request, Json}; use std::collections::HashMap; - use crate::web_frameworks::sink; + use super::sink; async fn my_axum_handler_1(Path(a): Path) -> &'static str { // $ MISSING: Alert[rust/summary/taint-sources] sink(a.as_str()); // $ MISSING: hasTaintFlow From 9160036e416a82158d88e5ae10bbd04077965efd Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 12 May 2025 16:45:41 +0100 Subject: [PATCH 297/336] Rust: Rename OperationImpl -> Impl. --- rust/ql/lib/codeql/rust/elements/Operation.qll | 2 +- rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/Operation.qll b/rust/ql/lib/codeql/rust/elements/Operation.qll index b3615bddb33e..dad24e980eda 100644 --- a/rust/ql/lib/codeql/rust/elements/Operation.qll +++ b/rust/ql/lib/codeql/rust/elements/Operation.qll @@ -2,7 +2,7 @@ * Provides classes for operations. */ -import internal.OperationImpl +import internal.OperationImpl::Impl as OperationImpl private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl final class Operation = OperationImpl::Operation; diff --git a/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll index 7b2d1a9d62e2..deffd72086d6 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll @@ -11,7 +11,7 @@ private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl * INTERNAL: This module contains the customizable definition of `Operation` and should not * be referenced directly. */ -module OperationImpl { +module Impl { /** * An operation, for example `&&`, `+=`, `!` or `*`. */ From a2944cdb61c6af07b7ccd57745c6211648b08d10 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 12 May 2025 16:48:06 +0100 Subject: [PATCH 298/336] Rust: Make usage of Impl more consistent with other Impl modules. --- rust/ql/lib/codeql/rust/elements/Operation.qll | 4 ++-- rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll | 2 +- rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/Operation.qll b/rust/ql/lib/codeql/rust/elements/Operation.qll index dad24e980eda..035e4ce81f2b 100644 --- a/rust/ql/lib/codeql/rust/elements/Operation.qll +++ b/rust/ql/lib/codeql/rust/elements/Operation.qll @@ -2,7 +2,7 @@ * Provides classes for operations. */ -import internal.OperationImpl::Impl as OperationImpl +private import internal.OperationImpl private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl -final class Operation = OperationImpl::Operation; +final class Operation = Impl::Operation; diff --git a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll index 42ac0521db3c..966d64936377 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll @@ -5,7 +5,7 @@ */ private import codeql.rust.elements.internal.generated.BinaryExpr -private import codeql.rust.elements.Operation::OperationImpl as OperationImpl +private import codeql.rust.elements.internal.OperationImpl::Impl as OperationImpl /** * INTERNAL: This module contains the customizable definition of `BinaryExpr` and should not diff --git a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll index 56cc43babd0c..75e2969fabc5 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll @@ -5,7 +5,7 @@ */ private import codeql.rust.elements.internal.generated.PrefixExpr -private import codeql.rust.elements.Operation::OperationImpl as OperationImpl +private import codeql.rust.elements.internal.OperationImpl::Impl as OperationImpl /** * INTERNAL: This module contains the customizable definition of `PrefixExpr` and should not From cd01bd0e0747584f1074f55e94dbdbf2ffe76998 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 12 May 2025 20:19:47 +0200 Subject: [PATCH 299/336] Rust: Add `LiteralExpr` sub classes --- .../codeql/rust/elements/LiteralExprExt.qll | 15 ++ .../elements/internal/LiteralExprImpl.qll | 187 ++++++++++++++++++ rust/ql/lib/rust.qll | 1 + .../extractor-tests/literal/literal.expected | 42 ++++ .../test/extractor-tests/literal/literal.ql | 13 ++ .../test/extractor-tests/literal/literal.rs | 65 ++++++ 6 files changed, 323 insertions(+) create mode 100644 rust/ql/lib/codeql/rust/elements/LiteralExprExt.qll create mode 100644 rust/ql/test/extractor-tests/literal/literal.expected create mode 100644 rust/ql/test/extractor-tests/literal/literal.ql create mode 100644 rust/ql/test/extractor-tests/literal/literal.rs diff --git a/rust/ql/lib/codeql/rust/elements/LiteralExprExt.qll b/rust/ql/lib/codeql/rust/elements/LiteralExprExt.qll new file mode 100644 index 000000000000..e86d45c71120 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/LiteralExprExt.qll @@ -0,0 +1,15 @@ +/** Provides sub classes of literal expressions. */ + +private import internal.LiteralExprImpl + +final class CharLiteralExpr = Impl::CharLiteralExpr; + +final class StringLiteralExpr = Impl::StringLiteralExpr; + +final class NumberLiteralExpr = Impl::NumberLiteralExpr; + +final class IntegerLiteralExpr = Impl::IntegerLiteralExpr; + +final class FloatLiteralExpr = Impl::FloatLiteralExpr; + +final class BooleanLiteralExpr = Impl::BooleanLiteralExpr; diff --git a/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll index 6a8d02d9380e..c424ff5471da 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll @@ -42,4 +42,191 @@ module Impl { ) } } + + /** + * A [character literal][1]. For example: + * + * ```rust + * 'x'; + * ``` + * + * [1]: https://doc.rust-lang.org/reference/tokens.html#character-literals + */ + class CharLiteralExpr extends LiteralExpr { + CharLiteralExpr() { + // todo: proper implementation + this.getTextValue().regexpMatch("'.*'") + } + + override string getAPrimaryQlClass() { result = "CharLiteralExpr" } + } + + /** + * A [string literal][1]. For example: + * + * ```rust + * "Hello, world!"; + * ``` + * + * [1]: https://doc.rust-lang.org/reference/tokens.html#string-literals + */ + class StringLiteralExpr extends LiteralExpr { + StringLiteralExpr() { + // todo: proper implementation + this.getTextValue().regexpMatch("r?#*\".*\"#*") + } + + override string getAPrimaryQlClass() { result = "StringLiteralExpr" } + } + + /** + * A number literal. + */ + abstract class NumberLiteralExpr extends LiteralExpr { } + + // https://doc.rust-lang.org/reference/tokens.html#integer-literals + private module IntegerLiteralRegexs { + bindingset[s] + string paren(string s) { result = "(" + s + ")" } + + string integerLiteral() { + result = + paren(paren(decLiteral()) + "|" + paren(binLiteral()) + "|" + paren(octLiteral()) + "|" + + paren(hexLiteral())) + paren(suffix()) + "?" + } + + private string suffix() { result = "u8|i8|u16|i16|u32|i32|u64|i64|u128|i128|usize|isize" } + + string decLiteral() { result = decDigit() + "(" + decDigit() + "|_)*" } + + string binLiteral() { + result = "0b(" + binDigit() + "|_)*" + binDigit() + "(" + binDigit() + "|_)*" + } + + string octLiteral() { + result = "0o(" + octDigit() + "|_)*" + octDigit() + "(" + octDigit() + "|_)*" + } + + string hexLiteral() { + result = "0x(" + hexDigit() + "|_)*" + hexDigit() + "(" + hexDigit() + "|_)*" + } + + string decDigit() { result = "[0-9]" } + + string binDigit() { result = "[01]" } + + string octDigit() { result = "[0-7]" } + + string hexDigit() { result = "[0-9a-fA-F]" } + } + + /** + * An [integer literal][1]. For example: + * + * ```rust + * 42; + * ``` + * + * [1]: https://doc.rust-lang.org/reference/tokens.html#integer-literals + */ + class IntegerLiteralExpr extends NumberLiteralExpr { + IntegerLiteralExpr() { this.getTextValue().regexpMatch(IntegerLiteralRegexs::integerLiteral()) } + + /** + * Get the suffix of this integer literal, if any. + * + * For example, `42u8` has the suffix `u8`. + */ + string getSuffix() { + exists(string s, string reg, int last | + s = this.getTextValue() and + reg = IntegerLiteralRegexs::integerLiteral() and + last = strictcount(reg.indexOf("(")) and + result = s.regexpCapture(reg, last) + ) + } + + override string getAPrimaryQlClass() { result = "IntegerLiteralExpr" } + } + + // https://doc.rust-lang.org/reference/tokens.html#floating-point-literals + private module FloatLiteralRegexs { + private import IntegerLiteralRegexs + + string floatLiteral() { + result = + paren(decLiteral() + "\\.") + "|" + paren(floatLiteralSuffix1()) + "|" + + paren(floatLiteralSuffix2()) + } + + string floatLiteralSuffix1() { + result = decLiteral() + "\\." + decLiteral() + paren(suffix()) + "?" + } + + string floatLiteralSuffix2() { + result = + decLiteral() + paren("\\." + decLiteral()) + "?" + paren(exponent()) + paren(suffix()) + "?" + } + + string integerSuffixLiteral() { + result = + paren(paren(decLiteral()) + "|" + paren(binLiteral()) + "|" + paren(octLiteral()) + "|" + + paren(hexLiteral())) + paren(suffix()) + } + + private string suffix() { result = "f32|f64" } + + string exponent() { + result = "(e|E)(\\+|-)?(" + decDigit() + "|_)*" + decDigit() + "(" + decDigit() + "|_)*" + } + } + + /** + * A [floating-point literal][1]. For example: + * + * ```rust + * 42.0; + * ``` + * + * [1]: https://doc.rust-lang.org/reference/tokens.html#floating-point-literals + */ + class FloatLiteralExpr extends NumberLiteralExpr { + FloatLiteralExpr() { + this.getTextValue() + .regexpMatch([ + FloatLiteralRegexs::floatLiteral(), FloatLiteralRegexs::integerSuffixLiteral() + ]) and + // E.g. `0x01_f32` is an integer, not a float + not this instanceof IntegerLiteralExpr + } + + /** + * Get the suffix of this floating-point literal, if any. + * + * For example, `42.0f32` has the suffix `f32`. + */ + string getSuffix() { + exists(string s, string reg, int last | + s = this.getTextValue() and + reg = + [ + FloatLiteralRegexs::floatLiteralSuffix1(), FloatLiteralRegexs::floatLiteralSuffix2(), + FloatLiteralRegexs::integerSuffixLiteral() + ] and + last = strictcount(reg.indexOf("(")) and + result = s.regexpCapture(reg, last) + ) + } + + override string getAPrimaryQlClass() { result = "FloatLiteralExpr" } + } + + /** + * A Boolean literal. Either `true` or `false`. + */ + class BooleanLiteralExpr extends LiteralExpr { + BooleanLiteralExpr() { this.getTextValue() = ["false", "true"] } + + override string getAPrimaryQlClass() { result = "BooleanLiteralExpr" } + } } diff --git a/rust/ql/lib/rust.qll b/rust/ql/lib/rust.qll index ff97a37b5d1f..b64f37533aa1 100644 --- a/rust/ql/lib/rust.qll +++ b/rust/ql/lib/rust.qll @@ -4,6 +4,7 @@ import codeql.rust.elements import codeql.Locations import codeql.files.FileSystem import codeql.rust.elements.AssignmentOperation +import codeql.rust.elements.LiteralExprExt import codeql.rust.elements.LogicalOperation import codeql.rust.elements.AsyncBlockExpr import codeql.rust.elements.Variable diff --git a/rust/ql/test/extractor-tests/literal/literal.expected b/rust/ql/test/extractor-tests/literal/literal.expected new file mode 100644 index 000000000000..55d1ac11013c --- /dev/null +++ b/rust/ql/test/extractor-tests/literal/literal.expected @@ -0,0 +1,42 @@ +charLiteral +| literal.rs:2:5:2:7 | 'a' | +| literal.rs:3:5:3:7 | 'b' | +stringLiteral +| literal.rs:8:5:8:9 | "foo" | +| literal.rs:9:5:9:10 | r"foo" | +| literal.rs:10:5:10:13 | "\\"foo\\"" | +| literal.rs:11:5:11:14 | r#""foo""# | +| literal.rs:13:5:13:18 | "foo #\\"# bar" | +| literal.rs:14:5:14:22 | r##"foo #"# bar"## | +| literal.rs:16:5:16:10 | "\\x52" | +| literal.rs:17:5:17:7 | "R" | +| literal.rs:18:5:18:8 | r"R" | +| literal.rs:19:5:19:11 | "\\\\x52" | +| literal.rs:20:5:20:11 | r"\\x52" | +integerLiteral +| literal.rs:25:5:25:7 | 123 | | +| literal.rs:26:5:26:10 | 123i32 | i32 | +| literal.rs:27:5:27:10 | 123u32 | u32 | +| literal.rs:28:5:28:11 | 123_u32 | u32 | +| literal.rs:30:5:30:8 | 0xff | | +| literal.rs:31:5:31:11 | 0xff_u8 | u8 | +| literal.rs:32:5:32:12 | 0x01_f32 | | +| literal.rs:33:5:33:11 | 0x01_e3 | | +| literal.rs:35:5:35:8 | 0o70 | | +| literal.rs:36:5:36:12 | 0o70_i16 | i16 | +| literal.rs:38:5:38:25 | 0b1111_1111_1001_0000 | | +| literal.rs:39:5:39:28 | 0b1111_1111_1001_0000i64 | i64 | +| literal.rs:40:5:40:15 | 0b________1 | | +| literal.rs:42:5:42:10 | 0usize | usize | +| literal.rs:45:5:46:10 | 128_i8 | i8 | +| literal.rs:47:5:48:10 | 256_u8 | u8 | +floatLiteral +| literal.rs:53:5:53:8 | 5f32 | f32 | +| literal.rs:55:5:55:12 | 123.0f64 | f64 | +| literal.rs:56:5:56:10 | 0.1f64 | f64 | +| literal.rs:57:5:57:10 | 0.1f32 | f32 | +| literal.rs:58:5:58:14 | 12E+99_f64 | f64 | +| literal.rs:59:18:59:19 | 2. | | +booleanLiteral +| literal.rs:63:5:63:8 | true | +| literal.rs:64:5:64:9 | false | diff --git a/rust/ql/test/extractor-tests/literal/literal.ql b/rust/ql/test/extractor-tests/literal/literal.ql new file mode 100644 index 000000000000..3585ad2f5b91 --- /dev/null +++ b/rust/ql/test/extractor-tests/literal/literal.ql @@ -0,0 +1,13 @@ +import rust + +query predicate charLiteral(CharLiteralExpr e) { any() } + +query predicate stringLiteral(StringLiteralExpr e) { any() } + +query predicate integerLiteral(IntegerLiteralExpr e, string suffix) { + suffix = concat(e.getSuffix()) +} + +query predicate floatLiteral(FloatLiteralExpr e, string suffix) { suffix = concat(e.getSuffix()) } + +query predicate booleanLiteral(BooleanLiteralExpr e) { any() } diff --git a/rust/ql/test/extractor-tests/literal/literal.rs b/rust/ql/test/extractor-tests/literal/literal.rs new file mode 100644 index 000000000000..74503f2a24e4 --- /dev/null +++ b/rust/ql/test/extractor-tests/literal/literal.rs @@ -0,0 +1,65 @@ +fn char_literals() { + 'a'; + 'b'; +} + +fn string_literals() { + // from https://doc.rust-lang.org/reference/tokens.html#string-literals + "foo"; + r"foo"; // foo + "\"foo\""; + r#""foo""#; // "foo" + + "foo #\"# bar"; + r##"foo #"# bar"##; // foo #"# bar + + "\x52"; + "R"; + r"R"; // R + "\\x52"; + r"\x52"; // \x52 +} + +fn integer_literals() { + // from https://doc.rust-lang.org/reference/tokens.html#integer-literals + 123; + 123i32; + 123u32; + 123_u32; + + 0xff; + 0xff_u8; + 0x01_f32; // integer 7986, not floating-point 1.0 + 0x01_e3; // integer 483, not floating-point 1000.0 + + 0o70; + 0o70_i16; + + 0b1111_1111_1001_0000; + 0b1111_1111_1001_0000i64; + 0b________1; + + 0usize; + + // These are too big for their type, but are accepted as literal expressions. + #[allow(overflowing_literals)] + 128_i8; + #[allow(overflowing_literals)] + 256_u8; +} + +fn float_literals() { + // This is an integer literal, accepted as a floating-point literal expression. + 5f32; + + 123.0f64; + 0.1f64; + 0.1f32; + 12E+99_f64; + let x: f64 = 2.; +} + +fn boolean_literals() { + true; + false; +} From e51cb478af4f8a8bca580592a7fb800a87ee83c4 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 12 May 2025 19:43:19 +0100 Subject: [PATCH 300/336] C++: Expose 'MemoryLocation0'. --- .../cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll | 2 +- .../cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll index acb17006fefb..b5937815dab5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll @@ -235,7 +235,7 @@ private newtype TMemoryLocation = * * Some of these memory locations will be filtered out for performance reasons before being passed to SSA construction. */ -abstract private class MemoryLocation0 extends TMemoryLocation { +abstract class MemoryLocation0 extends TMemoryLocation { final string toString() { if this.isMayAccess() then result = "?" + this.toStringInternal() diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll index 8bee2bf86a77..b3922bb2bd45 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll @@ -73,6 +73,8 @@ class MemoryLocation extends TMemoryLocation { final predicate canReuseSsa() { canReuseSsaForVariable(var) } } +class MemoryLocation0 = MemoryLocation; + predicate canReuseSsaForOldResult(Instruction instr) { none() } abstract class VariableGroup extends Unit { From f1b4e05579f3cc497058902839b773395844af7d Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 12 May 2025 19:45:19 +0100 Subject: [PATCH 301/336] C++: Expose 'isBusyDef'. --- .../ir/implementation/aliased_ssa/internal/AliasedSSA.qll | 2 +- .../ir/implementation/unaliased_ssa/internal/SimpleSSA.qll | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll index b5937815dab5..522cd393081e 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll @@ -874,7 +874,7 @@ private int numberOfOverlappingUses(MemoryLocation0 def) { * Holds if `def` is a busy definition. That is, it has a large number of * overlapping uses. */ -private predicate isBusyDef(MemoryLocation0 def) { numberOfOverlappingUses(def) > 1024 } +predicate isBusyDef(MemoryLocation0 def) { numberOfOverlappingUses(def) > 1024 } /** Holds if `use` is a use that overlaps with a busy definition. */ private predicate useOverlapWithBusyDef(MemoryLocation0 use) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll index b3922bb2bd45..39283d07b54c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll @@ -143,3 +143,9 @@ int getStartBitOffset(MemoryLocation location) { none() } /** Gets the end bit offset of a `MemoryLocation`, if any. */ int getEndBitOffset(MemoryLocation location) { none() } + +/** + * Holds if `def` is a busy definition. That is, it has a large number of + * overlapping uses. + */ +predicate isBusyDef(MemoryLocation def) { none() } From a50167812d046a3a7026c0aaddb9e927a32ec4ee Mon Sep 17 00:00:00 2001 From: yoff Date: Mon, 12 May 2025 20:53:04 +0200 Subject: [PATCH 302/336] ruby: adjust precision of `rb/useless-assignment-to-local` from `medium` to `high` --- .../query-suite/ruby-code-quality.qls.expected | 1 + ...25-05-12-rb-useless-assignment-to-local-precision-high.md | 5 +++++ ruby/ql/src/queries/variables/DeadStoreOfLocal.ql | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 ruby/ql/src/change-notes/2025-05-12-rb-useless-assignment-to-local-precision-high.md diff --git a/ruby/ql/integration-tests/query-suite/ruby-code-quality.qls.expected b/ruby/ql/integration-tests/query-suite/ruby-code-quality.qls.expected index db6b75902201..94b2f19caaa8 100644 --- a/ruby/ql/integration-tests/query-suite/ruby-code-quality.qls.expected +++ b/ruby/ql/integration-tests/query-suite/ruby-code-quality.qls.expected @@ -1,2 +1,3 @@ ql/ruby/ql/src/queries/performance/DatabaseQueryInLoop.ql +ql/ruby/ql/src/queries/variables/DeadStoreOfLocal.ql ql/ruby/ql/src/queries/variables/UninitializedLocal.ql diff --git a/ruby/ql/src/change-notes/2025-05-12-rb-useless-assignment-to-local-precision-high.md b/ruby/ql/src/change-notes/2025-05-12-rb-useless-assignment-to-local-precision-high.md new file mode 100644 index 000000000000..c62510ba5ba4 --- /dev/null +++ b/ruby/ql/src/change-notes/2025-05-12-rb-useless-assignment-to-local-precision-high.md @@ -0,0 +1,5 @@ +--- +category: queryMetadata +--- + +* The precision of `rb/useless-assignment-to-local` has been adjusted from `medium` to `high`. diff --git a/ruby/ql/src/queries/variables/DeadStoreOfLocal.ql b/ruby/ql/src/queries/variables/DeadStoreOfLocal.ql index a7b37515d7fe..808ce42dd85d 100644 --- a/ruby/ql/src/queries/variables/DeadStoreOfLocal.ql +++ b/ruby/ql/src/queries/variables/DeadStoreOfLocal.ql @@ -8,7 +8,7 @@ * @tags maintainability * quality * external/cwe/cwe-563 - * @precision medium + * @precision high */ import codeql.ruby.AST From ffd6b2677c5a6af5af06da8eca02c3ac4371f6fb Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 12 May 2025 11:09:34 +0200 Subject: [PATCH 303/336] C#: Cleanup test options files. --- csharp/ql/test/experimental/CWE-918/options | 3 +-- .../CWE-1004/CookieHttpOnlyFalseSystemWeb/options | 1 - .../CookieWithoutHttpOnlySystemWeb/ConfigEmpty/options | 1 - .../CookieWithoutHttpOnlySystemWeb/ConfigFalse/options | 1 - .../CookieWithoutHttpOnlySystemWeb/HttpCookiesTrue/options | 1 - .../CWE-614/RequireSSLFalseSystemWeb/options | 1 - .../CWE-614/RequireSSLSystemWeb/ConfigEmpty/options | 1 - .../CWE-614/RequireSSLSystemWeb/ConfigFalse/options | 1 - .../CWE-614/RequireSSLSystemWeb/FormsTrue/options | 1 - .../CWE-614/RequireSSLSystemWeb/HttpCookiesTrue/options | 1 - .../ql/test/library-tests/dataflow/flowsources/remote/options | 4 ++-- csharp/ql/test/library-tests/dataflow/global/options | 3 +-- csharp/ql/test/query-tests/Security Features/CWE-020/options | 1 - .../query-tests/Security Features/CWE-022/TaintedPath/options | 1 - .../query-tests/Security Features/CWE-079/StoredXSS/options | 1 - csharp/ql/test/query-tests/Security Features/CWE-090/options | 1 - .../Security Features/CWE-091/XMLInjection/options | 1 - csharp/ql/test/query-tests/Security Features/CWE-094/options | 1 - csharp/ql/test/query-tests/Security Features/CWE-099/options | 1 - csharp/ql/test/query-tests/Security Features/CWE-112/options | 1 - .../Security Features/CWE-114/AssemblyPathInjection/options | 1 - csharp/ql/test/query-tests/Security Features/CWE-117/options | 1 - csharp/ql/test/query-tests/Security Features/CWE-134/options | 1 - .../CWE-201/ExposureInTransmittedData/options | 1 - csharp/ql/test/query-tests/Security Features/CWE-209/options | 1 - .../MissingASPNETGlobalErrorHandler/WebConfigOff/options | 1 - .../WebConfigOffButGlobal/options | 1 - .../CWE-285/MissingAccessControl/WebFormsTests/options | 3 +-- csharp/ql/test/query-tests/Security Features/CWE-312/options | 1 - .../test/query-tests/Security Features/CWE-352/global/options | 1 - .../query-tests/Security Features/CWE-352/missing/options | 1 - csharp/ql/test/query-tests/Security Features/CWE-359/options | 1 - csharp/ql/test/query-tests/Security Features/CWE-384/options | 1 - .../CWE-451/MissingXFrameOptions/CodeAddedHeader/options | 1 - .../CWE-451/MissingXFrameOptions/NoHeader/options | 1 - .../CWE-451/MissingXFrameOptions/WebConfigAddedHeader/options | 1 - .../Security Features/CWE-502/UnsafeDeserialization/options | 1 - .../CWE-502/UnsafeDeserializationUntrustedInput/options | 1 - .../UnsafeDeserializationUntrustedInputNewtonsoftJson/options | 1 - .../Security Features/CWE-539/PersistentCookie/options | 1 - .../query-tests/Security Features/CWE-601/UrlRedirect/options | 1 - .../Security Features/CWE-614/RequireSSL/AddedInCode/options | 1 - .../Security Features/CWE-639/WebFormsTests/options | 3 +-- csharp/ql/test/query-tests/Security Features/CWE-643/options | 1 - .../test/query-tests/Security Features/CWE-730/ReDoS/options | 1 - .../Security Features/CWE-730/ReDoSGlobalTimeout/options | 1 - .../Security Features/CWE-730/RegexInjection/options | 1 - csharp/ql/test/query-tests/Security Features/CWE-807/options | 1 - csharp/ql/test/query-tests/Security Features/CWE-838/options | 1 - .../test/query-tests/Telemetry/SupportedExternalApis/options | 1 - .../test/query-tests/Telemetry/SupportedExternalSinks/options | 1 - csharp/ql/test/utils/modelgenerator/dataflow/options | 3 +-- 52 files changed, 7 insertions(+), 58 deletions(-) diff --git a/csharp/ql/test/experimental/CWE-918/options b/csharp/ql/test/experimental/CWE-918/options index 914a0be40c93..f81b977ac98d 100644 --- a/csharp/ql/test/experimental/CWE-918/options +++ b/csharp/ql/test/experimental/CWE-918/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj -semmle-extractor-options: ${testdir}/../../resources/stubs/System.Web.cs \ No newline at end of file +semmle-extractor-options: ${testdir}/../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieHttpOnlyFalseSystemWeb/options b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieHttpOnlyFalseSystemWeb/options index daca5d73f552..9290f65d5b22 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieHttpOnlyFalseSystemWeb/options +++ b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieHttpOnlyFalseSystemWeb/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigEmpty/options b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigEmpty/options index dbb615bf06c0..9d05f9bf06d4 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigEmpty/options +++ b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigEmpty/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigFalse/options b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigFalse/options index dbb615bf06c0..9d05f9bf06d4 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigFalse/options +++ b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/ConfigFalse/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/HttpCookiesTrue/options b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/HttpCookiesTrue/options index dbb615bf06c0..9d05f9bf06d4 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/HttpCookiesTrue/options +++ b/csharp/ql/test/experimental/Security Features/CWE-1004/CookieWithoutHttpOnlySystemWeb/HttpCookiesTrue/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLFalseSystemWeb/options b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLFalseSystemWeb/options index daca5d73f552..9290f65d5b22 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLFalseSystemWeb/options +++ b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLFalseSystemWeb/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigEmpty/options b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigEmpty/options index dbb615bf06c0..9d05f9bf06d4 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigEmpty/options +++ b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigEmpty/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigFalse/options b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigFalse/options index dbb615bf06c0..9d05f9bf06d4 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigFalse/options +++ b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/ConfigFalse/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/FormsTrue/options b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/FormsTrue/options index dbb615bf06c0..9d05f9bf06d4 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/FormsTrue/options +++ b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/FormsTrue/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/HttpCookiesTrue/options b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/HttpCookiesTrue/options index dbb615bf06c0..9d05f9bf06d4 100644 --- a/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/HttpCookiesTrue/options +++ b/csharp/ql/test/experimental/Security Features/CWE-614/RequireSSLSystemWeb/HttpCookiesTrue/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/library-tests/dataflow/flowsources/remote/options b/csharp/ql/test/library-tests/dataflow/flowsources/remote/options index 1fcc7e1cf48f..63ce15b2b4f4 100644 --- a/csharp/ql/test/library-tests/dataflow/flowsources/remote/options +++ b/csharp/ql/test/library-tests/dataflow/flowsources/remote/options @@ -1,4 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj -semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs \ No newline at end of file +semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs +semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.Http.cs diff --git a/csharp/ql/test/library-tests/dataflow/global/options b/csharp/ql/test/library-tests/dataflow/global/options index 8b0f1661e630..96b0b028bdd2 100644 --- a/csharp/ql/test/library-tests/dataflow/global/options +++ b/csharp/ql/test/library-tests/dataflow/global/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj -semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs \ No newline at end of file +semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-020/options b/csharp/ql/test/query-tests/Security Features/CWE-020/options index 0ce0c6870b7c..96b0b028bdd2 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-020/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-020/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-022/TaintedPath/options b/csharp/ql/test/query-tests/Security Features/CWE-022/TaintedPath/options index daca5d73f552..9290f65d5b22 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-022/TaintedPath/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-022/TaintedPath/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/options b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/options index ebbb04324897..c5b4a9586554 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-079/StoredXSS/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/System.Data.SqlClient/4.9.0/System.Data.SqlClient.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-090/options b/csharp/ql/test/query-tests/Security Features/CWE-090/options index ba17ecb5638c..20a0480c8e2f 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-090/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-090/options @@ -1,5 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/System.Data.SqlClient/4.9.0/System.Data.SqlClient.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs semmle-extractor-options: ${testdir}/../../../resources/stubs/System.DirectoryServices.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-091/XMLInjection/options b/csharp/ql/test/query-tests/Security Features/CWE-091/XMLInjection/options index daca5d73f552..9290f65d5b22 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-091/XMLInjection/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-091/XMLInjection/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-094/options b/csharp/ql/test/query-tests/Security Features/CWE-094/options index ce5d6db635af..cce2f114af69 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-094/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-094/options @@ -1,6 +1,5 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Windows.cs semmle-extractor-options: ${testdir}/../../../resources/stubs/Microsoft.CSharp.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-099/options b/csharp/ql/test/query-tests/Security Features/CWE-099/options index 595b1a2bac00..7404a7573b27 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-099/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-099/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/System.Data.SqlClient/4.9.0/System.Data.SqlClient.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-112/options b/csharp/ql/test/query-tests/Security Features/CWE-112/options index 0ce0c6870b7c..96b0b028bdd2 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-112/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-112/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-114/AssemblyPathInjection/options b/csharp/ql/test/query-tests/Security Features/CWE-114/AssemblyPathInjection/options index daca5d73f552..9290f65d5b22 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-114/AssemblyPathInjection/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-114/AssemblyPathInjection/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-117/options b/csharp/ql/test/query-tests/Security Features/CWE-117/options index cffffd064100..5dfd0afb374f 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-117/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-117/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj semmle-extractor-options: --load-sources-from-project:../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-134/options b/csharp/ql/test/query-tests/Security Features/CWE-134/options index aff430e13cc9..ab08ee323e2b 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-134/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-134/options @@ -1,5 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Windows.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-201/ExposureInTransmittedData/options b/csharp/ql/test/query-tests/Security Features/CWE-201/ExposureInTransmittedData/options index ebbb04324897..c5b4a9586554 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-201/ExposureInTransmittedData/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-201/ExposureInTransmittedData/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/System.Data.SqlClient/4.9.0/System.Data.SqlClient.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-209/options b/csharp/ql/test/query-tests/Security Features/CWE-209/options index 0ce0c6870b7c..96b0b028bdd2 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-209/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-209/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOff/options b/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOff/options index dbb615bf06c0..9d05f9bf06d4 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOff/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOff/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOffButGlobal/options b/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOffButGlobal/options index dbb615bf06c0..9d05f9bf06d4 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOffButGlobal/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-248/MissingASPNETGlobalErrorHandler/WebConfigOffButGlobal/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-285/MissingAccessControl/WebFormsTests/options b/csharp/ql/test/query-tests/Security Features/CWE-285/MissingAccessControl/WebFormsTests/options index d43edf41c562..9d05f9bf06d4 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-285/MissingAccessControl/WebFormsTests/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-285/MissingAccessControl/WebFormsTests/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj -semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs \ No newline at end of file +semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-312/options b/csharp/ql/test/query-tests/Security Features/CWE-312/options index aff430e13cc9..ab08ee323e2b 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-312/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-312/options @@ -1,5 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Windows.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-352/global/options b/csharp/ql/test/query-tests/Security Features/CWE-352/global/options index daca5d73f552..9290f65d5b22 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-352/global/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-352/global/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-352/missing/options b/csharp/ql/test/query-tests/Security Features/CWE-352/missing/options index daca5d73f552..9290f65d5b22 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-352/missing/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-352/missing/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-359/options b/csharp/ql/test/query-tests/Security Features/CWE-359/options index aff430e13cc9..ab08ee323e2b 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-359/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-359/options @@ -1,5 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Windows.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-384/options b/csharp/ql/test/query-tests/Security Features/CWE-384/options index 0ce0c6870b7c..96b0b028bdd2 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-384/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-384/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/CodeAddedHeader/options b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/CodeAddedHeader/options index dbb615bf06c0..9d05f9bf06d4 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/CodeAddedHeader/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/CodeAddedHeader/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/NoHeader/options b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/NoHeader/options index dbb615bf06c0..9d05f9bf06d4 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/NoHeader/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/NoHeader/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeader/options b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeader/options index dbb615bf06c0..9d05f9bf06d4 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeader/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeader/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/options b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/options index daca5d73f552..9290f65d5b22 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/options b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/options index daca5d73f552..9290f65d5b22 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/options b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/options index 62b643d45cbf..750b4e671894 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/Newtonsoft.Json/13.0.3/Newtonsoft.Json.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-539/PersistentCookie/options b/csharp/ql/test/query-tests/Security Features/CWE-539/PersistentCookie/options index daca5d73f552..9290f65d5b22 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-539/PersistentCookie/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-539/PersistentCookie/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/options b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/options index daca5d73f552..7553ab79ad31 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-601/UrlRedirect/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-614/RequireSSL/AddedInCode/options b/csharp/ql/test/query-tests/Security Features/CWE-614/RequireSSL/AddedInCode/options index dbb615bf06c0..9d05f9bf06d4 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-614/RequireSSL/AddedInCode/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-614/RequireSSL/AddedInCode/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-639/WebFormsTests/options b/csharp/ql/test/query-tests/Security Features/CWE-639/WebFormsTests/options index 1fcc7e1cf48f..9290f65d5b22 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-639/WebFormsTests/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-639/WebFormsTests/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj -semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs \ No newline at end of file +semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-643/options b/csharp/ql/test/query-tests/Security Features/CWE-643/options index 595b1a2bac00..7404a7573b27 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-643/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-643/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/System.Data.SqlClient/4.9.0/System.Data.SqlClient.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoS/options b/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoS/options index daca5d73f552..9290f65d5b22 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoS/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoS/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoSGlobalTimeout/options b/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoSGlobalTimeout/options index daca5d73f552..9290f65d5b22 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoSGlobalTimeout/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-730/ReDoSGlobalTimeout/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/options b/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/options index daca5d73f552..9290f65d5b22 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-807/options b/csharp/ql/test/query-tests/Security Features/CWE-807/options index 0ce0c6870b7c..96b0b028bdd2 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-807/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-807/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-838/options b/csharp/ql/test/query-tests/Security Features/CWE-838/options index 0af895004012..5e2b8b8284e2 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-838/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-838/options @@ -1,5 +1,4 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/System.Data.SqlClient/4.9.0/System.Data.SqlClient.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs ${testdir}/../../../resources/stubs/System.Windows.cs diff --git a/csharp/ql/test/query-tests/Telemetry/SupportedExternalApis/options b/csharp/ql/test/query-tests/Telemetry/SupportedExternalApis/options index 0ce0c6870b7c..96b0b028bdd2 100644 --- a/csharp/ql/test/query-tests/Telemetry/SupportedExternalApis/options +++ b/csharp/ql/test/query-tests/Telemetry/SupportedExternalApis/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Telemetry/SupportedExternalSinks/options b/csharp/ql/test/query-tests/Telemetry/SupportedExternalSinks/options index 0ce0c6870b7c..96b0b028bdd2 100644 --- a/csharp/ql/test/query-tests/Telemetry/SupportedExternalSinks/options +++ b/csharp/ql/test/query-tests/Telemetry/SupportedExternalSinks/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/utils/modelgenerator/dataflow/options b/csharp/ql/test/utils/modelgenerator/dataflow/options index 8b0f1661e630..96b0b028bdd2 100644 --- a/csharp/ql/test/utils/modelgenerator/dataflow/options +++ b/csharp/ql/test/utils/modelgenerator/dataflow/options @@ -1,4 +1,3 @@ semmle-extractor-options: /nostdlib /noconfig semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj -semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs \ No newline at end of file +semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs From 82cf472f8aea8a21363587f1dbad897fc3c903ee Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 12 May 2025 09:11:51 +0200 Subject: [PATCH 304/336] C#: Fix ASP tests. --- csharp/ql/test/library-tests/asp/basic/Test.cs | 2 +- csharp/ql/test/library-tests/asp/basic/options | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 csharp/ql/test/library-tests/asp/basic/options diff --git a/csharp/ql/test/library-tests/asp/basic/Test.cs b/csharp/ql/test/library-tests/asp/basic/Test.cs index 607e4d6d0e23..64185aa2c155 100644 --- a/csharp/ql/test/library-tests/asp/basic/Test.cs +++ b/csharp/ql/test/library-tests/asp/basic/Test.cs @@ -1,5 +1,5 @@ // semmle-extractor-options: /nostdlib /noconfig -// semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +// semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj // semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs using System; diff --git a/csharp/ql/test/library-tests/asp/basic/options b/csharp/ql/test/library-tests/asp/basic/options deleted file mode 100644 index 8b0f1661e630..000000000000 --- a/csharp/ql/test/library-tests/asp/basic/options +++ /dev/null @@ -1,4 +0,0 @@ -semmle-extractor-options: /nostdlib /noconfig -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj -semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs \ No newline at end of file From 60d26e522e15156a8144fb0739b8fdd145aea6a3 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 12 May 2025 11:09:34 +0200 Subject: [PATCH 305/336] C#: Cleanup test options files. --- csharp/ql/test/library-tests/asp/basic/Test.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/test/library-tests/asp/basic/Test.cs b/csharp/ql/test/library-tests/asp/basic/Test.cs index 64185aa2c155..607e4d6d0e23 100644 --- a/csharp/ql/test/library-tests/asp/basic/Test.cs +++ b/csharp/ql/test/library-tests/asp/basic/Test.cs @@ -1,5 +1,5 @@ // semmle-extractor-options: /nostdlib /noconfig -// semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj +// semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj // semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs using System; From 05dc9b6d34d9c4b46e42ee21ecbe26b930e1549c Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 12 May 2025 10:20:12 +0200 Subject: [PATCH 306/336] C#: Remove dependency to ASP.NET in the System.Web.cs stub file. --- .../query-tests/Security Features/CWE-611/options | 6 ++---- csharp/ql/test/resources/stubs/System.Web.Http.cs | 14 ++++++++++++++ csharp/ql/test/resources/stubs/System.Web.cs | 15 --------------- 3 files changed, 16 insertions(+), 19 deletions(-) create mode 100644 csharp/ql/test/resources/stubs/System.Web.Http.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-611/options b/csharp/ql/test/query-tests/Security Features/CWE-611/options index 8b0f1661e630..ea31b8476dd2 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-611/options +++ b/csharp/ql/test/query-tests/Security Features/CWE-611/options @@ -1,4 +1,2 @@ -semmle-extractor-options: /nostdlib /noconfig -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj -semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj -semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs \ No newline at end of file +semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs +semmle-extractor-options: /r:System.Collections.Specialized.dll /r:System.Xml.ReaderWriter.dll /r:System.Private.Xml.dll /r:System.Runtime.Extensions.dll diff --git a/csharp/ql/test/resources/stubs/System.Web.Http.cs b/csharp/ql/test/resources/stubs/System.Web.Http.cs new file mode 100644 index 000000000000..7cb6d36c74d4 --- /dev/null +++ b/csharp/ql/test/resources/stubs/System.Web.Http.cs @@ -0,0 +1,14 @@ +namespace System.Web.Http +{ + public class ApiController + { + public Microsoft.AspNetCore.Http.HttpContext Context => null; + public virtual Microsoft.AspNetCore.Mvc.RedirectResult Redirect(Uri location) => null; + public virtual Microsoft.AspNetCore.Mvc.RedirectResult Redirect(string location) => null; + public virtual ResponseMessageResult ResponseMessage(System.Net.Http.HttpResponseMessage response) => null; + public virtual Microsoft.AspNetCore.Mvc.RedirectToRouteResult RedirectToRoute(string routeName, object routeValues) => null; + public Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; set; } + } + + public class ResponseMessageResult { } +} diff --git a/csharp/ql/test/resources/stubs/System.Web.cs b/csharp/ql/test/resources/stubs/System.Web.cs index 56f51208e540..f0572742f883 100644 --- a/csharp/ql/test/resources/stubs/System.Web.cs +++ b/csharp/ql/test/resources/stubs/System.Web.cs @@ -60,21 +60,6 @@ public class HttpApplication : IHttpHandler } } -namespace System.Web.Http -{ - public class ApiController - { - public Microsoft.AspNetCore.Http.HttpContext Context => null; - public virtual Microsoft.AspNetCore.Mvc.RedirectResult Redirect(Uri location) => null; - public virtual Microsoft.AspNetCore.Mvc.RedirectResult Redirect(string location) => null; - public virtual ResponseMessageResult ResponseMessage(System.Net.Http.HttpResponseMessage response) => null; - public virtual Microsoft.AspNetCore.Mvc.RedirectToRouteResult RedirectToRoute(string routeName, object routeValues) => null; - public Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; set; } - } - - public class ResponseMessageResult { } -} - namespace System.Web.Mvc { public class Controller From 5faaa4f0f36c7c38dda30587b16c6d5959ea935e Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 12 May 2025 11:09:34 +0200 Subject: [PATCH 307/336] C#: Cleanup test options files. From 14bdc1ab22e9f0997325bbed4ca641e6819d5945 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Tue, 13 May 2025 09:31:50 +0200 Subject: [PATCH 308/336] Shared: Minor tweaks to model generator script Co-authored-by: Michael Nebel --- misc/scripts/models-as-data/generate_mad.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc/scripts/models-as-data/generate_mad.py b/misc/scripts/models-as-data/generate_mad.py index 60674ed54eda..a5f8ffc8fa05 100755 --- a/misc/scripts/models-as-data/generate_mad.py +++ b/misc/scripts/models-as-data/generate_mad.py @@ -75,7 +75,7 @@ def setenvironment(self, database, folder): @staticmethod def make(): - '''Create a generator instance based on command line arguments.''' + # Create a generator instance based on command line arguments. if any(s == "--help" for s in sys.argv): printHelp() sys.exit(0) @@ -85,7 +85,7 @@ def make(): sys.argv.remove("--language") sys.argv.remove(language) else: - print("Error: Language not specified. Use --language .") + printHelp() sys.exit(0) generator = Generator(language=language) From 014e7dc4bc693ec5c0bc38851c001a69f98c9e20 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Tue, 13 May 2025 09:50:07 +0200 Subject: [PATCH 309/336] Shared: Remove change note for internal MaD generator --- .../src/change-notes/2025-05-02-mad-generator-renamed.md | 8 -------- .../src/change-notes/2025-05-02-mad-generator-renamed.md | 8 -------- 2 files changed, 16 deletions(-) delete mode 100644 csharp/ql/src/change-notes/2025-05-02-mad-generator-renamed.md delete mode 100644 java/ql/src/change-notes/2025-05-02-mad-generator-renamed.md diff --git a/csharp/ql/src/change-notes/2025-05-02-mad-generator-renamed.md b/csharp/ql/src/change-notes/2025-05-02-mad-generator-renamed.md deleted file mode 100644 index 824b37180a18..000000000000 --- a/csharp/ql/src/change-notes/2025-05-02-mad-generator-renamed.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -category: minorAnalysis ---- -* Changes to the MaD model generation infrastructure: - * The `csharp/ql/src/utils/modelgenerator/GenerateFlowModel.py` script has - been removed. The `/misc/scripts/models-as-data/generate_mad.py` script now - supports being called directly and should be used instead. The script - requires a `--language` argument but otherwise functions identically. diff --git a/java/ql/src/change-notes/2025-05-02-mad-generator-renamed.md b/java/ql/src/change-notes/2025-05-02-mad-generator-renamed.md deleted file mode 100644 index 0a2d9e797fc5..000000000000 --- a/java/ql/src/change-notes/2025-05-02-mad-generator-renamed.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -category: minorAnalysis ---- -* Changes to the MaD model generation infrastructure: - * The `java/ql/src/utils/modelgenerator/GenerateFlowModel.py` script has - been removed. The `/misc/scripts/models-as-data/generate_mad.py` script now - supports being called directly and should be used instead. The script - requires a `--language` argument but otherwise functions identically. From b3dc7a21b38f3fc408492329c652e7b502feeb98 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 13 May 2025 09:06:25 +0100 Subject: [PATCH 310/336] Apply suggestions from code review Co-authored-by: Simon Friis Vindum --- rust/ql/lib/codeql/rust/elements/LogicalOperation.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll index 72cc4ffdf57e..eaf1ff06b7d5 100644 --- a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll +++ b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll @@ -18,14 +18,14 @@ abstract private class BinaryLogicalOperationImpl extends BinaryExpr, LogicalOpe final class BinaryLogicalOperation = BinaryLogicalOperationImpl; /** - * The logical and operation, `&&`. + * The logical "and" operation, `&&`. */ final class LogicalAndExpr extends BinaryLogicalOperationImpl, BinaryExpr { LogicalAndExpr() { this.getOperatorName() = "&&" } } /** - * The logical or operation, `||`. + * The logical "or" operation, `||`. */ final class LogicalOrExpr extends BinaryLogicalOperationImpl { LogicalOrExpr() { this.getOperatorName() = "||" } @@ -39,7 +39,7 @@ abstract private class UnaryLogicalOperationImpl extends PrefixExpr, LogicalOper final class UnaryLogicalOperation = UnaryLogicalOperationImpl; /** - * A logical not operation, `!`. + * A logical "not" operation, `!`. */ final class LogicalNotExpr extends UnaryLogicalOperationImpl { LogicalNotExpr() { this.getOperatorName() = "!" } From 510df38da2476708271777dc17ad5bd52068f14c Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 12 May 2025 19:46:50 +0100 Subject: [PATCH 311/336] C++: Add an 'hasIncompleteSsa' predicate to check whether a function has correctly modelled SSA information. --- .../cpp/ir/implementation/aliased_ssa/IRFunction.qll | 8 ++++++++ .../aliased_ssa/internal/SSAConstruction.qll | 12 ++++++++++++ .../code/cpp/ir/implementation/raw/IRFunction.qll | 8 ++++++++ .../implementation/raw/internal/IRConstruction.qll | 2 ++ .../ir/implementation/unaliased_ssa/IRFunction.qll | 8 ++++++++ .../unaliased_ssa/internal/SSAConstruction.qll | 12 ++++++++++++ 6 files changed, 50 insertions(+) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRFunction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRFunction.qll index 354ba41e3d1b..7fa08f57a006 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRFunction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRFunction.qll @@ -58,4 +58,12 @@ class IRFunction extends IRFunctionBase { * Gets all blocks in this function. */ final IRBlock getABlock() { result.getEnclosingIRFunction() = this } + + /** + * Holds if this function may have incomplete def-use information. + * + * Def-use information may be omitted for a function when it is too expensive + * to compute. + */ + final predicate hasIncompleteSsa() { Construction::hasIncompleteSsa(this) } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll index e0a6594e7400..d7df2d40abee 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll @@ -1319,6 +1319,18 @@ predicate canReuseSsaForMemoryResult(Instruction instruction) { // We don't support reusing SSA for any location that could create a `Chi` instruction. } +/** + * Holds if the def-use information for `f` may have been omitted because it + * was too expensive to compute. This happens if one of the memory allocations + * in `f` is a busy definition (i.e., it has many different overlapping uses). + */ +predicate hasIncompleteSsa(IRFunction f) { + exists(Alias::MemoryLocation0 defLocation | + Alias::isBusyDef(defLocation) and + defLocation.getIRFunction() = f + ) +} + /** * Expose some of the internal predicates to PrintSSA.qll. We do this by publicly importing those modules in the * `DebugSsa` module, which is then imported by PrintSSA. diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRFunction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRFunction.qll index 354ba41e3d1b..7fa08f57a006 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRFunction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRFunction.qll @@ -58,4 +58,12 @@ class IRFunction extends IRFunctionBase { * Gets all blocks in this function. */ final IRBlock getABlock() { result.getEnclosingIRFunction() = this } + + /** + * Holds if this function may have incomplete def-use information. + * + * Def-use information may be omitted for a function when it is too expensive + * to compute. + */ + final predicate hasIncompleteSsa() { Construction::hasIncompleteSsa(this) } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll index 5e2461ba8b7c..594e37b668d6 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll @@ -220,6 +220,8 @@ Instruction getMemoryOperandDefinition( none() } +predicate hasIncompleteSsa(IRFunction f) { none() } + /** * Holds if the operand totally overlaps with its definition and consumes the * bit range `[startBitOffset, endBitOffset)`. diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRFunction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRFunction.qll index 354ba41e3d1b..7fa08f57a006 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRFunction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRFunction.qll @@ -58,4 +58,12 @@ class IRFunction extends IRFunctionBase { * Gets all blocks in this function. */ final IRBlock getABlock() { result.getEnclosingIRFunction() = this } + + /** + * Holds if this function may have incomplete def-use information. + * + * Def-use information may be omitted for a function when it is too expensive + * to compute. + */ + final predicate hasIncompleteSsa() { Construction::hasIncompleteSsa(this) } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index e0a6594e7400..d7df2d40abee 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -1319,6 +1319,18 @@ predicate canReuseSsaForMemoryResult(Instruction instruction) { // We don't support reusing SSA for any location that could create a `Chi` instruction. } +/** + * Holds if the def-use information for `f` may have been omitted because it + * was too expensive to compute. This happens if one of the memory allocations + * in `f` is a busy definition (i.e., it has many different overlapping uses). + */ +predicate hasIncompleteSsa(IRFunction f) { + exists(Alias::MemoryLocation0 defLocation | + Alias::isBusyDef(defLocation) and + defLocation.getIRFunction() = f + ) +} + /** * Expose some of the internal predicates to PrintSSA.qll. We do this by publicly importing those modules in the * `DebugSsa` module, which is then imported by PrintSSA. From 9d2eb3d9b83bba10b6f8c690513c8f0f8fe197a8 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 12 May 2025 19:47:47 +0100 Subject: [PATCH 312/336] C++: Filter out instructions with incomplete SSA in range analysis. --- .../new/internal/semantic/SemanticExprSpecific.qll | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExprSpecific.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExprSpecific.qll index 1b36ae2efc5e..1b83ae959d2c 100644 --- a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExprSpecific.qll +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExprSpecific.qll @@ -112,7 +112,14 @@ module SemanticExprConfig { } /** Holds if no range analysis should be performed on the phi edges in `f`. */ - private predicate excludeFunction(Cpp::Function f) { count(f.getEntryPoint()) > 1 } + private predicate excludeFunction(Cpp::Function f) { + count(f.getEntryPoint()) > 1 + or + exists(IR::IRFunction irFunction | + irFunction.getFunction() = f and + irFunction.hasIncompleteSsa() + ) + } SemType getUnknownExprType(Expr expr) { result = getSemanticType(expr.getResultIRType()) } From c3c18bdbd288a39fba09dcacda44d6cb4a8ced2a Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 13 May 2025 11:28:25 +0100 Subject: [PATCH 313/336] C++: Add change note. --- .../change-notes/2025-05-13-range-analysis-infinite-loop.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cpp/ql/lib/change-notes/2025-05-13-range-analysis-infinite-loop.md diff --git a/cpp/ql/lib/change-notes/2025-05-13-range-analysis-infinite-loop.md b/cpp/ql/lib/change-notes/2025-05-13-range-analysis-infinite-loop.md new file mode 100644 index 000000000000..7452e024d53f --- /dev/null +++ b/cpp/ql/lib/change-notes/2025-05-13-range-analysis-infinite-loop.md @@ -0,0 +1,4 @@ +--- +category: fix +--- +* Fixed an infinite loop in `semmle.code.cpp.rangeanalysis.new.RangeAnalysis` when computing ranges in very large and complex function bodies. \ No newline at end of file From 7494eac35c4050563903d4426c10844fc28e7919 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 13 May 2025 12:47:49 +0200 Subject: [PATCH 314/336] Address review comments --- .../elements/internal/LiteralExprImpl.qll | 39 +++++----- .../extractor-tests/literal/literal.expected | 73 ++++++++++--------- .../test/extractor-tests/literal/literal.rs | 3 + 3 files changed, 58 insertions(+), 57 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll index c424ff5471da..2a2a754e8899 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll @@ -53,10 +53,7 @@ module Impl { * [1]: https://doc.rust-lang.org/reference/tokens.html#character-literals */ class CharLiteralExpr extends LiteralExpr { - CharLiteralExpr() { - // todo: proper implementation - this.getTextValue().regexpMatch("'.*'") - } + CharLiteralExpr() { this.getTextValue().regexpMatch("'.*'") } override string getAPrimaryQlClass() { result = "CharLiteralExpr" } } @@ -71,10 +68,7 @@ module Impl { * [1]: https://doc.rust-lang.org/reference/tokens.html#string-literals */ class StringLiteralExpr extends LiteralExpr { - StringLiteralExpr() { - // todo: proper implementation - this.getTextValue().regexpMatch("r?#*\".*\"#*") - } + StringLiteralExpr() { this.getTextValue().regexpMatch("r?#*\".*\"#*") } override string getAPrimaryQlClass() { result = "StringLiteralExpr" } } @@ -138,11 +132,10 @@ module Impl { * For example, `42u8` has the suffix `u8`. */ string getSuffix() { - exists(string s, string reg, int last | + exists(string s, string reg | s = this.getTextValue() and reg = IntegerLiteralRegexs::integerLiteral() and - last = strictcount(reg.indexOf("(")) and - result = s.regexpCapture(reg, last) + result = s.regexpCapture(reg, 13) ) } @@ -193,9 +186,8 @@ module Impl { class FloatLiteralExpr extends NumberLiteralExpr { FloatLiteralExpr() { this.getTextValue() - .regexpMatch([ - FloatLiteralRegexs::floatLiteral(), FloatLiteralRegexs::integerSuffixLiteral() - ]) and + .regexpMatch(IntegerLiteralRegexs::paren(FloatLiteralRegexs::floatLiteral()) + "|" + + IntegerLiteralRegexs::paren(FloatLiteralRegexs::integerSuffixLiteral())) and // E.g. `0x01_f32` is an integer, not a float not this instanceof IntegerLiteralExpr } @@ -206,15 +198,18 @@ module Impl { * For example, `42.0f32` has the suffix `f32`. */ string getSuffix() { - exists(string s, string reg, int last | + exists(string s, string reg, int group | + reg = FloatLiteralRegexs::floatLiteralSuffix1() and + group = 3 + or + reg = FloatLiteralRegexs::floatLiteralSuffix2() and + group = 9 + or + reg = FloatLiteralRegexs::integerSuffixLiteral() and + group = 13 + | s = this.getTextValue() and - reg = - [ - FloatLiteralRegexs::floatLiteralSuffix1(), FloatLiteralRegexs::floatLiteralSuffix2(), - FloatLiteralRegexs::integerSuffixLiteral() - ] and - last = strictcount(reg.indexOf("(")) and - result = s.regexpCapture(reg, last) + result = s.regexpCapture(reg, group) ) } diff --git a/rust/ql/test/extractor-tests/literal/literal.expected b/rust/ql/test/extractor-tests/literal/literal.expected index 55d1ac11013c..d229d9684671 100644 --- a/rust/ql/test/extractor-tests/literal/literal.expected +++ b/rust/ql/test/extractor-tests/literal/literal.expected @@ -1,42 +1,45 @@ charLiteral | literal.rs:2:5:2:7 | 'a' | | literal.rs:3:5:3:7 | 'b' | +| literal.rs:4:5:4:8 | '\\'' | +| literal.rs:5:5:5:8 | '\\n' | +| literal.rs:6:5:6:15 | '\\u{1F600}' | stringLiteral -| literal.rs:8:5:8:9 | "foo" | -| literal.rs:9:5:9:10 | r"foo" | -| literal.rs:10:5:10:13 | "\\"foo\\"" | -| literal.rs:11:5:11:14 | r#""foo""# | -| literal.rs:13:5:13:18 | "foo #\\"# bar" | -| literal.rs:14:5:14:22 | r##"foo #"# bar"## | -| literal.rs:16:5:16:10 | "\\x52" | -| literal.rs:17:5:17:7 | "R" | -| literal.rs:18:5:18:8 | r"R" | -| literal.rs:19:5:19:11 | "\\\\x52" | -| literal.rs:20:5:20:11 | r"\\x52" | +| literal.rs:11:5:11:9 | "foo" | +| literal.rs:12:5:12:10 | r"foo" | +| literal.rs:13:5:13:13 | "\\"foo\\"" | +| literal.rs:14:5:14:14 | r#""foo""# | +| literal.rs:16:5:16:18 | "foo #\\"# bar" | +| literal.rs:17:5:17:22 | r##"foo #"# bar"## | +| literal.rs:19:5:19:10 | "\\x52" | +| literal.rs:20:5:20:7 | "R" | +| literal.rs:21:5:21:8 | r"R" | +| literal.rs:22:5:22:11 | "\\\\x52" | +| literal.rs:23:5:23:11 | r"\\x52" | integerLiteral -| literal.rs:25:5:25:7 | 123 | | -| literal.rs:26:5:26:10 | 123i32 | i32 | -| literal.rs:27:5:27:10 | 123u32 | u32 | -| literal.rs:28:5:28:11 | 123_u32 | u32 | -| literal.rs:30:5:30:8 | 0xff | | -| literal.rs:31:5:31:11 | 0xff_u8 | u8 | -| literal.rs:32:5:32:12 | 0x01_f32 | | -| literal.rs:33:5:33:11 | 0x01_e3 | | -| literal.rs:35:5:35:8 | 0o70 | | -| literal.rs:36:5:36:12 | 0o70_i16 | i16 | -| literal.rs:38:5:38:25 | 0b1111_1111_1001_0000 | | -| literal.rs:39:5:39:28 | 0b1111_1111_1001_0000i64 | i64 | -| literal.rs:40:5:40:15 | 0b________1 | | -| literal.rs:42:5:42:10 | 0usize | usize | -| literal.rs:45:5:46:10 | 128_i8 | i8 | -| literal.rs:47:5:48:10 | 256_u8 | u8 | +| literal.rs:28:5:28:7 | 123 | | +| literal.rs:29:5:29:10 | 123i32 | i32 | +| literal.rs:30:5:30:10 | 123u32 | u32 | +| literal.rs:31:5:31:11 | 123_u32 | u32 | +| literal.rs:33:5:33:8 | 0xff | | +| literal.rs:34:5:34:11 | 0xff_u8 | u8 | +| literal.rs:35:5:35:12 | 0x01_f32 | | +| literal.rs:36:5:36:11 | 0x01_e3 | | +| literal.rs:38:5:38:8 | 0o70 | | +| literal.rs:39:5:39:12 | 0o70_i16 | i16 | +| literal.rs:41:5:41:25 | 0b1111_1111_1001_0000 | | +| literal.rs:42:5:42:28 | 0b1111_1111_1001_0000i64 | i64 | +| literal.rs:43:5:43:15 | 0b________1 | | +| literal.rs:45:5:45:10 | 0usize | usize | +| literal.rs:48:5:49:10 | 128_i8 | i8 | +| literal.rs:50:5:51:10 | 256_u8 | u8 | floatLiteral -| literal.rs:53:5:53:8 | 5f32 | f32 | -| literal.rs:55:5:55:12 | 123.0f64 | f64 | -| literal.rs:56:5:56:10 | 0.1f64 | f64 | -| literal.rs:57:5:57:10 | 0.1f32 | f32 | -| literal.rs:58:5:58:14 | 12E+99_f64 | f64 | -| literal.rs:59:18:59:19 | 2. | | +| literal.rs:56:5:56:8 | 5f32 | f32 | +| literal.rs:58:5:58:12 | 123.0f64 | f64 | +| literal.rs:59:5:59:10 | 0.1f64 | f64 | +| literal.rs:60:5:60:10 | 0.1f32 | f32 | +| literal.rs:61:5:61:14 | 12E+99_f64 | f64 | +| literal.rs:62:18:62:19 | 2. | | booleanLiteral -| literal.rs:63:5:63:8 | true | -| literal.rs:64:5:64:9 | false | +| literal.rs:66:5:66:8 | true | +| literal.rs:67:5:67:9 | false | diff --git a/rust/ql/test/extractor-tests/literal/literal.rs b/rust/ql/test/extractor-tests/literal/literal.rs index 74503f2a24e4..ea4ccdece630 100644 --- a/rust/ql/test/extractor-tests/literal/literal.rs +++ b/rust/ql/test/extractor-tests/literal/literal.rs @@ -1,6 +1,9 @@ fn char_literals() { 'a'; 'b'; + '\''; + '\n'; + '\u{1F600}'; } fn string_literals() { From 0836f0b413126532825744034cf5e46a80604da6 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 13 May 2025 13:41:15 +0100 Subject: [PATCH 315/336] C++: Cache and fix join order in 'hasIncompleteSsa'. --- .../aliased_ssa/internal/SSAConstruction.qll | 26 ++++++++++--------- .../internal/SSAConstruction.qll | 26 ++++++++++--------- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll index d7df2d40abee..1a1eb6a1876f 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll @@ -731,6 +731,20 @@ private module Cached { or instruction = getChi(result.(UninitializedGroupInstruction)) } + + /** + * Holds if the def-use information for `f` may have been omitted because it + * was too expensive to compute. This happens if one of the memory allocations + * in `f` is a busy definition (i.e., it has many different overlapping uses). + */ + pragma[nomagic] + cached + predicate hasIncompleteSsa(IRFunction f) { + exists(Alias::MemoryLocation0 defLocation | + Alias::isBusyDef(pragma[only_bind_into](defLocation)) and + defLocation.getIRFunction() = f + ) + } } private Instruction getNewInstruction(OldInstruction instr) { getOldInstruction(result) = instr } @@ -1319,18 +1333,6 @@ predicate canReuseSsaForMemoryResult(Instruction instruction) { // We don't support reusing SSA for any location that could create a `Chi` instruction. } -/** - * Holds if the def-use information for `f` may have been omitted because it - * was too expensive to compute. This happens if one of the memory allocations - * in `f` is a busy definition (i.e., it has many different overlapping uses). - */ -predicate hasIncompleteSsa(IRFunction f) { - exists(Alias::MemoryLocation0 defLocation | - Alias::isBusyDef(defLocation) and - defLocation.getIRFunction() = f - ) -} - /** * Expose some of the internal predicates to PrintSSA.qll. We do this by publicly importing those modules in the * `DebugSsa` module, which is then imported by PrintSSA. diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index d7df2d40abee..1a1eb6a1876f 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -731,6 +731,20 @@ private module Cached { or instruction = getChi(result.(UninitializedGroupInstruction)) } + + /** + * Holds if the def-use information for `f` may have been omitted because it + * was too expensive to compute. This happens if one of the memory allocations + * in `f` is a busy definition (i.e., it has many different overlapping uses). + */ + pragma[nomagic] + cached + predicate hasIncompleteSsa(IRFunction f) { + exists(Alias::MemoryLocation0 defLocation | + Alias::isBusyDef(pragma[only_bind_into](defLocation)) and + defLocation.getIRFunction() = f + ) + } } private Instruction getNewInstruction(OldInstruction instr) { getOldInstruction(result) = instr } @@ -1319,18 +1333,6 @@ predicate canReuseSsaForMemoryResult(Instruction instruction) { // We don't support reusing SSA for any location that could create a `Chi` instruction. } -/** - * Holds if the def-use information for `f` may have been omitted because it - * was too expensive to compute. This happens if one of the memory allocations - * in `f` is a busy definition (i.e., it has many different overlapping uses). - */ -predicate hasIncompleteSsa(IRFunction f) { - exists(Alias::MemoryLocation0 defLocation | - Alias::isBusyDef(defLocation) and - defLocation.getIRFunction() = f - ) -} - /** * Expose some of the internal predicates to PrintSSA.qll. We do this by publicly importing those modules in the * `DebugSsa` module, which is then imported by PrintSSA. From ae54c62001603dd9e4ec3e85d92251877e11c552 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 13 May 2025 15:06:43 +0200 Subject: [PATCH 316/336] Simplify using non-capturing groups --- .../elements/internal/LiteralExprImpl.qll | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll index 2a2a754e8899..f848663a99bb 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll @@ -81,28 +81,28 @@ module Impl { // https://doc.rust-lang.org/reference/tokens.html#integer-literals private module IntegerLiteralRegexs { bindingset[s] - string paren(string s) { result = "(" + s + ")" } + string paren(string s) { result = "(?:" + s + ")" } string integerLiteral() { result = paren(paren(decLiteral()) + "|" + paren(binLiteral()) + "|" + paren(octLiteral()) + "|" + - paren(hexLiteral())) + paren(suffix()) + "?" + paren(hexLiteral())) + "(" + suffix() + ")?" } private string suffix() { result = "u8|i8|u16|i16|u32|i32|u64|i64|u128|i128|usize|isize" } - string decLiteral() { result = decDigit() + "(" + decDigit() + "|_)*" } + string decLiteral() { result = decDigit() + "(?:" + decDigit() + "|_)*" } string binLiteral() { - result = "0b(" + binDigit() + "|_)*" + binDigit() + "(" + binDigit() + "|_)*" + result = "0b(?:" + binDigit() + "|_)*" + binDigit() + "(?:" + binDigit() + "|_)*" } string octLiteral() { - result = "0o(" + octDigit() + "|_)*" + octDigit() + "(" + octDigit() + "|_)*" + result = "0o(?:" + octDigit() + "|_)*" + octDigit() + "(?:" + octDigit() + "|_)*" } string hexLiteral() { - result = "0x(" + hexDigit() + "|_)*" + hexDigit() + "(" + hexDigit() + "|_)*" + result = "0x(?:" + hexDigit() + "|_)*" + hexDigit() + "(?:" + hexDigit() + "|_)*" } string decDigit() { result = "[0-9]" } @@ -135,7 +135,7 @@ module Impl { exists(string s, string reg | s = this.getTextValue() and reg = IntegerLiteralRegexs::integerLiteral() and - result = s.regexpCapture(reg, 13) + result = s.regexpCapture(reg, 1) ) } @@ -153,24 +153,25 @@ module Impl { } string floatLiteralSuffix1() { - result = decLiteral() + "\\." + decLiteral() + paren(suffix()) + "?" + result = decLiteral() + "\\." + decLiteral() + "(" + suffix() + ")?" } string floatLiteralSuffix2() { result = - decLiteral() + paren("\\." + decLiteral()) + "?" + paren(exponent()) + paren(suffix()) + "?" + decLiteral() + paren("\\." + decLiteral()) + "?" + paren(exponent()) + "(" + suffix() + ")?" } string integerSuffixLiteral() { result = paren(paren(decLiteral()) + "|" + paren(binLiteral()) + "|" + paren(octLiteral()) + "|" + - paren(hexLiteral())) + paren(suffix()) + paren(hexLiteral())) + "(" + suffix() + ")" } private string suffix() { result = "f32|f64" } string exponent() { - result = "(e|E)(\\+|-)?(" + decDigit() + "|_)*" + decDigit() + "(" + decDigit() + "|_)*" + result = + "(?:e|E)(?:\\+|-)?(?:" + decDigit() + "|_)*" + decDigit() + "(?:" + decDigit() + "|_)*" } } @@ -198,18 +199,13 @@ module Impl { * For example, `42.0f32` has the suffix `f32`. */ string getSuffix() { - exists(string s, string reg, int group | - reg = FloatLiteralRegexs::floatLiteralSuffix1() and - group = 3 - or - reg = FloatLiteralRegexs::floatLiteralSuffix2() and - group = 9 - or - reg = FloatLiteralRegexs::integerSuffixLiteral() and - group = 13 - | + exists(string s, string reg | + reg = + IntegerLiteralRegexs::paren(FloatLiteralRegexs::floatLiteralSuffix1()) + "|" + + IntegerLiteralRegexs::paren(FloatLiteralRegexs::floatLiteralSuffix2()) + "|" + + IntegerLiteralRegexs::paren(FloatLiteralRegexs::integerSuffixLiteral()) and s = this.getTextValue() and - result = s.regexpCapture(reg, group) + result = s.regexpCapture(reg, [1, 2, 3]) ) } From f255fc2fd593dcd08e21062829384688690b297c Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 13 May 2025 14:21:28 +0100 Subject: [PATCH 317/336] C++: Drive-by join order fix. Before: ``` Evaluated relational algebra for predicate SsaInternals::getDefImpl/1#1ed4f567@65628fbv with tuple counts: 4935102 ~5% {4} r1 = SCAN `SsaInternals::SsaImpl::Definition.definesAt/3#dispred#7eea4c8f` OUTPUT In.2, In.3, In.0, In.1 104274503 ~1% {3} | JOIN WITH `SsaInternals::DefImpl.hasIndexInBlock/2#dispred#30a6c29f_120#join_rhs` ON FIRST 2 OUTPUT Rhs.2, Lhs.3, Lhs.2 4921319 ~2% {2} | JOIN WITH `SsaInternals::DefImpl.getSourceVariable/0#dispred#72437659` ON FIRST 2 OUTPUT Lhs.2, Lhs.0 return r1 ``` After: ``` Evaluated relational algebra for predicate SsaInternals::SsaImpl::Definition.definesAt/3#dispred#7eea4c8f_1230#join_rhs@b280fb5h with tuple counts: 4935102 ~3% {4} r1 = SCAN `SsaInternals::SsaImpl::Definition.definesAt/3#dispred#7eea4c8f` OUTPUT In.1, In.2, In.3, In.0 return r1 Evaluated relational algebra for predicate SsaInternals::DefImpl.hasIndexInBlock/3#dispred#31d295aa_1230#join_rhs@2be655s4 with tuple counts: 5634706 ~1% {4} r1 = SCAN `SsaInternals::DefImpl.hasIndexInBlock/3#dispred#31d295aa` OUTPUT In.1, In.2, In.3, In.0 return r1 Evaluated relational algebra for predicate SsaInternals::getDefImpl/1#1ed4f567@8afa36uu with tuple counts: 4921319 ~2% {2} r1 = JOIN `SsaInternals::SsaImpl::Definition.definesAt/3#dispred#7eea4c8f_1230#join_rhs` WITH `SsaInternals::DefImpl.hasIndexInBlock/3#dispred#31d295aa_1230#join_rhs` ON FIRST 3 OUTPUT Lhs.3, Rhs.3 return r1 ``` --- .../code/cpp/ir/dataflow/internal/DataFlowPrivate.qll | 4 ++-- .../code/cpp/ir/dataflow/internal/SsaInternals.qll | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 39975d8883c4..e517a75edf97 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -1567,7 +1567,7 @@ private int countNumberOfBranchesUsingParameter(SwitchInstruction switch, Parame | exists(Ssa::UseImpl use | use.hasIndexInBlock(useblock, _, sv)) or - exists(Ssa::DefImpl def | def.hasIndexInBlock(useblock, _, sv)) + exists(Ssa::DefImpl def | def.hasIndexInBlock(sv, useblock, _)) ) ) ) @@ -1814,7 +1814,7 @@ module IteratorFlow { */ private predicate isIteratorWrite(Instruction write, Operand address) { exists(Ssa::DefImpl writeDef, IRBlock bb, int i | - writeDef.hasIndexInBlock(bb, i, _) and + writeDef.hasIndexInBlock(_, bb, i) and bb.getInstruction(i) = write and address = writeDef.getAddressOperand() ) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll index 51829f13df51..bea6b68d5119 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll @@ -191,7 +191,7 @@ abstract class DefImpl extends TDefImpl { * Holds if this definition (or use) has index `index` in block `block`, * and is a definition (or use) of the variable `sv` */ - final predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) { + final predicate hasIndexInBlock(SourceVariable sv, IRBlock block, int index) { this.hasIndexInBlock(block, index) and sv = this.getSourceVariable() } @@ -891,12 +891,12 @@ private module SsaInput implements SsaImplCommon::InputSig { predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) { DataFlowImplCommon::forceCachingInSameStage() and ( - exists(DefImpl def | def.hasIndexInBlock(bb, i, v) | + exists(DefImpl def | def.hasIndexInBlock(v, bb, i) | if def.isCertain() then certain = true else certain = false ) or exists(GlobalDefImpl global | - global.hasIndexInBlock(bb, i, v) and + global.hasIndexInBlock(v, bb, i) and certain = true ) ) @@ -934,10 +934,11 @@ module SsaCached { } /** Gets the `DefImpl` corresponding to `def`. */ +pragma[nomagic] private DefImpl getDefImpl(SsaImpl::Definition def) { exists(SourceVariable sv, IRBlock bb, int i | def.definesAt(sv, bb, i) and - result.hasIndexInBlock(bb, i, sv) + result.hasIndexInBlock(sv, bb, i) ) } From 08aad903462040ae251b715dad6f2c187d9d0c59 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 25 Apr 2025 14:55:15 +0100 Subject: [PATCH 318/336] Add 2.2.0-Beta1 deps --- java/kotlin-extractor/deps/kotlin-compiler-2.2.0-Beta1.jar | 3 +++ .../deps/kotlin-compiler-embeddable-2.2.0-Beta1.jar | 3 +++ java/kotlin-extractor/deps/kotlin-stdlib-2.2.0-Beta1.jar | 3 +++ 3 files changed, 9 insertions(+) create mode 100644 java/kotlin-extractor/deps/kotlin-compiler-2.2.0-Beta1.jar create mode 100644 java/kotlin-extractor/deps/kotlin-compiler-embeddable-2.2.0-Beta1.jar create mode 100644 java/kotlin-extractor/deps/kotlin-stdlib-2.2.0-Beta1.jar diff --git a/java/kotlin-extractor/deps/kotlin-compiler-2.2.0-Beta1.jar b/java/kotlin-extractor/deps/kotlin-compiler-2.2.0-Beta1.jar new file mode 100644 index 000000000000..616f8fa27016 --- /dev/null +++ b/java/kotlin-extractor/deps/kotlin-compiler-2.2.0-Beta1.jar @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5cabb8d9f7621865fb0300773bd0cb6dcd91412d0026342c6aacdf23bdb7cf0b +size 57574890 diff --git a/java/kotlin-extractor/deps/kotlin-compiler-embeddable-2.2.0-Beta1.jar b/java/kotlin-extractor/deps/kotlin-compiler-embeddable-2.2.0-Beta1.jar new file mode 100644 index 000000000000..65c3079c09cd --- /dev/null +++ b/java/kotlin-extractor/deps/kotlin-compiler-embeddable-2.2.0-Beta1.jar @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:046daac99684ac0fbe3f8c9780651192fb23061a27b72f1e948c25d160d7b147 +size 56134176 diff --git a/java/kotlin-extractor/deps/kotlin-stdlib-2.2.0-Beta1.jar b/java/kotlin-extractor/deps/kotlin-stdlib-2.2.0-Beta1.jar new file mode 100644 index 000000000000..bd02764d8d83 --- /dev/null +++ b/java/kotlin-extractor/deps/kotlin-stdlib-2.2.0-Beta1.jar @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51aefa2b8d09b2d32cd65056a0f1485556447c764574115981474fa9716a124a +size 1730638 From abea647bb1a6b984ef0c586ec26fda92e6b12274 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Fri, 25 Apr 2025 17:18:09 +0200 Subject: [PATCH 319/336] Bazel: update `rules_kotlin` to 2.1.3 --- MODULE.bazel | 2 +- .../rules_kotlin/2.1.3-codeql.1/MODULE.bazel | 35 +++++++++++++++++++ .../codeql_add_language_version_option.patch | 32 +++++++++++++++++ .../patches/codeql_do_not_emit_jdeps.patch | 16 +++++++++ .../rules_kotlin/2.1.3-codeql.1/source.json | 9 +++++ .../modules/rules_kotlin/metadata.json | 1 + 6 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/MODULE.bazel create mode 100644 misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_add_language_version_option.patch create mode 100644 misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_do_not_emit_jdeps.patch create mode 100644 misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/source.json diff --git a/MODULE.bazel b/MODULE.bazel index ae00bca4390d..7e8e36b53092 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -24,7 +24,7 @@ bazel_dep(name = "bazel_skylib", version = "1.7.1") bazel_dep(name = "abseil-cpp", version = "20240116.1", repo_name = "absl") bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json") bazel_dep(name = "fmt", version = "10.0.0") -bazel_dep(name = "rules_kotlin", version = "2.0.0-codeql.1") +bazel_dep(name = "rules_kotlin", version = "2.1.3-codeql.1") bazel_dep(name = "gazelle", version = "0.40.0") bazel_dep(name = "rules_dotnet", version = "0.17.4") bazel_dep(name = "googletest", version = "1.14.0.bcr.1") diff --git a/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/MODULE.bazel b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/MODULE.bazel new file mode 100644 index 000000000000..41bef52cf9f6 --- /dev/null +++ b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/MODULE.bazel @@ -0,0 +1,35 @@ +module( + name = "rules_kotlin", + version = "2.1.3-codeql.1", + compatibility_level = 1, + repo_name = "rules_kotlin", +) + +bazel_dep(name = "platforms", version = "0.0.11") +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "rules_java", version = "7.2.0") +bazel_dep(name = "rules_python", version = "0.23.1") +bazel_dep(name = "rules_cc", version = "0.0.8") +bazel_dep(name = "rules_android", version = "0.1.1") + +rules_kotlin_extensions = use_extension( + "//src/main/starlark/core/repositories:bzlmod_setup.bzl", + "rules_kotlin_extensions", +) +use_repo( + rules_kotlin_extensions, + "com_github_google_ksp", + "com_github_jetbrains_kotlin", + "com_github_pinterest_ktlint", + "kotlinx_serialization_core_jvm", + "kotlinx_serialization_json", + "kotlinx_serialization_json_jvm", +) + +register_toolchains("//kotlin/internal:default_toolchain") + +# TODO(bencodes) We should be able to remove this once rules_android has rolled out official Bzlmod support +remote_android_extensions = use_extension("@bazel_tools//tools/android:android_extensions.bzl", "remote_android_tools_extensions") +use_repo(remote_android_extensions, "android_gmaven_r8", "android_tools") + +bazel_dep(name = "rules_proto", version = "5.3.0-21.7") diff --git a/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_add_language_version_option.patch b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_add_language_version_option.patch new file mode 100644 index 000000000000..b0bf85d4faef --- /dev/null +++ b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_add_language_version_option.patch @@ -0,0 +1,32 @@ +diff --git a/src/main/starlark/core/options/opts.kotlinc.bzl b/src/main/starlark/core/options/opts.kotlinc.bzl +index 76df826..ef2d6ca 100644 +--- a/src/main/starlark/core/options/opts.kotlinc.bzl ++++ b/src/main/starlark/core/options/opts.kotlinc.bzl +@@ -33,6 +33,11 @@ def _map_jdk_release_to_flag(version): + return None + return ["-Xjdk-release=%s" % version] + ++def _map_language_version_to_flag(version): ++ if not version: ++ return None ++ return ["-language-version=%s" % version, "-api-version=%s" % version] ++ + _KOPTS_ALL = { + "warn": struct( + args = dict( +@@ -429,6 +434,15 @@ _KOPTS_ALL = { + value_to_flag = None, + map_value_to_flag = _map_jdk_release_to_flag, + ), ++ "language_version": struct( ++ args = dict( ++ default = "1.9", ++ doc = "-language-version", ++ ), ++ type = attr.string, ++ value_to_flag = None, ++ map_value_to_flag = _map_language_version_to_flag, ++ ), + } + + def _merge(key, rule_defined): diff --git a/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_do_not_emit_jdeps.patch b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_do_not_emit_jdeps.patch new file mode 100644 index 000000000000..380c837d06a4 --- /dev/null +++ b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/patches/codeql_do_not_emit_jdeps.patch @@ -0,0 +1,16 @@ +Emitting jdeps is broken for the 2.0.0 kotlin extractor, and we don't need those files. +Patching it here rather than passing `--@rules_kotlin//kotlin/settings:jvm_emit_jdeps=false` +allows us to not have to specify that option (and therefore pull in `rules_kotlin`) in `semmle-code`. +diff --git a/kotlin/settings/BUILD.bazel b/kotlin/settings/BUILD.bazel +index 2c93c11..f352b80 100644 +--- a/kotlin/settings/BUILD.bazel ++++ b/kotlin/settings/BUILD.bazel +@@ -25,7 +25,7 @@ release_archive( + # Flag that controls the emission of jdeps files during kotlin jvm compilation. + bool_flag( + name = "jvm_emit_jdeps", +- build_setting_default = True, # Upstream default behavior ++ build_setting_default = False, + visibility = ["//visibility:public"], + ) + diff --git a/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/source.json b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/source.json new file mode 100644 index 000000000000..8abac8eb4bd1 --- /dev/null +++ b/misc/bazel/registry/modules/rules_kotlin/2.1.3-codeql.1/source.json @@ -0,0 +1,9 @@ +{ + "integrity": "sha256-4USKVrJGJAeyaI3qht9cN1s2oJkb1HjC3dlMlxaBJeI=", + "url": "https://github.com/bazelbuild/rules_kotlin/releases/download/v2.1.3/rules_kotlin-v2.1.3.tar.gz", + "patches": { + "codeql_do_not_emit_jdeps.patch": "sha256-1ir4Aio1SICxnj1wafQ0GefT/m7bwn2n+SQwq19V3A8=", + "codeql_add_language_version_option.patch": "sha256-F7RthnrO6kJlCNcQ76L1Utqll2OwyeFZ/HmT82NwgB4=" + }, + "patch_strip": 1 +} diff --git a/misc/bazel/registry/modules/rules_kotlin/metadata.json b/misc/bazel/registry/modules/rules_kotlin/metadata.json index ac259b2e729a..3e11b7df8202 100644 --- a/misc/bazel/registry/modules/rules_kotlin/metadata.json +++ b/misc/bazel/registry/modules/rules_kotlin/metadata.json @@ -21,6 +21,7 @@ "github:bazelbuild/rules_kotlin" ], "versions": [ + "2.1.3-codeql.1", "2.0.0-codeql.1" ], "yanked_versions": {} From 163a403065d31132b7fe5a0b5ad46e75c826b1da Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 25 Apr 2025 16:35:14 +0100 Subject: [PATCH 320/336] Add Kotlin 2.2.0-Beta1; drop Kotlin 1.5 --- MODULE.bazel | 15 +++------------ java/kotlin-extractor/versions.bzl | 5 +---- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 7e8e36b53092..49ea49975bb9 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -193,10 +193,6 @@ use_repo( kotlin_extractor_deps, "codeql_kotlin_defaults", "codeql_kotlin_embeddable", - "kotlin-compiler-1.5.0", - "kotlin-compiler-1.5.10", - "kotlin-compiler-1.5.20", - "kotlin-compiler-1.5.30", "kotlin-compiler-1.6.0", "kotlin-compiler-1.6.20", "kotlin-compiler-1.7.0", @@ -208,10 +204,7 @@ use_repo( "kotlin-compiler-2.0.20-Beta2", "kotlin-compiler-2.1.0-Beta1", "kotlin-compiler-2.1.20-Beta1", - "kotlin-compiler-embeddable-1.5.0", - "kotlin-compiler-embeddable-1.5.10", - "kotlin-compiler-embeddable-1.5.20", - "kotlin-compiler-embeddable-1.5.30", + "kotlin-compiler-2.2.0-Beta1", "kotlin-compiler-embeddable-1.6.0", "kotlin-compiler-embeddable-1.6.20", "kotlin-compiler-embeddable-1.7.0", @@ -223,10 +216,7 @@ use_repo( "kotlin-compiler-embeddable-2.0.20-Beta2", "kotlin-compiler-embeddable-2.1.0-Beta1", "kotlin-compiler-embeddable-2.1.20-Beta1", - "kotlin-stdlib-1.5.0", - "kotlin-stdlib-1.5.10", - "kotlin-stdlib-1.5.20", - "kotlin-stdlib-1.5.30", + "kotlin-compiler-embeddable-2.2.0-Beta1", "kotlin-stdlib-1.6.0", "kotlin-stdlib-1.6.20", "kotlin-stdlib-1.7.0", @@ -238,6 +228,7 @@ use_repo( "kotlin-stdlib-2.0.20-Beta2", "kotlin-stdlib-2.1.0-Beta1", "kotlin-stdlib-2.1.20-Beta1", + "kotlin-stdlib-2.2.0-Beta1", ) go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk") diff --git a/java/kotlin-extractor/versions.bzl b/java/kotlin-extractor/versions.bzl index c48f98ae363e..e389bfd9514d 100644 --- a/java/kotlin-extractor/versions.bzl +++ b/java/kotlin-extractor/versions.bzl @@ -1,9 +1,5 @@ # when updating this list, `bazel mod tidy` should be run from `codeql` to update `MODULE.bazel` VERSIONS = [ - "1.5.0", - "1.5.10", - "1.5.20", - "1.5.30", "1.6.0", "1.6.20", "1.7.0", @@ -15,6 +11,7 @@ VERSIONS = [ "2.0.20-Beta2", "2.1.0-Beta1", "2.1.20-Beta1", + "2.2.0-Beta1", ] def _version_to_tuple(v): From 24feb5166153a7209d5e0d756c7e1826f27cafe6 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 28 Apr 2025 14:21:52 +0100 Subject: [PATCH 321/336] Fix Gradle config --- java/kotlin-extractor/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/kotlin-extractor/build.gradle b/java/kotlin-extractor/build.gradle index 57229642a927..eebdf150eb7a 100644 --- a/java/kotlin-extractor/build.gradle +++ b/java/kotlin-extractor/build.gradle @@ -55,7 +55,7 @@ sourceSets { } jar { - archiveName = "${OUTPUT_JAR_NAME}" + archiveBaseName = "${OUTPUT_JAR_NAME}" } task getHomeDir { From a36fc30d442195830a3b2da4d4a4ac271dabf32d Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 28 Apr 2025 14:23:19 +0100 Subject: [PATCH 322/336] Fix build for Kotlin 2.2.0 --- .../src/main/kotlin/KotlinFileExtractor.kt | 16 ++-------------- .../src/main/kotlin/KotlinUsesExtractor.kt | 2 +- .../src/main/kotlin/comments/CommentExtractor.kt | 8 +++++++- .../src/main/kotlin/utils/IrVisitorLookup.kt | 4 ++-- .../utils/versions/v_1_5_0/IrLazyFunction.kt | 3 +++ .../kotlin/utils/versions/v_1_5_0/IrVisitor.kt | 4 ++++ .../utils/versions/v_1_5_0/getJvmDefaultMode.kt | 7 +++++++ .../utils/versions/v_1_5_0/isDispatchReceiver.kt | 6 ++++++ .../v_1_5_0/parameterIndexExcludingReceivers.kt | 5 +++++ .../v_1_9_0-Beta/CommentExtractorLighterAST.kt | 3 +-- .../versions/v_2_2_0-Beta1/IrLazyFunction.kt | 3 +++ .../utils/versions/v_2_2_0-Beta1/IrVisitor.kt | 4 ++++ ...tParameterDeclarationWithWrappedDescriptor.kt | 7 +++++++ .../versions/v_2_2_0-Beta1/getJvmDefaultMode.kt | 7 +++++++ .../versions/v_2_2_0-Beta1/isDispatchReceiver.kt | 6 ++++++ .../parameterIndexExcludingReceivers.kt | 10 ++++++++++ 16 files changed, 75 insertions(+), 20 deletions(-) create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/IrLazyFunction.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/IrVisitor.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/getJvmDefaultMode.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/isDispatchReceiver.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/parameterIndexExcludingReceivers.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/IrLazyFunction.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/IrVisitor.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/createImplicitParameterDeclarationWithWrappedDescriptor.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/getJvmDefaultMode.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/isDispatchReceiver.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/parameterIndexExcludingReceivers.kt diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index f1f4131002b4..ab3d3f69e91c 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -21,7 +21,6 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget import org.jetbrains.kotlin.ir.builders.declarations.* import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* @@ -1619,9 +1618,7 @@ open class KotlinFileExtractor( // (NB. kotlinc's actual implementation strategy is different -- it makes an inner class // called InterfaceWithDefault$DefaultImpls and stores the default methods // there to allow default method usage in Java < 8, but this is hopefully niche. - !jvmDefaultModeEnabledIsEnabled( - pluginContext.languageVersionSettings - .getFlag(JvmAnalysisFlags.jvmDefaultMode)) && + !jvmDefaultModeEnabledIsEnabled(getJvmDefaultMode(pluginContext.languageVersionSettings)) && f.parentClassOrNull.let { it != null && it.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && @@ -6011,11 +6008,7 @@ open class KotlinFileExtractor( is IrGetValue -> { val exprParent = parent.expr(e, callable) val owner = e.symbol.owner - if ( - owner is IrValueParameter && - owner.index == -1 && - !owner.isExtensionReceiver() - ) { + if (owner is IrValueParameter && isDispatchReceiver(owner)) { extractThisAccess(e, owner.parent, exprParent, callable) } else { val isAnnotationClassParameter = @@ -6966,11 +6959,6 @@ open class KotlinFileExtractor( } } - private fun IrValueParameter.isExtensionReceiver(): Boolean { - val parentFun = parent as? IrFunction ?: return false - return parentFun.extensionReceiverParameter == this - } - private open inner class GeneratedClassHelper( protected val locId: Label, protected val ids: GeneratedClassLabels diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt index a401d017a028..56deb81da012 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt @@ -2136,7 +2136,7 @@ open class KotlinUsesExtractor( } val parentId = parent ?: overriddenParentAttributes?.id ?: useDeclarationParentOf(vp, false) - val idxBase = overriddenParentAttributes?.valueParameters?.indexOf(vp) ?: vp.index + val idxBase = overriddenParentAttributes?.valueParameters?.indexOf(vp) ?: parameterIndexExcludingReceivers(vp) val idxOffset = if ( declarationParent is IrFunction && diff --git a/java/kotlin-extractor/src/main/kotlin/comments/CommentExtractor.kt b/java/kotlin-extractor/src/main/kotlin/comments/CommentExtractor.kt index 0c6308acd996..322cffc87f32 100644 --- a/java/kotlin-extractor/src/main/kotlin/comments/CommentExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/comments/CommentExtractor.kt @@ -2,12 +2,18 @@ package com.github.codeql.comments import com.github.codeql.* import com.github.codeql.utils.isLocalFunction +import com.github.codeql.utils.versions.isDispatchReceiver import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrBody import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.util.parentClassOrNull +private fun IrValueParameter.isExtensionReceiver(): Boolean { + val parentFun = parent as? IrFunction ?: return false + return parentFun.extensionReceiverParameter == this +} + open class CommentExtractor( protected val fileExtractor: KotlinFileExtractor, protected val file: IrFile, @@ -19,7 +25,7 @@ open class CommentExtractor( protected fun getLabel(element: IrElement): Label? { if (element == file) return fileLabel - if (element is IrValueParameter && element.index == -1) { + if (element is IrValueParameter && (isDispatchReceiver(element) || element.isExtensionReceiver())) { // Don't attribute comments to the implicit `this` parameter of a function. return null } diff --git a/java/kotlin-extractor/src/main/kotlin/utils/IrVisitorLookup.kt b/java/kotlin-extractor/src/main/kotlin/utils/IrVisitorLookup.kt index 2ac55ee7edec..fff09c0da28b 100644 --- a/java/kotlin-extractor/src/main/kotlin/utils/IrVisitorLookup.kt +++ b/java/kotlin-extractor/src/main/kotlin/utils/IrVisitorLookup.kt @@ -1,17 +1,17 @@ package com.github.codeql.utils +import com.github.codeql.utils.versions.IrVisitor import com.intellij.psi.PsiElement import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.util.isFakeOverride -import org.jetbrains.kotlin.ir.visitors.IrElementVisitor class IrVisitorLookup( private val psi2Ir: Psi2IrFacade, private val psi: PsiElement, private val file: IrFile -) : IrElementVisitor> { +) : IrVisitor>() { private val location = psi.getLocation() override fun visitElement(element: IrElement, data: MutableCollection): Unit { diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/IrLazyFunction.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/IrLazyFunction.kt new file mode 100644 index 000000000000..e74d4f0426a2 --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/IrLazyFunction.kt @@ -0,0 +1,3 @@ +package com.github.codeql.utils.versions + +typealias IrLazyFunction = org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction \ No newline at end of file diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/IrVisitor.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/IrVisitor.kt new file mode 100644 index 000000000000..4c5b074c4809 --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/IrVisitor.kt @@ -0,0 +1,4 @@ +package com.github.codeql.utils.versions + +abstract class IrVisitor : org.jetbrains.kotlin.ir.visitors.IrElementVisitor +abstract class IrVisitorVoid : org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid \ No newline at end of file diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/getJvmDefaultMode.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/getJvmDefaultMode.kt new file mode 100644 index 000000000000..e42c7c9c8167 --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/getJvmDefaultMode.kt @@ -0,0 +1,7 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.config.JvmAnalysisFlags +import org.jetbrains.kotlin.config.LanguageVersionSettings + +fun getJvmDefaultMode(lvs: LanguageVersionSettings) = + lvs.getFlag(JvmAnalysisFlags.jvmDefaultMode) diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/isDispatchReceiver.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/isDispatchReceiver.kt new file mode 100644 index 000000000000..2aeac8aafe7e --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/isDispatchReceiver.kt @@ -0,0 +1,6 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrValueParameter + +fun isDispatchReceiver(p: IrValueParameter) = p.index == -1 && p != (p.parent as? IrFunction)?.extensionReceiverParameter \ No newline at end of file diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/parameterIndexExcludingReceivers.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/parameterIndexExcludingReceivers.kt new file mode 100644 index 000000000000..cfcad9ec69ac --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/parameterIndexExcludingReceivers.kt @@ -0,0 +1,5 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.ir.declarations.IrValueParameter + +fun parameterIndexExcludingReceivers(vp: IrValueParameter) = vp.index diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_9_0-Beta/CommentExtractorLighterAST.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_9_0-Beta/CommentExtractorLighterAST.kt index ecaa5e232873..af9276d43ca8 100644 --- a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_9_0-Beta/CommentExtractorLighterAST.kt +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_9_0-Beta/CommentExtractorLighterAST.kt @@ -9,7 +9,6 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET -import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.kdoc.lexer.KDocTokens @@ -43,7 +42,7 @@ class CommentExtractorLighterAST( val kDocOwners = mutableMapOf>() val visitor = - object : IrElementVisitorVoid { + object : IrVisitorVoid() { override fun visitElement(element: IrElement) { val metadata = (element as? IrMetadataSourceOwner)?.metadata val sourceElement = (metadata as? FirMetadataSource)?.fir?.source diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/IrLazyFunction.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/IrLazyFunction.kt new file mode 100644 index 000000000000..6a445959f1ea --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/IrLazyFunction.kt @@ -0,0 +1,3 @@ +package com.github.codeql.utils.versions + +typealias IrLazyFunction = org.jetbrains.kotlin.psi2ir.lazy.IrLazyFunction \ No newline at end of file diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/IrVisitor.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/IrVisitor.kt new file mode 100644 index 000000000000..45c5948d8fe3 --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/IrVisitor.kt @@ -0,0 +1,4 @@ +package com.github.codeql.utils.versions + +typealias IrVisitor = org.jetbrains.kotlin.ir.visitors.IrVisitor +typealias IrVisitorVoid = org.jetbrains.kotlin.ir.visitors.IrVisitorVoid \ No newline at end of file diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/createImplicitParameterDeclarationWithWrappedDescriptor.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/createImplicitParameterDeclarationWithWrappedDescriptor.kt new file mode 100644 index 000000000000..d6ebeb42c512 --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/createImplicitParameterDeclarationWithWrappedDescriptor.kt @@ -0,0 +1,7 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.util.createThisReceiverParameter + +fun IrClass.createImplicitParameterDeclarationWithWrappedDescriptor() = + this.createThisReceiverParameter() diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/getJvmDefaultMode.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/getJvmDefaultMode.kt new file mode 100644 index 000000000000..06a5de34de24 --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/getJvmDefaultMode.kt @@ -0,0 +1,7 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.config.jvmDefaultMode + +fun getJvmDefaultMode(lvs: LanguageVersionSettings) = + lvs.jvmDefaultMode diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/isDispatchReceiver.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/isDispatchReceiver.kt new file mode 100644 index 000000000000..49323e54d929 --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/isDispatchReceiver.kt @@ -0,0 +1,6 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.declarations.IrParameterKind + +fun isDispatchReceiver(p: IrValueParameter) = p.kind == IrParameterKind.DispatchReceiver \ No newline at end of file diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/parameterIndexExcludingReceivers.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/parameterIndexExcludingReceivers.kt new file mode 100644 index 000000000000..c50e4dadaf50 --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/parameterIndexExcludingReceivers.kt @@ -0,0 +1,10 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrValueParameter + +fun parameterIndexExcludingReceivers(vp: IrValueParameter): Int { + val offset = + (vp.parent as? IrFunction)?.let { (if (it.extensionReceiverParameter != null) 1 else 0) + (if (it.dispatchReceiverParameter != null) 1 else 0) } ?: 0 + return vp.indexInParameters - offset +} From 4cb1e7840f8c48539134a5e6e6ef28098d8cc557 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 28 Apr 2025 14:32:05 +0100 Subject: [PATCH 323/336] Update Kotlin doc table --- docs/codeql/reusables/supported-versions-compilers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/reusables/supported-versions-compilers.rst b/docs/codeql/reusables/supported-versions-compilers.rst index bb2d4a7416a9..7e17d0cd97f1 100644 --- a/docs/codeql/reusables/supported-versions-compilers.rst +++ b/docs/codeql/reusables/supported-versions-compilers.rst @@ -21,7 +21,7 @@ Java,"Java 7 to 24 [6]_","javac (OpenJDK and Oracle JDK), Eclipse compiler for Java (ECJ) [7]_",``.java`` - Kotlin,"Kotlin 1.5.0 to 2.1.2\ *x*","kotlinc",``.kt`` + Kotlin,"Kotlin 1.6.0 to 2.2.0\ *x*","kotlinc",``.kt`` JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [8]_" Python [9]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13",Not applicable,``.py`` Ruby [10]_,"up to 3.3",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``" From 2ad5e20e799b2684bc22ceb00cd818d7f99b487b Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 28 Apr 2025 14:34:38 +0100 Subject: [PATCH 324/336] Change note --- java/ql/lib/change-notes/2025-04-28-kotlin-220.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 java/ql/lib/change-notes/2025-04-28-kotlin-220.md diff --git a/java/ql/lib/change-notes/2025-04-28-kotlin-220.md b/java/ql/lib/change-notes/2025-04-28-kotlin-220.md new file mode 100644 index 000000000000..c0c257a2f076 --- /dev/null +++ b/java/ql/lib/change-notes/2025-04-28-kotlin-220.md @@ -0,0 +1,4 @@ +--- +category: feature +--- +* 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). From 3f23212d4e36989fc1a00c981665e28e7dde2fa1 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 28 Apr 2025 14:35:05 +0100 Subject: [PATCH 325/336] Update test expectation --- .../diagnostics/kotlin-version-too-new/diagnostics.expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/integration-tests/kotlin/all-platforms/diagnostics/kotlin-version-too-new/diagnostics.expected b/java/ql/integration-tests/kotlin/all-platforms/diagnostics/kotlin-version-too-new/diagnostics.expected index 9a2cbdc1ab08..39e1f6e6b984 100644 --- a/java/ql/integration-tests/kotlin/all-platforms/diagnostics/kotlin-version-too-new/diagnostics.expected +++ b/java/ql/integration-tests/kotlin/all-platforms/diagnostics/kotlin-version-too-new/diagnostics.expected @@ -1,5 +1,5 @@ { - "markdownMessage": "The Kotlin version installed (`999.999.999`) is too recent for this version of CodeQL. Install a version lower than 2.1.30.", + "markdownMessage": "The Kotlin version installed (`999.999.999`) is too recent for this version of CodeQL. Install a version lower than 2.2.10.", "severity": "error", "source": { "extractorName": "java", From 0d21fa51f28a39a93add5a3e4bed3946f5e13a53 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 28 Apr 2025 16:17:07 +0100 Subject: [PATCH 326/336] Change default version --- java/kotlin-extractor/dev/wrapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/kotlin-extractor/dev/wrapper.py b/java/kotlin-extractor/dev/wrapper.py index f51db2892695..f95a89352fc3 100755 --- a/java/kotlin-extractor/dev/wrapper.py +++ b/java/kotlin-extractor/dev/wrapper.py @@ -27,7 +27,7 @@ import io import os -DEFAULT_VERSION = "2.0.0" +DEFAULT_VERSION = "2.2.0-Beta1" def options(): From 29d369f22fcec0e841f3e22c89224ae24473927a Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 29 Apr 2025 11:22:54 +0100 Subject: [PATCH 327/336] Don't try to decode a class from a .java file --- java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt b/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt index 5a06de67c042..a18dd06247f7 100644 --- a/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt +++ b/java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt @@ -90,7 +90,11 @@ fun getIrClassVirtualFile(irClass: IrClass): VirtualFile? { } } is VirtualFileBasedSourceElement -> { - return cSource.virtualFile + if (cSource.virtualFile.name.endsWith(".class")) { + // At least lately, despite VirtualFileBasedSourceElement being constructed on a BinaryJavaClass, + // this can be a .java source file. + return cSource.virtualFile + } } is KotlinJvmBinarySourceElement -> { val binaryClass = cSource.binaryClass From 34e0a7b23a3b20e2f4b89f980ff91475a374e40e Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 29 Apr 2025 13:51:07 +0100 Subject: [PATCH 328/336] Bump Kotlin version to keep integration test working --- .../kotlin/all-platforms/gradle_groovy_app/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/integration-tests/kotlin/all-platforms/gradle_groovy_app/app/build.gradle b/java/ql/integration-tests/kotlin/all-platforms/gradle_groovy_app/app/build.gradle index 16aad9297b05..8ef1009376c9 100644 --- a/java/ql/integration-tests/kotlin/all-platforms/gradle_groovy_app/app/build.gradle +++ b/java/ql/integration-tests/kotlin/all-platforms/gradle_groovy_app/app/build.gradle @@ -8,7 +8,7 @@ plugins { // Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin. - id 'org.jetbrains.kotlin.jvm' version '1.5.31' + id 'org.jetbrains.kotlin.jvm' version '1.6.0' // Apply the application plugin to add support for building a CLI application in Java. id 'application' From 1afe67ab136ceb817e531a1e0d82557c53c00b69 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 29 Apr 2025 13:51:28 +0100 Subject: [PATCH 329/336] Accept Kotlin 2.1.20 test changes These are mainly small changes in how source-locations are ascribed to synthetic expressions, plus three real changes: - The comment extractor is performing better presumably due to improvements in the underlying representation - *= /= and %= operations are once again extracted correctly; presumably their origin information has been fixed - Reference to a static final Java field can lead to more constant propagation than before The last one might be a minor nuisance to someone trying to find references to such a field. --- .../annotation_classes/classes.expected | 4 +- .../annotations/jvmName/test.expected | 4 +- .../arrays/arrayAccesses.expected | 27 +- .../library-tests/classes/PrintAst.expected | 48 +- .../classes/genericExprTypes.expected | 14 +- .../library-tests/comments/comments.expected | 5 +- .../library-tests/exprs/PrintAst.expected | 776 +++++++++--------- .../library-tests/exprs/binop.expected | 3 - .../exprs/delegatedProperties.expected | 22 +- .../library-tests/exprs/exprs.expected | 330 ++++---- .../library-tests/exprs/funcExprs.expected | 6 +- .../exprs_typeaccess/PrintAst.expected | 3 +- .../generic-instance-methods/test.expected | 20 +- .../test.expected | 8 +- .../internal-public-alias/test.expected | 6 +- .../jvmstatic-annotation/test.expected | 12 +- .../library-tests/methods/exprs.expected | 24 +- .../library-tests/methods/methods.expected | 8 +- .../library-tests/methods/parameters.expected | 4 +- .../modifiers/modifiers.expected | 20 +- .../private-anonymous-types/test.expected | 8 +- .../properties/properties.expected | 32 +- .../reflection/reflection.expected | 18 +- .../variables/variableAccesses.expected | 6 +- .../variables/variables.expected | 4 +- 25 files changed, 699 insertions(+), 713 deletions(-) diff --git a/java/ql/test-kotlin2/library-tests/annotation_classes/classes.expected b/java/ql/test-kotlin2/library-tests/annotation_classes/classes.expected index cf47ffc15bd2..d42e6cf854c2 100644 --- a/java/ql/test-kotlin2/library-tests/annotation_classes/classes.expected +++ b/java/ql/test-kotlin2/library-tests/annotation_classes/classes.expected @@ -32,8 +32,8 @@ annotations | def.kt:41:5:41:12 | Annot0k | def.kt:41:5:42:19 | Z | def.kt:5:1:21:60 | Annot0k | | def.kt:45:1:45:8 | Annot0k | def.kt:45:1:51:1 | fn | def.kt:5:1:21:60 | Annot0k | | def.kt:46:21:46:28 | Annot0k | def.kt:46:21:46:39 | a | def.kt:5:1:21:60 | Annot0k | -| def.kt:54:1:54:12 | Annot0k | def.kt:53:1:57:23 | getP | def.kt:5:1:21:60 | Annot0k | -| def.kt:55:1:55:12 | Annot0k | def.kt:53:1:57:23 | setP | def.kt:5:1:21:60 | Annot0k | +| def.kt:54:1:54:12 | Annot0k | def.kt:53:1:57:19 | getP | def.kt:5:1:21:60 | Annot0k | +| def.kt:55:1:55:12 | Annot0k | def.kt:53:1:57:19 | setP | def.kt:5:1:21:60 | Annot0k | | def.kt:56:1:56:14 | Annot0k | def.kt:53:1:57:23 | p | def.kt:5:1:21:60 | Annot0k | | def.kt:59:5:59:21 | Annot0k | def.kt:59:5:59:28 | | def.kt:5:1:21:60 | Annot0k | | use.java:10:5:10:21 | Annot0j | use.java:14:18:14:18 | Z | Annot0j.java:1:19:1:25 | Annot0j | diff --git a/java/ql/test-kotlin2/library-tests/annotations/jvmName/test.expected b/java/ql/test-kotlin2/library-tests/annotations/jvmName/test.expected index a3313a519ca6..c56618efda8b 100644 --- a/java/ql/test-kotlin2/library-tests/annotations/jvmName/test.expected +++ b/java/ql/test-kotlin2/library-tests/annotations/jvmName/test.expected @@ -1,8 +1,8 @@ | Test.java:2:17:2:17 | m | m | m | | test.kt:3:9:4:18 | getX_prop | getX_prop | getX | | test.kt:6:5:6:19 | getX | getX | getX | -| test.kt:8:5:10:19 | changeY | changeY | setY | -| test.kt:8:5:10:19 | y | y | getY | +| test.kt:8:5:10:14 | changeY | changeY | setY | +| test.kt:8:5:10:14 | y | y | getY | | test.kt:12:5:13:15 | method | method | fn | | test.kt:17:5:17:14 | p | p | p | | test.kt:18:5:18:32 | w | w | q | diff --git a/java/ql/test-kotlin2/library-tests/arrays/arrayAccesses.expected b/java/ql/test-kotlin2/library-tests/arrays/arrayAccesses.expected index 2decb2b876b6..6217a2650e20 100644 --- a/java/ql/test-kotlin2/library-tests/arrays/arrayAccesses.expected +++ b/java/ql/test-kotlin2/library-tests/arrays/arrayAccesses.expected @@ -1,12 +1,21 @@ -| arrayGetsSets.kt:12:11:12:15 | ...[...] | arrayGetsSets.kt:12:3:12:15 | set(...) | int | arrayGetsSets.kt:12:11:12:12 | a1 | arrayGetsSets.kt:12:14:12:14 | 0 | -| arrayGetsSets.kt:13:11:13:15 | ...[...] | arrayGetsSets.kt:13:3:13:15 | set(...) | short | arrayGetsSets.kt:13:11:13:12 | a2 | arrayGetsSets.kt:13:14:13:14 | 0 | -| arrayGetsSets.kt:14:11:14:15 | ...[...] | arrayGetsSets.kt:14:3:14:15 | set(...) | byte | arrayGetsSets.kt:14:11:14:12 | a3 | arrayGetsSets.kt:14:14:14:14 | 0 | -| arrayGetsSets.kt:15:11:15:15 | ...[...] | arrayGetsSets.kt:15:3:15:15 | set(...) | long | arrayGetsSets.kt:15:11:15:12 | a4 | arrayGetsSets.kt:15:14:15:14 | 0 | -| arrayGetsSets.kt:16:11:16:15 | ...[...] | arrayGetsSets.kt:16:3:16:15 | set(...) | float | arrayGetsSets.kt:16:11:16:12 | a5 | arrayGetsSets.kt:16:14:16:14 | 0 | -| arrayGetsSets.kt:17:11:17:15 | ...[...] | arrayGetsSets.kt:17:3:17:15 | set(...) | double | arrayGetsSets.kt:17:11:17:12 | a6 | arrayGetsSets.kt:17:14:17:14 | 0 | -| arrayGetsSets.kt:18:11:18:15 | ...[...] | arrayGetsSets.kt:18:3:18:15 | set(...) | boolean | arrayGetsSets.kt:18:11:18:12 | a7 | arrayGetsSets.kt:18:14:18:14 | 0 | -| arrayGetsSets.kt:19:11:19:15 | ...[...] | arrayGetsSets.kt:19:3:19:15 | set(...) | char | arrayGetsSets.kt:19:11:19:12 | a8 | arrayGetsSets.kt:19:14:19:14 | 0 | -| arrayGetsSets.kt:20:11:20:15 | ...[...] | arrayGetsSets.kt:20:3:20:15 | set(...) | Object | arrayGetsSets.kt:20:11:20:12 | a9 | arrayGetsSets.kt:20:14:20:14 | 0 | +| arrayGetsSets.kt:12:3:12:15 | ...[...] | arrayGetsSets.kt:12:3:12:15 | ...=... | int[] | arrayGetsSets.kt:12:3:12:4 | a1 | arrayGetsSets.kt:12:6:12:6 | 0 | +| arrayGetsSets.kt:12:11:12:15 | ...[...] | arrayGetsSets.kt:12:3:12:15 | ...=... | int | arrayGetsSets.kt:12:11:12:12 | a1 | arrayGetsSets.kt:12:14:12:14 | 0 | +| arrayGetsSets.kt:13:3:13:15 | ...[...] | arrayGetsSets.kt:13:3:13:15 | ...=... | short[] | arrayGetsSets.kt:13:3:13:4 | a2 | arrayGetsSets.kt:13:6:13:6 | 0 | +| arrayGetsSets.kt:13:11:13:15 | ...[...] | arrayGetsSets.kt:13:3:13:15 | ...=... | short | arrayGetsSets.kt:13:11:13:12 | a2 | arrayGetsSets.kt:13:14:13:14 | 0 | +| arrayGetsSets.kt:14:3:14:15 | ...[...] | arrayGetsSets.kt:14:3:14:15 | ...=... | byte[] | arrayGetsSets.kt:14:3:14:4 | a3 | arrayGetsSets.kt:14:6:14:6 | 0 | +| arrayGetsSets.kt:14:11:14:15 | ...[...] | arrayGetsSets.kt:14:3:14:15 | ...=... | byte | arrayGetsSets.kt:14:11:14:12 | a3 | arrayGetsSets.kt:14:14:14:14 | 0 | +| arrayGetsSets.kt:15:3:15:15 | ...[...] | arrayGetsSets.kt:15:3:15:15 | ...=... | long[] | arrayGetsSets.kt:15:3:15:4 | a4 | arrayGetsSets.kt:15:6:15:6 | 0 | +| arrayGetsSets.kt:15:11:15:15 | ...[...] | arrayGetsSets.kt:15:3:15:15 | ...=... | long | arrayGetsSets.kt:15:11:15:12 | a4 | arrayGetsSets.kt:15:14:15:14 | 0 | +| arrayGetsSets.kt:16:3:16:15 | ...[...] | arrayGetsSets.kt:16:3:16:15 | ...=... | float[] | arrayGetsSets.kt:16:3:16:4 | a5 | arrayGetsSets.kt:16:6:16:6 | 0 | +| arrayGetsSets.kt:16:11:16:15 | ...[...] | arrayGetsSets.kt:16:3:16:15 | ...=... | float | arrayGetsSets.kt:16:11:16:12 | a5 | arrayGetsSets.kt:16:14:16:14 | 0 | +| arrayGetsSets.kt:17:3:17:15 | ...[...] | arrayGetsSets.kt:17:3:17:15 | ...=... | double[] | arrayGetsSets.kt:17:3:17:4 | a6 | arrayGetsSets.kt:17:6:17:6 | 0 | +| arrayGetsSets.kt:17:11:17:15 | ...[...] | arrayGetsSets.kt:17:3:17:15 | ...=... | double | arrayGetsSets.kt:17:11:17:12 | a6 | arrayGetsSets.kt:17:14:17:14 | 0 | +| arrayGetsSets.kt:18:3:18:15 | ...[...] | arrayGetsSets.kt:18:3:18:15 | ...=... | boolean[] | arrayGetsSets.kt:18:3:18:4 | a7 | arrayGetsSets.kt:18:6:18:6 | 0 | +| arrayGetsSets.kt:18:11:18:15 | ...[...] | arrayGetsSets.kt:18:3:18:15 | ...=... | boolean | arrayGetsSets.kt:18:11:18:12 | a7 | arrayGetsSets.kt:18:14:18:14 | 0 | +| arrayGetsSets.kt:19:3:19:15 | ...[...] | arrayGetsSets.kt:19:3:19:15 | ...=... | char[] | arrayGetsSets.kt:19:3:19:4 | a8 | arrayGetsSets.kt:19:6:19:6 | 0 | +| arrayGetsSets.kt:19:11:19:15 | ...[...] | arrayGetsSets.kt:19:3:19:15 | ...=... | char | arrayGetsSets.kt:19:11:19:12 | a8 | arrayGetsSets.kt:19:14:19:14 | 0 | +| arrayGetsSets.kt:20:3:20:15 | ...[...] | arrayGetsSets.kt:20:3:20:15 | ...=... | Object[] | arrayGetsSets.kt:20:3:20:4 | a9 | arrayGetsSets.kt:20:6:20:6 | 0 | +| arrayGetsSets.kt:20:11:20:15 | ...[...] | arrayGetsSets.kt:20:3:20:15 | ...=... | Object | arrayGetsSets.kt:20:11:20:12 | a9 | arrayGetsSets.kt:20:14:20:14 | 0 | | arrayGetsSets.kt:32:3:32:12 | ...[...] | arrayGetsSets.kt:32:3:32:12 | ...+=... | int | arrayGetsSets.kt:32:3:32:4 | a1 | arrayGetsSets.kt:32:6:32:6 | 0 | | arrayGetsSets.kt:38:3:38:13 | ...[...] | arrayGetsSets.kt:38:3:38:13 | .../=... | long | arrayGetsSets.kt:38:3:38:4 | a4 | arrayGetsSets.kt:38:6:38:6 | 0 | | arrayGetsSets.kt:39:3:39:13 | ...[...] | arrayGetsSets.kt:39:3:39:13 | ...-=... | float | arrayGetsSets.kt:39:3:39:4 | a5 | arrayGetsSets.kt:39:6:39:6 | 0 | diff --git a/java/ql/test-kotlin2/library-tests/classes/PrintAst.expected b/java/ql/test-kotlin2/library-tests/classes/PrintAst.expected index f98dba8f6cb4..4abfda927996 100644 --- a/java/ql/test-kotlin2/library-tests/classes/PrintAst.expected +++ b/java/ql/test-kotlin2/library-tests/classes/PrintAst.expected @@ -882,20 +882,16 @@ localClassField.kt: # 2| 0: [WhenExpr] when ... # 2| 0: [WhenBranch] ... -> ... # 2| 0: [BooleanLiteral] true -# 2| 1: [ExprStmt] ; -# 2| 0: [ImplicitCoercionToUnitExpr] -# 2| 0: [TypeAccess] Unit -# 2| 1: [StmtExpr] -# 2| 0: [BlockStmt] { ... } -# 3| 0: [LocalTypeDeclStmt] class ... -# 3| 0: [LocalClass] L -# 3| 1: [Constructor] L -# 3| 5: [BlockStmt] { ... } -# 3| 0: [SuperConstructorInvocationStmt] super(...) -# 3| 1: [BlockStmt] { ... } -# 4| 1: [ExprStmt] ; -# 4| 0: [ClassInstanceExpr] new L(...) -# 4| -3: [TypeAccess] L +# 2| 1: [BlockStmt] { ... } +# 3| 0: [LocalTypeDeclStmt] class ... +# 3| 0: [LocalClass] L +# 3| 1: [Constructor] L +# 3| 5: [BlockStmt] { ... } +# 3| 0: [SuperConstructorInvocationStmt] super(...) +# 3| 1: [BlockStmt] { ... } +# 4| 1: [ExprStmt] ; +# 4| 0: [ClassInstanceExpr] new L(...) +# 4| -3: [TypeAccess] L # 5| 1: [WhenBranch] ... -> ... # 5| 0: [BooleanLiteral] true # 5| 1: [BlockStmt] { ... } @@ -910,20 +906,16 @@ localClassField.kt: # 7| 0: [WhenExpr] when ... # 7| 0: [WhenBranch] ... -> ... # 7| 0: [BooleanLiteral] true -# 7| 1: [ExprStmt] ; -# 7| 0: [ImplicitCoercionToUnitExpr] -# 7| 0: [TypeAccess] Unit -# 7| 1: [StmtExpr] -# 7| 0: [BlockStmt] { ... } -# 8| 0: [LocalTypeDeclStmt] class ... -# 8| 0: [LocalClass] L -# 8| 1: [Constructor] L -# 8| 5: [BlockStmt] { ... } -# 8| 0: [SuperConstructorInvocationStmt] super(...) -# 8| 1: [BlockStmt] { ... } -# 9| 1: [ExprStmt] ; -# 9| 0: [ClassInstanceExpr] new L(...) -# 9| -3: [TypeAccess] L +# 7| 1: [BlockStmt] { ... } +# 8| 0: [LocalTypeDeclStmt] class ... +# 8| 0: [LocalClass] L +# 8| 1: [Constructor] L +# 8| 5: [BlockStmt] { ... } +# 8| 0: [SuperConstructorInvocationStmt] super(...) +# 8| 1: [BlockStmt] { ... } +# 9| 1: [ExprStmt] ; +# 9| 0: [ClassInstanceExpr] new L(...) +# 9| -3: [TypeAccess] L # 10| 1: [WhenBranch] ... -> ... # 10| 0: [BooleanLiteral] true # 10| 1: [BlockStmt] { ... } diff --git a/java/ql/test-kotlin2/library-tests/classes/genericExprTypes.expected b/java/ql/test-kotlin2/library-tests/classes/genericExprTypes.expected index a61d001d270c..2f7075c7e8e1 100644 --- a/java/ql/test-kotlin2/library-tests/classes/genericExprTypes.expected +++ b/java/ql/test-kotlin2/library-tests/classes/genericExprTypes.expected @@ -6,23 +6,23 @@ | generic_anonymous.kt:1:26:1:33 | t | T | | generic_anonymous.kt:1:26:1:33 | this | Generic | | generic_anonymous.kt:1:26:1:33 | this.t | T | +| generic_anonymous.kt:3:3:3:15 | T | T | +| generic_anonymous.kt:3:3:3:15 | new Object(...) { ... } | new Object(...) { ... } | +| generic_anonymous.kt:3:3:3:15 | this | Generic | +| generic_anonymous.kt:3:3:3:15 | this.x | new Object(...) { ... } | | generic_anonymous.kt:3:3:5:3 | ...=... | new Object(...) { ... } | | generic_anonymous.kt:3:3:5:3 | T | T | -| generic_anonymous.kt:3:3:5:3 | T | T | -| generic_anonymous.kt:3:3:5:3 | new Object(...) { ... } | new Object(...) { ... } | | generic_anonymous.kt:3:3:5:3 | new Object(...) { ... } | new Object(...) { ... } | -| generic_anonymous.kt:3:3:5:3 | this | Generic | -| generic_anonymous.kt:3:3:5:3 | this.x | new Object(...) { ... } | | generic_anonymous.kt:3:3:5:3 | x | new Object(...) { ... } | | generic_anonymous.kt:3:19:5:3 | | new Object(...) { ... } | | generic_anonymous.kt:3:19:5:3 | Object | Object | | generic_anonymous.kt:3:19:5:3 | new (...) | new Object(...) { ... } | +| generic_anonymous.kt:4:7:4:16 | T | T | +| generic_anonymous.kt:4:7:4:16 | this | new Object(...) { ... } | +| generic_anonymous.kt:4:7:4:16 | this.member | T | | generic_anonymous.kt:4:7:4:20 | ...=... | T | | generic_anonymous.kt:4:7:4:20 | T | T | -| generic_anonymous.kt:4:7:4:20 | T | T | | generic_anonymous.kt:4:7:4:20 | member | T | -| generic_anonymous.kt:4:7:4:20 | this | new Object(...) { ... } | -| generic_anonymous.kt:4:7:4:20 | this.member | T | | generic_anonymous.kt:4:20:4:20 | Generic | Generic | | generic_anonymous.kt:4:20:4:20 | Generic.this | Generic | | generic_anonymous.kt:4:20:4:20 | getT(...) | T | diff --git a/java/ql/test-kotlin2/library-tests/comments/comments.expected b/java/ql/test-kotlin2/library-tests/comments/comments.expected index 5acdeffb4b3a..77a5ce164707 100644 --- a/java/ql/test-kotlin2/library-tests/comments/comments.expected +++ b/java/ql/test-kotlin2/library-tests/comments/comments.expected @@ -18,13 +18,15 @@ comments commentOwners | comments.kt:1:1:1:36 | /** Kdoc owned by CompilationUnit */ | comments.kt:0:0:0:0 | comments | | comments.kt:4:1:11:3 | /**\n * A group of *members*.\n *\n * This class has no useful logic; it's just a documentation example.\n *\n * @property name the name of this group.\n * @constructor Creates an empty group.\n */ | comments.kt:12:1:31:1 | Group | -| comments.kt:14:5:16:7 | /**\n * Members of this group.\n */ | comments.kt:17:5:17:46 | getMembers$private | +| comments.kt:14:5:16:7 | /**\n * Members of this group.\n */ | comments.kt:17:5:17:23 | getMembers$private | | comments.kt:14:5:16:7 | /**\n * Members of this group.\n */ | comments.kt:17:5:17:46 | members | | comments.kt:14:5:16:7 | /**\n * Members of this group.\n */ | comments.kt:17:5:17:46 | members | | comments.kt:19:5:22:7 | /**\n * Adds a [member] to this group.\n * @return the new size of the group.\n */ | comments.kt:23:5:26:5 | add | +| comments.kt:48:1:50:3 | /**\n * A type alias comment\n */ | comments.kt:51:1:51:24 | MyType | | comments.kt:61:5:63:7 | /**\n * A prop comment\n */ | comments.kt:64:5:68:17 | prop | | comments.kt:65:9:67:11 | /**\n * An accessor comment\n */ | comments.kt:68:9:68:17 | getProp | | comments.kt:79:9:81:11 | /**\n * A local function comment\n */ | comments.kt:82:9:82:24 | localFn | +| comments.kt:88:10:90:11 | /**\n * An anonymous object comment\n */ | comments.kt:87:15:92:5 | | | comments.kt:88:10:90:11 | /**\n * An anonymous object comment\n */ | comments.kt:87:15:92:5 | new X(...) { ... } | commentNoOwners | comments.kt:24:9:24:25 | // A line comment | @@ -32,7 +34,6 @@ commentNoOwners | comments.kt:35:5:35:34 | /** Medium is in the middle */ | | comments.kt:37:5:37:23 | /** This is high */ | | comments.kt:42:5:44:7 | /**\n * A variable.\n */ | -| comments.kt:48:1:50:3 | /**\n * A type alias comment\n */ | | comments.kt:54:5:56:7 | /**\n * An init block comment\n */ | | comments.kt:71:9:73:11 | /**\n * An anonymous function comment\n */ | commentSections diff --git a/java/ql/test-kotlin2/library-tests/exprs/PrintAst.expected b/java/ql/test-kotlin2/library-tests/exprs/PrintAst.expected index f408cad82881..6a4ac3cab31d 100644 --- a/java/ql/test-kotlin2/library-tests/exprs/PrintAst.expected +++ b/java/ql/test-kotlin2/library-tests/exprs/PrintAst.expected @@ -21,16 +21,14 @@ delegatedProperties.kt: # 60| 0: [VarAccess] DelegatedPropertiesKt.topLevelInt # 60| -1: [TypeAccess] DelegatedPropertiesKt # 60| 1: [VarAccess] -# 87| 5: [ExtensionMethod] setExtDelegated -# 87| 3: [TypeAccess] Unit +# 87| 5: [ExtensionMethod] getExtDelegated +# 87| 3: [TypeAccess] int #-----| 4: (Parameters) # 87| 0: [Parameter] # 87| 0: [TypeAccess] MyClass -# 87| 1: [Parameter] -# 87| 0: [TypeAccess] int # 87| 5: [BlockStmt] { ... } # 87| 0: [ReturnStmt] return ... -# 87| 0: [MethodCall] setValue(...) +# 87| 0: [MethodCall] getValue(...) # 87| -2: [TypeAccess] Integer # 87| -1: [TypeAccess] PropertyReferenceDelegatesKt # 87| 0: [VarAccess] DelegatedPropertiesKt.extDelegated$delegateMyClass @@ -70,43 +68,16 @@ delegatedProperties.kt: # 87| -3: [TypeAccess] KMutableProperty1 # 87| 0: [TypeAccess] MyClass # 87| 1: [TypeAccess] Integer -# 87| 3: [VarAccess] -# 87| 6: [FieldDeclaration] KMutableProperty0 extDelegated$delegateMyClass; -# 87| -1: [TypeAccess] KMutableProperty0 -# 87| 0: [TypeAccess] Integer -# 87| 0: [PropertyRefExpr] ...::... -# 87| -4: [AnonymousClass] new KMutableProperty0(...) { ... } -# 87| 1: [Constructor] -# 87| 5: [BlockStmt] { ... } -# 87| 0: [SuperConstructorInvocationStmt] super(...) -# 87| 2: [Method] get -# 87| 5: [BlockStmt] { ... } -# 87| 0: [ReturnStmt] return ... -# 87| 0: [MethodCall] getTopLevelInt(...) -# 87| -1: [TypeAccess] DelegatedPropertiesKt -# 87| 3: [Method] invoke -# 87| 5: [BlockStmt] { ... } -# 87| 0: [ReturnStmt] return ... -# 87| 0: [MethodCall] get(...) -# 87| -1: [ThisAccess] this -# 87| 4: [Method] set -#-----| 4: (Parameters) -# 87| 0: [Parameter] a0 -# 87| 5: [BlockStmt] { ... } -# 87| 0: [ReturnStmt] return ... -# 87| 0: [MethodCall] setTopLevelInt(...) -# 87| -1: [TypeAccess] DelegatedPropertiesKt -# 87| 0: [VarAccess] a0 -# 87| -3: [TypeAccess] KMutableProperty0 -# 87| 0: [TypeAccess] Integer -# 87| 7: [ExtensionMethod] getExtDelegated -# 87| 3: [TypeAccess] int +# 87| 6: [ExtensionMethod] setExtDelegated +# 87| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 87| 0: [Parameter] # 87| 0: [TypeAccess] MyClass +# 87| 1: [Parameter] +# 87| 0: [TypeAccess] int # 87| 5: [BlockStmt] { ... } # 87| 0: [ReturnStmt] return ... -# 87| 0: [MethodCall] getValue(...) +# 87| 0: [MethodCall] setValue(...) # 87| -2: [TypeAccess] Integer # 87| -1: [TypeAccess] PropertyReferenceDelegatesKt # 87| 0: [VarAccess] DelegatedPropertiesKt.extDelegated$delegateMyClass @@ -146,6 +117,35 @@ delegatedProperties.kt: # 87| -3: [TypeAccess] KMutableProperty1 # 87| 0: [TypeAccess] MyClass # 87| 1: [TypeAccess] Integer +# 87| 3: [VarAccess] +# 87| 7: [FieldDeclaration] KMutableProperty0 extDelegated$delegateMyClass; +# 87| -1: [TypeAccess] KMutableProperty0 +# 87| 0: [TypeAccess] Integer +# 87| 0: [PropertyRefExpr] ...::... +# 87| -4: [AnonymousClass] new KMutableProperty0(...) { ... } +# 87| 1: [Constructor] +# 87| 5: [BlockStmt] { ... } +# 87| 0: [SuperConstructorInvocationStmt] super(...) +# 87| 2: [Method] get +# 87| 5: [BlockStmt] { ... } +# 87| 0: [ReturnStmt] return ... +# 87| 0: [MethodCall] getTopLevelInt(...) +# 87| -1: [TypeAccess] DelegatedPropertiesKt +# 87| 3: [Method] invoke +# 87| 5: [BlockStmt] { ... } +# 87| 0: [ReturnStmt] return ... +# 87| 0: [MethodCall] get(...) +# 87| -1: [ThisAccess] this +# 87| 4: [Method] set +#-----| 4: (Parameters) +# 87| 0: [Parameter] a0 +# 87| 5: [BlockStmt] { ... } +# 87| 0: [ReturnStmt] return ... +# 87| 0: [MethodCall] setTopLevelInt(...) +# 87| -1: [TypeAccess] DelegatedPropertiesKt +# 87| 0: [VarAccess] a0 +# 87| -3: [TypeAccess] KMutableProperty0 +# 87| 0: [TypeAccess] Integer # 4| 2: [Class] ClassProp1 # 4| 1: [Constructor] ClassProp1 # 4| 5: [BlockStmt] { ... } @@ -637,14 +637,11 @@ delegatedProperties.kt: # 39| -1: [ThisAccess] this # 39| -3: [TypeAccess] KProperty0 # 39| 0: [TypeAccess] Integer -# 42| 3: [Method] setVarResource0 -# 42| 3: [TypeAccess] Unit -#-----| 4: (Parameters) -# 42| 0: [Parameter] -# 42| 0: [TypeAccess] int +# 42| 3: [Method] getVarResource0 +# 42| 3: [TypeAccess] int # 42| 5: [BlockStmt] { ... } # 42| 0: [ReturnStmt] return ... -# 42| 0: [MethodCall] setValue(...) +# 42| 0: [MethodCall] getValue(...) # 42| -1: [VarAccess] this.varResource0$delegate # 42| -1: [ThisAccess] this # 42| 0: [ThisAccess] this @@ -680,16 +677,14 @@ delegatedProperties.kt: # 42| -3: [TypeAccess] KMutableProperty1 # 42| 0: [TypeAccess] Owner # 42| 1: [TypeAccess] Integer -# 42| 2: [VarAccess] -# 42| 4: [FieldDeclaration] ResourceDelegate varResource0$delegate; -# 42| -1: [TypeAccess] ResourceDelegate -# 42| 0: [ClassInstanceExpr] new ResourceDelegate(...) -# 42| -3: [TypeAccess] ResourceDelegate -# 42| 5: [Method] getVarResource0 -# 42| 3: [TypeAccess] int +# 42| 4: [Method] setVarResource0 +# 42| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 42| 0: [Parameter] +# 42| 0: [TypeAccess] int # 42| 5: [BlockStmt] { ... } # 42| 0: [ReturnStmt] return ... -# 42| 0: [MethodCall] getValue(...) +# 42| 0: [MethodCall] setValue(...) # 42| -1: [VarAccess] this.varResource0$delegate # 42| -1: [ThisAccess] this # 42| 0: [ThisAccess] this @@ -725,6 +720,11 @@ delegatedProperties.kt: # 42| -3: [TypeAccess] KMutableProperty1 # 42| 0: [TypeAccess] Owner # 42| 1: [TypeAccess] Integer +# 42| 2: [VarAccess] +# 42| 5: [FieldDeclaration] ResourceDelegate varResource0$delegate; +# 42| -1: [TypeAccess] ResourceDelegate +# 42| 0: [ClassInstanceExpr] new ResourceDelegate(...) +# 42| -3: [TypeAccess] ResourceDelegate # 45| 5: [Class] ResourceDelegate # 45| 1: [Constructor] ResourceDelegate # 45| 5: [BlockStmt] { ... } @@ -882,7 +882,49 @@ delegatedProperties.kt: # 65| 0: [ReturnStmt] return ... # 65| 0: [VarAccess] this.anotherClassInstance # 65| -1: [ThisAccess] this -# 66| 7: [Method] setDelegatedToMember1 +# 66| 7: [Method] getDelegatedToMember1 +# 66| 3: [TypeAccess] int +# 66| 5: [BlockStmt] { ... } +# 66| 0: [ReturnStmt] return ... +# 66| 0: [MethodCall] getValue(...) +# 66| -2: [TypeAccess] Integer +# 66| -1: [TypeAccess] PropertyReferenceDelegatesKt +# 66| 0: [VarAccess] this.delegatedToMember1$delegate +# 66| -1: [ThisAccess] this +# 66| 1: [ThisAccess] this +# 66| 2: [PropertyRefExpr] ...::... +# 66| -4: [AnonymousClass] new KMutableProperty1(...) { ... } +# 66| 1: [Constructor] +# 66| 5: [BlockStmt] { ... } +# 66| 0: [SuperConstructorInvocationStmt] super(...) +# 66| 2: [Method] get +#-----| 4: (Parameters) +# 66| 0: [Parameter] a0 +# 66| 5: [BlockStmt] { ... } +# 66| 0: [ReturnStmt] return ... +# 66| 0: [MethodCall] getDelegatedToMember1(...) +# 66| -1: [VarAccess] a0 +# 66| 3: [Method] invoke +#-----| 4: (Parameters) +# 66| 0: [Parameter] a0 +# 66| 5: [BlockStmt] { ... } +# 66| 0: [ReturnStmt] return ... +# 66| 0: [MethodCall] get(...) +# 66| -1: [ThisAccess] this +# 66| 0: [VarAccess] a0 +# 66| 4: [Method] set +#-----| 4: (Parameters) +# 66| 0: [Parameter] a0 +# 66| 1: [Parameter] a1 +# 66| 5: [BlockStmt] { ... } +# 66| 0: [ReturnStmt] return ... +# 66| 0: [MethodCall] setDelegatedToMember1(...) +# 66| -1: [VarAccess] a0 +# 66| 0: [VarAccess] a1 +# 66| -3: [TypeAccess] KMutableProperty1 +# 66| 0: [TypeAccess] MyClass +# 66| 1: [TypeAccess] Integer +# 66| 8: [Method] setDelegatedToMember1 # 66| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 66| 0: [Parameter] @@ -928,7 +970,7 @@ delegatedProperties.kt: # 66| 0: [TypeAccess] MyClass # 66| 1: [TypeAccess] Integer # 66| 3: [VarAccess] -# 66| 8: [FieldDeclaration] KMutableProperty0 delegatedToMember1$delegate; +# 66| 9: [FieldDeclaration] KMutableProperty0 delegatedToMember1$delegate; # 66| -1: [TypeAccess] KMutableProperty0 # 66| 0: [TypeAccess] Integer # 66| 0: [PropertyRefExpr] ...::... @@ -969,49 +1011,50 @@ delegatedProperties.kt: # 66| 0: [TypeAccess] Integer # 66| 0: [ThisAccess] MyClass.this # 66| 0: [TypeAccess] MyClass -# 66| 9: [Method] getDelegatedToMember1 -# 66| 3: [TypeAccess] int -# 66| 5: [BlockStmt] { ... } -# 66| 0: [ReturnStmt] return ... -# 66| 0: [MethodCall] getValue(...) -# 66| -2: [TypeAccess] Integer -# 66| -1: [TypeAccess] PropertyReferenceDelegatesKt -# 66| 0: [VarAccess] this.delegatedToMember1$delegate -# 66| -1: [ThisAccess] this -# 66| 1: [ThisAccess] this -# 66| 2: [PropertyRefExpr] ...::... -# 66| -4: [AnonymousClass] new KMutableProperty1(...) { ... } -# 66| 1: [Constructor] -# 66| 5: [BlockStmt] { ... } -# 66| 0: [SuperConstructorInvocationStmt] super(...) -# 66| 2: [Method] get +# 67| 10: [Method] getDelegatedToMember2 +# 67| 3: [TypeAccess] int +# 67| 5: [BlockStmt] { ... } +# 67| 0: [ReturnStmt] return ... +# 67| 0: [MethodCall] getValue(...) +# 67| -3: [TypeAccess] Integer +# 67| -2: [TypeAccess] MyClass +# 67| -1: [TypeAccess] PropertyReferenceDelegatesKt +# 67| 0: [VarAccess] this.delegatedToMember2$delegate +# 67| -1: [ThisAccess] this +# 67| 1: [ThisAccess] this +# 67| 2: [PropertyRefExpr] ...::... +# 67| -4: [AnonymousClass] new KMutableProperty1(...) { ... } +# 67| 1: [Constructor] +# 67| 5: [BlockStmt] { ... } +# 67| 0: [SuperConstructorInvocationStmt] super(...) +# 67| 2: [Method] get #-----| 4: (Parameters) -# 66| 0: [Parameter] a0 -# 66| 5: [BlockStmt] { ... } -# 66| 0: [ReturnStmt] return ... -# 66| 0: [MethodCall] getDelegatedToMember1(...) -# 66| -1: [VarAccess] a0 -# 66| 3: [Method] invoke +# 67| 0: [Parameter] a0 +# 67| 5: [BlockStmt] { ... } +# 67| 0: [ReturnStmt] return ... +# 67| 0: [MethodCall] getDelegatedToMember2(...) +# 67| -1: [VarAccess] a0 +# 67| 3: [Method] invoke #-----| 4: (Parameters) -# 66| 0: [Parameter] a0 -# 66| 5: [BlockStmt] { ... } -# 66| 0: [ReturnStmt] return ... -# 66| 0: [MethodCall] get(...) -# 66| -1: [ThisAccess] this -# 66| 0: [VarAccess] a0 -# 66| 4: [Method] set +# 67| 0: [Parameter] a0 +# 67| 5: [BlockStmt] { ... } +# 67| 0: [ReturnStmt] return ... +# 67| 0: [MethodCall] get(...) +# 67| -1: [ThisAccess] this +# 67| 0: [VarAccess] a0 +# 67| 4: [Method] set #-----| 4: (Parameters) -# 66| 0: [Parameter] a0 -# 66| 1: [Parameter] a1 -# 66| 5: [BlockStmt] { ... } -# 66| 0: [ReturnStmt] return ... -# 66| 0: [MethodCall] setDelegatedToMember1(...) -# 66| -1: [VarAccess] a0 -# 66| 0: [VarAccess] a1 -# 66| -3: [TypeAccess] KMutableProperty1 -# 66| 0: [TypeAccess] MyClass -# 66| 1: [TypeAccess] Integer -# 67| 10: [Method] setDelegatedToMember2 +# 67| 0: [Parameter] a0 +# 67| 1: [Parameter] a1 +# 67| 5: [BlockStmt] { ... } +# 67| 0: [ReturnStmt] return ... +# 67| 0: [MethodCall] setDelegatedToMember2(...) +# 67| -1: [VarAccess] a0 +# 67| 0: [VarAccess] a1 +# 67| -3: [TypeAccess] KMutableProperty1 +# 67| 0: [TypeAccess] MyClass +# 67| 1: [TypeAccess] Integer +# 67| 11: [Method] setDelegatedToMember2 # 67| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 67| 0: [Parameter] @@ -1058,7 +1101,7 @@ delegatedProperties.kt: # 67| 0: [TypeAccess] MyClass # 67| 1: [TypeAccess] Integer # 67| 3: [VarAccess] -# 67| 11: [FieldDeclaration] KMutableProperty1 delegatedToMember2$delegate; +# 67| 12: [FieldDeclaration] KMutableProperty1 delegatedToMember2$delegate; # 67| -1: [TypeAccess] KMutableProperty1 # 67| 0: [TypeAccess] MyClass # 67| 1: [TypeAccess] Integer @@ -1094,57 +1137,56 @@ delegatedProperties.kt: # 67| -3: [TypeAccess] KMutableProperty1 # 67| 0: [TypeAccess] MyClass # 67| 1: [TypeAccess] Integer -# 67| 12: [Method] getDelegatedToMember2 -# 67| 3: [TypeAccess] int -# 67| 5: [BlockStmt] { ... } -# 67| 0: [ReturnStmt] return ... -# 67| 0: [MethodCall] getValue(...) -# 67| -3: [TypeAccess] Integer -# 67| -2: [TypeAccess] MyClass -# 67| -1: [TypeAccess] PropertyReferenceDelegatesKt -# 67| 0: [VarAccess] this.delegatedToMember2$delegate -# 67| -1: [ThisAccess] this -# 67| 1: [ThisAccess] this -# 67| 2: [PropertyRefExpr] ...::... -# 67| -4: [AnonymousClass] new KMutableProperty1(...) { ... } -# 67| 1: [Constructor] -# 67| 5: [BlockStmt] { ... } -# 67| 0: [SuperConstructorInvocationStmt] super(...) -# 67| 2: [Method] get -#-----| 4: (Parameters) -# 67| 0: [Parameter] a0 -# 67| 5: [BlockStmt] { ... } -# 67| 0: [ReturnStmt] return ... -# 67| 0: [MethodCall] getDelegatedToMember2(...) -# 67| -1: [VarAccess] a0 -# 67| 3: [Method] invoke -#-----| 4: (Parameters) -# 67| 0: [Parameter] a0 -# 67| 5: [BlockStmt] { ... } -# 67| 0: [ReturnStmt] return ... -# 67| 0: [MethodCall] get(...) -# 67| -1: [ThisAccess] this -# 67| 0: [VarAccess] a0 -# 67| 4: [Method] set -#-----| 4: (Parameters) -# 67| 0: [Parameter] a0 -# 67| 1: [Parameter] a1 -# 67| 5: [BlockStmt] { ... } -# 67| 0: [ReturnStmt] return ... -# 67| 0: [MethodCall] setDelegatedToMember2(...) -# 67| -1: [VarAccess] a0 -# 67| 0: [VarAccess] a1 -# 67| -3: [TypeAccess] KMutableProperty1 -# 67| 0: [TypeAccess] MyClass -# 67| 1: [TypeAccess] Integer -# 69| 13: [Method] setDelegatedToExtMember1 -# 69| 3: [TypeAccess] Unit -#-----| 4: (Parameters) -# 69| 0: [Parameter] -# 69| 0: [TypeAccess] int +# 69| 13: [Method] getDelegatedToExtMember1 +# 69| 3: [TypeAccess] int # 69| 5: [BlockStmt] { ... } # 69| 0: [ReturnStmt] return ... -# 69| 0: [MethodCall] setValue(...) +# 69| 0: [MethodCall] getValue(...) +# 69| -2: [TypeAccess] Integer +# 69| -1: [TypeAccess] PropertyReferenceDelegatesKt +# 69| 0: [VarAccess] this.delegatedToExtMember1$delegate +# 69| -1: [ThisAccess] this +# 69| 1: [ThisAccess] this +# 69| 2: [PropertyRefExpr] ...::... +# 69| -4: [AnonymousClass] new KMutableProperty1(...) { ... } +# 69| 1: [Constructor] +# 69| 5: [BlockStmt] { ... } +# 69| 0: [SuperConstructorInvocationStmt] super(...) +# 69| 2: [Method] get +#-----| 4: (Parameters) +# 69| 0: [Parameter] a0 +# 69| 5: [BlockStmt] { ... } +# 69| 0: [ReturnStmt] return ... +# 69| 0: [MethodCall] getDelegatedToExtMember1(...) +# 69| -1: [VarAccess] a0 +# 69| 3: [Method] invoke +#-----| 4: (Parameters) +# 69| 0: [Parameter] a0 +# 69| 5: [BlockStmt] { ... } +# 69| 0: [ReturnStmt] return ... +# 69| 0: [MethodCall] get(...) +# 69| -1: [ThisAccess] this +# 69| 0: [VarAccess] a0 +# 69| 4: [Method] set +#-----| 4: (Parameters) +# 69| 0: [Parameter] a0 +# 69| 1: [Parameter] a1 +# 69| 5: [BlockStmt] { ... } +# 69| 0: [ReturnStmt] return ... +# 69| 0: [MethodCall] setDelegatedToExtMember1(...) +# 69| -1: [VarAccess] a0 +# 69| 0: [VarAccess] a1 +# 69| -3: [TypeAccess] KMutableProperty1 +# 69| 0: [TypeAccess] MyClass +# 69| 1: [TypeAccess] Integer +# 69| 14: [Method] setDelegatedToExtMember1 +# 69| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 69| 0: [Parameter] +# 69| 0: [TypeAccess] int +# 69| 5: [BlockStmt] { ... } +# 69| 0: [ReturnStmt] return ... +# 69| 0: [MethodCall] setValue(...) # 69| -2: [TypeAccess] Integer # 69| -1: [TypeAccess] PropertyReferenceDelegatesKt # 69| 0: [VarAccess] this.delegatedToExtMember1$delegate @@ -1183,7 +1225,7 @@ delegatedProperties.kt: # 69| 0: [TypeAccess] MyClass # 69| 1: [TypeAccess] Integer # 69| 3: [VarAccess] -# 69| 14: [FieldDeclaration] KMutableProperty0 delegatedToExtMember1$delegate; +# 69| 15: [FieldDeclaration] KMutableProperty0 delegatedToExtMember1$delegate; # 69| -1: [TypeAccess] KMutableProperty0 # 69| 0: [TypeAccess] Integer # 69| 0: [PropertyRefExpr] ...::... @@ -1226,49 +1268,50 @@ delegatedProperties.kt: # 69| 0: [TypeAccess] Integer # 69| 0: [ThisAccess] MyClass.this # 69| 0: [TypeAccess] MyClass -# 69| 15: [Method] getDelegatedToExtMember1 -# 69| 3: [TypeAccess] int -# 69| 5: [BlockStmt] { ... } -# 69| 0: [ReturnStmt] return ... -# 69| 0: [MethodCall] getValue(...) -# 69| -2: [TypeAccess] Integer -# 69| -1: [TypeAccess] PropertyReferenceDelegatesKt -# 69| 0: [VarAccess] this.delegatedToExtMember1$delegate -# 69| -1: [ThisAccess] this -# 69| 1: [ThisAccess] this -# 69| 2: [PropertyRefExpr] ...::... -# 69| -4: [AnonymousClass] new KMutableProperty1(...) { ... } -# 69| 1: [Constructor] -# 69| 5: [BlockStmt] { ... } -# 69| 0: [SuperConstructorInvocationStmt] super(...) -# 69| 2: [Method] get +# 70| 16: [Method] getDelegatedToExtMember2 +# 70| 3: [TypeAccess] int +# 70| 5: [BlockStmt] { ... } +# 70| 0: [ReturnStmt] return ... +# 70| 0: [MethodCall] getValue(...) +# 70| -3: [TypeAccess] Integer +# 70| -2: [TypeAccess] MyClass +# 70| -1: [TypeAccess] PropertyReferenceDelegatesKt +# 70| 0: [VarAccess] this.delegatedToExtMember2$delegate +# 70| -1: [ThisAccess] this +# 70| 1: [ThisAccess] this +# 70| 2: [PropertyRefExpr] ...::... +# 70| -4: [AnonymousClass] new KMutableProperty1(...) { ... } +# 70| 1: [Constructor] +# 70| 5: [BlockStmt] { ... } +# 70| 0: [SuperConstructorInvocationStmt] super(...) +# 70| 2: [Method] get #-----| 4: (Parameters) -# 69| 0: [Parameter] a0 -# 69| 5: [BlockStmt] { ... } -# 69| 0: [ReturnStmt] return ... -# 69| 0: [MethodCall] getDelegatedToExtMember1(...) -# 69| -1: [VarAccess] a0 -# 69| 3: [Method] invoke +# 70| 0: [Parameter] a0 +# 70| 5: [BlockStmt] { ... } +# 70| 0: [ReturnStmt] return ... +# 70| 0: [MethodCall] getDelegatedToExtMember2(...) +# 70| -1: [VarAccess] a0 +# 70| 3: [Method] invoke #-----| 4: (Parameters) -# 69| 0: [Parameter] a0 -# 69| 5: [BlockStmt] { ... } -# 69| 0: [ReturnStmt] return ... -# 69| 0: [MethodCall] get(...) -# 69| -1: [ThisAccess] this -# 69| 0: [VarAccess] a0 -# 69| 4: [Method] set +# 70| 0: [Parameter] a0 +# 70| 5: [BlockStmt] { ... } +# 70| 0: [ReturnStmt] return ... +# 70| 0: [MethodCall] get(...) +# 70| -1: [ThisAccess] this +# 70| 0: [VarAccess] a0 +# 70| 4: [Method] set #-----| 4: (Parameters) -# 69| 0: [Parameter] a0 -# 69| 1: [Parameter] a1 -# 69| 5: [BlockStmt] { ... } -# 69| 0: [ReturnStmt] return ... -# 69| 0: [MethodCall] setDelegatedToExtMember1(...) -# 69| -1: [VarAccess] a0 -# 69| 0: [VarAccess] a1 -# 69| -3: [TypeAccess] KMutableProperty1 -# 69| 0: [TypeAccess] MyClass -# 69| 1: [TypeAccess] Integer -# 70| 16: [Method] setDelegatedToExtMember2 +# 70| 0: [Parameter] a0 +# 70| 1: [Parameter] a1 +# 70| 5: [BlockStmt] { ... } +# 70| 0: [ReturnStmt] return ... +# 70| 0: [MethodCall] setDelegatedToExtMember2(...) +# 70| -1: [VarAccess] a0 +# 70| 0: [VarAccess] a1 +# 70| -3: [TypeAccess] KMutableProperty1 +# 70| 0: [TypeAccess] MyClass +# 70| 1: [TypeAccess] Integer +# 70| 17: [Method] setDelegatedToExtMember2 # 70| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 70| 0: [Parameter] @@ -1315,7 +1358,7 @@ delegatedProperties.kt: # 70| 0: [TypeAccess] MyClass # 70| 1: [TypeAccess] Integer # 70| 3: [VarAccess] -# 70| 17: [FieldDeclaration] KMutableProperty1 delegatedToExtMember2$delegate; +# 70| 18: [FieldDeclaration] KMutableProperty1 delegatedToExtMember2$delegate; # 70| -1: [TypeAccess] KMutableProperty1 # 70| 0: [TypeAccess] MyClass # 70| 1: [TypeAccess] Integer @@ -1353,82 +1396,7 @@ delegatedProperties.kt: # 70| -3: [TypeAccess] KMutableProperty1 # 70| 0: [TypeAccess] MyClass # 70| 1: [TypeAccess] Integer -# 70| 18: [Method] getDelegatedToExtMember2 -# 70| 3: [TypeAccess] int -# 70| 5: [BlockStmt] { ... } -# 70| 0: [ReturnStmt] return ... -# 70| 0: [MethodCall] getValue(...) -# 70| -3: [TypeAccess] Integer -# 70| -2: [TypeAccess] MyClass -# 70| -1: [TypeAccess] PropertyReferenceDelegatesKt -# 70| 0: [VarAccess] this.delegatedToExtMember2$delegate -# 70| -1: [ThisAccess] this -# 70| 1: [ThisAccess] this -# 70| 2: [PropertyRefExpr] ...::... -# 70| -4: [AnonymousClass] new KMutableProperty1(...) { ... } -# 70| 1: [Constructor] -# 70| 5: [BlockStmt] { ... } -# 70| 0: [SuperConstructorInvocationStmt] super(...) -# 70| 2: [Method] get -#-----| 4: (Parameters) -# 70| 0: [Parameter] a0 -# 70| 5: [BlockStmt] { ... } -# 70| 0: [ReturnStmt] return ... -# 70| 0: [MethodCall] getDelegatedToExtMember2(...) -# 70| -1: [VarAccess] a0 -# 70| 3: [Method] invoke -#-----| 4: (Parameters) -# 70| 0: [Parameter] a0 -# 70| 5: [BlockStmt] { ... } -# 70| 0: [ReturnStmt] return ... -# 70| 0: [MethodCall] get(...) -# 70| -1: [ThisAccess] this -# 70| 0: [VarAccess] a0 -# 70| 4: [Method] set -#-----| 4: (Parameters) -# 70| 0: [Parameter] a0 -# 70| 1: [Parameter] a1 -# 70| 5: [BlockStmt] { ... } -# 70| 0: [ReturnStmt] return ... -# 70| 0: [MethodCall] setDelegatedToExtMember2(...) -# 70| -1: [VarAccess] a0 -# 70| 0: [VarAccess] a1 -# 70| -3: [TypeAccess] KMutableProperty1 -# 70| 0: [TypeAccess] MyClass -# 70| 1: [TypeAccess] Integer -# 72| 19: [FieldDeclaration] KProperty0 delegatedToBaseClass1$delegate; -# 72| -1: [TypeAccess] KProperty0 -# 72| 0: [TypeAccess] Integer -# 72| 0: [PropertyRefExpr] ...::... -# 72| -4: [AnonymousClass] new KProperty0(...) { ... } -# 72| 1: [Constructor] -#-----| 4: (Parameters) -# 72| 0: [Parameter] -# 72| 5: [BlockStmt] { ... } -# 72| 0: [SuperConstructorInvocationStmt] super(...) -# 72| 1: [ExprStmt] ; -# 72| 0: [AssignExpr] ...=... -# 72| 0: [VarAccess] this. -# 72| -1: [ThisAccess] this -# 72| 1: [VarAccess] -# 72| 2: [FieldDeclaration] MyClass ; -# 72| -1: [TypeAccess] MyClass -# 72| 3: [Method] get -# 72| 5: [BlockStmt] { ... } -# 72| 0: [ReturnStmt] return ... -# 72| 0: [MethodCall] getBaseClassInt(...) -# 72| -1: [VarAccess] this. -# 72| -1: [ThisAccess] this -# 72| 4: [Method] invoke -# 72| 5: [BlockStmt] { ... } -# 72| 0: [ReturnStmt] return ... -# 72| 0: [MethodCall] get(...) -# 72| -1: [ThisAccess] this -# 72| -3: [TypeAccess] KProperty0 -# 72| 0: [TypeAccess] Integer -# 72| 0: [ThisAccess] MyClass.this -# 72| 0: [TypeAccess] MyClass -# 72| 20: [Method] getDelegatedToBaseClass1 +# 72| 19: [Method] getDelegatedToBaseClass1 # 72| 3: [TypeAccess] int # 72| 5: [BlockStmt] { ... } # 72| 0: [ReturnStmt] return ... @@ -1461,34 +1429,39 @@ delegatedProperties.kt: # 72| -3: [TypeAccess] KProperty1 # 72| 0: [TypeAccess] MyClass # 72| 1: [TypeAccess] Integer -# 73| 21: [FieldDeclaration] KProperty1 delegatedToBaseClass2$delegate; -# 73| -1: [TypeAccess] KProperty1 -# 73| 0: [TypeAccess] Base -# 73| 1: [TypeAccess] Integer -# 73| 0: [PropertyRefExpr] ...::... -# 73| -4: [AnonymousClass] new KProperty1(...) { ... } -# 73| 1: [Constructor] -# 73| 5: [BlockStmt] { ... } -# 73| 0: [SuperConstructorInvocationStmt] super(...) -# 73| 2: [Method] get -#-----| 4: (Parameters) -# 73| 0: [Parameter] a0 -# 73| 5: [BlockStmt] { ... } -# 73| 0: [ReturnStmt] return ... -# 73| 0: [MethodCall] getBaseClassInt(...) -# 73| -1: [VarAccess] a0 -# 73| 3: [Method] invoke +# 72| 20: [FieldDeclaration] KProperty0 delegatedToBaseClass1$delegate; +# 72| -1: [TypeAccess] KProperty0 +# 72| 0: [TypeAccess] Integer +# 72| 0: [PropertyRefExpr] ...::... +# 72| -4: [AnonymousClass] new KProperty0(...) { ... } +# 72| 1: [Constructor] #-----| 4: (Parameters) -# 73| 0: [Parameter] a0 -# 73| 5: [BlockStmt] { ... } -# 73| 0: [ReturnStmt] return ... -# 73| 0: [MethodCall] get(...) -# 73| -1: [ThisAccess] this -# 73| 0: [VarAccess] a0 -# 73| -3: [TypeAccess] KProperty1 -# 73| 0: [TypeAccess] Base -# 73| 1: [TypeAccess] Integer -# 73| 22: [Method] getDelegatedToBaseClass2 +# 72| 0: [Parameter] +# 72| 5: [BlockStmt] { ... } +# 72| 0: [SuperConstructorInvocationStmt] super(...) +# 72| 1: [ExprStmt] ; +# 72| 0: [AssignExpr] ...=... +# 72| 0: [VarAccess] this. +# 72| -1: [ThisAccess] this +# 72| 1: [VarAccess] +# 72| 2: [FieldDeclaration] MyClass ; +# 72| -1: [TypeAccess] MyClass +# 72| 3: [Method] get +# 72| 5: [BlockStmt] { ... } +# 72| 0: [ReturnStmt] return ... +# 72| 0: [MethodCall] getBaseClassInt(...) +# 72| -1: [VarAccess] this. +# 72| -1: [ThisAccess] this +# 72| 4: [Method] invoke +# 72| 5: [BlockStmt] { ... } +# 72| 0: [ReturnStmt] return ... +# 72| 0: [MethodCall] get(...) +# 72| -1: [ThisAccess] this +# 72| -3: [TypeAccess] KProperty0 +# 72| 0: [TypeAccess] Integer +# 72| 0: [ThisAccess] MyClass.this +# 72| 0: [TypeAccess] MyClass +# 73| 21: [Method] getDelegatedToBaseClass2 # 73| 3: [TypeAccess] int # 73| 5: [BlockStmt] { ... } # 73| 0: [ReturnStmt] return ... @@ -1522,40 +1495,34 @@ delegatedProperties.kt: # 73| -3: [TypeAccess] KProperty1 # 73| 0: [TypeAccess] MyClass # 73| 1: [TypeAccess] Integer -# 75| 23: [FieldDeclaration] KProperty0 delegatedToAnotherClass1$delegate; -# 75| -1: [TypeAccess] KProperty0 -# 75| 0: [TypeAccess] Integer -# 75| 0: [PropertyRefExpr] ...::... -# 75| -4: [AnonymousClass] new KProperty0(...) { ... } -# 75| 1: [Constructor] +# 73| 22: [FieldDeclaration] KProperty1 delegatedToBaseClass2$delegate; +# 73| -1: [TypeAccess] KProperty1 +# 73| 0: [TypeAccess] Base +# 73| 1: [TypeAccess] Integer +# 73| 0: [PropertyRefExpr] ...::... +# 73| -4: [AnonymousClass] new KProperty1(...) { ... } +# 73| 1: [Constructor] +# 73| 5: [BlockStmt] { ... } +# 73| 0: [SuperConstructorInvocationStmt] super(...) +# 73| 2: [Method] get #-----| 4: (Parameters) -# 75| 0: [Parameter] -# 75| 5: [BlockStmt] { ... } -# 75| 0: [SuperConstructorInvocationStmt] super(...) -# 75| 1: [ExprStmt] ; -# 75| 0: [AssignExpr] ...=... -# 75| 0: [VarAccess] this. -# 75| -1: [ThisAccess] this -# 75| 1: [VarAccess] -# 75| 2: [FieldDeclaration] ClassWithDelegate ; -# 75| -1: [TypeAccess] ClassWithDelegate -# 75| 3: [Method] get -# 75| 5: [BlockStmt] { ... } -# 75| 0: [ReturnStmt] return ... -# 75| 0: [MethodCall] getAnotherClassInt(...) -# 75| -1: [VarAccess] this. -# 75| -1: [ThisAccess] this -# 75| 4: [Method] invoke -# 75| 5: [BlockStmt] { ... } -# 75| 0: [ReturnStmt] return ... -# 75| 0: [MethodCall] get(...) -# 75| -1: [ThisAccess] this -# 75| -3: [TypeAccess] KProperty0 -# 75| 0: [TypeAccess] Integer -# 75| 0: [MethodCall] getAnotherClassInstance(...) -# 75| -1: [ThisAccess] MyClass.this -# 75| 0: [TypeAccess] MyClass -# 75| 24: [Method] getDelegatedToAnotherClass1 +# 73| 0: [Parameter] a0 +# 73| 5: [BlockStmt] { ... } +# 73| 0: [ReturnStmt] return ... +# 73| 0: [MethodCall] getBaseClassInt(...) +# 73| -1: [VarAccess] a0 +# 73| 3: [Method] invoke +#-----| 4: (Parameters) +# 73| 0: [Parameter] a0 +# 73| 5: [BlockStmt] { ... } +# 73| 0: [ReturnStmt] return ... +# 73| 0: [MethodCall] get(...) +# 73| -1: [ThisAccess] this +# 73| 0: [VarAccess] a0 +# 73| -3: [TypeAccess] KProperty1 +# 73| 0: [TypeAccess] Base +# 73| 1: [TypeAccess] Integer +# 75| 23: [Method] getDelegatedToAnotherClass1 # 75| 3: [TypeAccess] int # 75| 5: [BlockStmt] { ... } # 75| 0: [ReturnStmt] return ... @@ -1588,14 +1555,44 @@ delegatedProperties.kt: # 75| -3: [TypeAccess] KProperty1 # 75| 0: [TypeAccess] MyClass # 75| 1: [TypeAccess] Integer -# 77| 25: [Method] setDelegatedToTopLevel -# 77| 3: [TypeAccess] Unit -#-----| 4: (Parameters) -# 77| 0: [Parameter] -# 77| 0: [TypeAccess] int +# 75| 24: [FieldDeclaration] KProperty0 delegatedToAnotherClass1$delegate; +# 75| -1: [TypeAccess] KProperty0 +# 75| 0: [TypeAccess] Integer +# 75| 0: [PropertyRefExpr] ...::... +# 75| -4: [AnonymousClass] new KProperty0(...) { ... } +# 75| 1: [Constructor] +#-----| 4: (Parameters) +# 75| 0: [Parameter] +# 75| 5: [BlockStmt] { ... } +# 75| 0: [SuperConstructorInvocationStmt] super(...) +# 75| 1: [ExprStmt] ; +# 75| 0: [AssignExpr] ...=... +# 75| 0: [VarAccess] this. +# 75| -1: [ThisAccess] this +# 75| 1: [VarAccess] +# 75| 2: [FieldDeclaration] ClassWithDelegate ; +# 75| -1: [TypeAccess] ClassWithDelegate +# 75| 3: [Method] get +# 75| 5: [BlockStmt] { ... } +# 75| 0: [ReturnStmt] return ... +# 75| 0: [MethodCall] getAnotherClassInt(...) +# 75| -1: [VarAccess] this. +# 75| -1: [ThisAccess] this +# 75| 4: [Method] invoke +# 75| 5: [BlockStmt] { ... } +# 75| 0: [ReturnStmt] return ... +# 75| 0: [MethodCall] get(...) +# 75| -1: [ThisAccess] this +# 75| -3: [TypeAccess] KProperty0 +# 75| 0: [TypeAccess] Integer +# 75| 0: [MethodCall] getAnotherClassInstance(...) +# 75| -1: [ThisAccess] MyClass.this +# 75| 0: [TypeAccess] MyClass +# 77| 25: [Method] getDelegatedToTopLevel +# 77| 3: [TypeAccess] int # 77| 5: [BlockStmt] { ... } # 77| 0: [ReturnStmt] return ... -# 77| 0: [MethodCall] setValue(...) +# 77| 0: [MethodCall] getValue(...) # 77| -2: [TypeAccess] Integer # 77| -1: [TypeAccess] PropertyReferenceDelegatesKt # 77| 0: [VarAccess] this.delegatedToTopLevel$delegate @@ -1633,40 +1630,14 @@ delegatedProperties.kt: # 77| -3: [TypeAccess] KMutableProperty1 # 77| 0: [TypeAccess] MyClass # 77| 1: [TypeAccess] Integer -# 77| 3: [VarAccess] -# 77| 26: [FieldDeclaration] KMutableProperty0 delegatedToTopLevel$delegate; -# 77| -1: [TypeAccess] KMutableProperty0 -# 77| 0: [TypeAccess] Integer -# 77| 0: [PropertyRefExpr] ...::... -# 77| -4: [AnonymousClass] new KMutableProperty0(...) { ... } -# 77| 1: [Constructor] -# 77| 5: [BlockStmt] { ... } -# 77| 0: [SuperConstructorInvocationStmt] super(...) -# 77| 2: [Method] get -# 77| 5: [BlockStmt] { ... } -# 77| 0: [ReturnStmt] return ... -# 77| 0: [MethodCall] getTopLevelInt(...) -# 77| -1: [TypeAccess] DelegatedPropertiesKt -# 77| 3: [Method] invoke -# 77| 5: [BlockStmt] { ... } -# 77| 0: [ReturnStmt] return ... -# 77| 0: [MethodCall] get(...) -# 77| -1: [ThisAccess] this -# 77| 4: [Method] set -#-----| 4: (Parameters) -# 77| 0: [Parameter] a0 -# 77| 5: [BlockStmt] { ... } -# 77| 0: [ReturnStmt] return ... -# 77| 0: [MethodCall] setTopLevelInt(...) -# 77| -1: [TypeAccess] DelegatedPropertiesKt -# 77| 0: [VarAccess] a0 -# 77| -3: [TypeAccess] KMutableProperty0 -# 77| 0: [TypeAccess] Integer -# 77| 27: [Method] getDelegatedToTopLevel -# 77| 3: [TypeAccess] int +# 77| 26: [Method] setDelegatedToTopLevel +# 77| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 77| 0: [Parameter] +# 77| 0: [TypeAccess] int # 77| 5: [BlockStmt] { ... } # 77| 0: [ReturnStmt] return ... -# 77| 0: [MethodCall] getValue(...) +# 77| 0: [MethodCall] setValue(...) # 77| -2: [TypeAccess] Integer # 77| -1: [TypeAccess] PropertyReferenceDelegatesKt # 77| 0: [VarAccess] this.delegatedToTopLevel$delegate @@ -1704,26 +1675,36 @@ delegatedProperties.kt: # 77| -3: [TypeAccess] KMutableProperty1 # 77| 0: [TypeAccess] MyClass # 77| 1: [TypeAccess] Integer -# 79| 28: [FieldDeclaration] KProperty0 max$delegate; -# 79| -1: [TypeAccess] KProperty0 -# 79| 0: [TypeAccess] Integer -# 79| 0: [PropertyRefExpr] ...::... -# 79| -4: [AnonymousClass] new KProperty0(...) { ... } -# 79| 1: [Constructor] -# 79| 5: [BlockStmt] { ... } -# 79| 0: [SuperConstructorInvocationStmt] super(...) -# 79| 2: [Method] get -# 79| 5: [BlockStmt] { ... } -# 79| 0: [ReturnStmt] return ... -# 79| 0: [VarAccess] MAX_VALUE -# 79| 3: [Method] invoke -# 79| 5: [BlockStmt] { ... } -# 79| 0: [ReturnStmt] return ... -# 79| 0: [MethodCall] get(...) -# 79| -1: [ThisAccess] this -# 79| -3: [TypeAccess] KProperty0 -# 79| 0: [TypeAccess] Integer -# 79| 29: [Method] getMax +# 77| 3: [VarAccess] +# 77| 27: [FieldDeclaration] KMutableProperty0 delegatedToTopLevel$delegate; +# 77| -1: [TypeAccess] KMutableProperty0 +# 77| 0: [TypeAccess] Integer +# 77| 0: [PropertyRefExpr] ...::... +# 77| -4: [AnonymousClass] new KMutableProperty0(...) { ... } +# 77| 1: [Constructor] +# 77| 5: [BlockStmt] { ... } +# 77| 0: [SuperConstructorInvocationStmt] super(...) +# 77| 2: [Method] get +# 77| 5: [BlockStmt] { ... } +# 77| 0: [ReturnStmt] return ... +# 77| 0: [MethodCall] getTopLevelInt(...) +# 77| -1: [TypeAccess] DelegatedPropertiesKt +# 77| 3: [Method] invoke +# 77| 5: [BlockStmt] { ... } +# 77| 0: [ReturnStmt] return ... +# 77| 0: [MethodCall] get(...) +# 77| -1: [ThisAccess] this +# 77| 4: [Method] set +#-----| 4: (Parameters) +# 77| 0: [Parameter] a0 +# 77| 5: [BlockStmt] { ... } +# 77| 0: [ReturnStmt] return ... +# 77| 0: [MethodCall] setTopLevelInt(...) +# 77| -1: [TypeAccess] DelegatedPropertiesKt +# 77| 0: [VarAccess] a0 +# 77| -3: [TypeAccess] KMutableProperty0 +# 77| 0: [TypeAccess] Integer +# 79| 28: [Method] getMax # 79| 3: [TypeAccess] int # 79| 5: [BlockStmt] { ... } # 79| 0: [ReturnStmt] return ... @@ -1756,6 +1737,25 @@ delegatedProperties.kt: # 79| -3: [TypeAccess] KProperty1 # 79| 0: [TypeAccess] MyClass # 79| 1: [TypeAccess] Integer +# 79| 29: [FieldDeclaration] KProperty0 max$delegate; +# 79| -1: [TypeAccess] KProperty0 +# 79| 0: [TypeAccess] Integer +# 79| 0: [PropertyRefExpr] ...::... +# 79| -4: [AnonymousClass] new KProperty0(...) { ... } +# 79| 1: [Constructor] +# 79| 5: [BlockStmt] { ... } +# 79| 0: [SuperConstructorInvocationStmt] super(...) +# 79| 2: [Method] get +# 79| 5: [BlockStmt] { ... } +# 79| 0: [ReturnStmt] return ... +# 79| 0: [VarAccess] MAX_VALUE +# 79| 3: [Method] invoke +# 79| 5: [BlockStmt] { ... } +# 79| 0: [ReturnStmt] return ... +# 79| 0: [MethodCall] get(...) +# 79| -1: [ThisAccess] this +# 79| -3: [TypeAccess] KProperty0 +# 79| 0: [TypeAccess] Integer # 81| 30: [Method] fn # 81| 3: [TypeAccess] Unit # 81| 5: [BlockStmt] { ... } @@ -2848,23 +2848,17 @@ exprs.kt: # 271| 0: [VarAccess] updated # 271| 1: [IntegerLiteral] 1 # 272| 3: [ExprStmt] ; -# 272| 0: [AssignExpr] ...=... +# 272| 0: [AssignMulExpr] ...*=... # 272| 0: [VarAccess] updated -# 272| 1: [MulExpr] ... * ... -# 272| 0: [VarAccess] updated -# 272| 1: [IntegerLiteral] 1 +# 272| 1: [IntegerLiteral] 1 # 273| 4: [ExprStmt] ; -# 273| 0: [AssignExpr] ...=... +# 273| 0: [AssignDivExpr] .../=... # 273| 0: [VarAccess] updated -# 273| 1: [DivExpr] ... / ... -# 273| 0: [VarAccess] updated -# 273| 1: [IntegerLiteral] 1 +# 273| 1: [IntegerLiteral] 1 # 274| 5: [ExprStmt] ; -# 274| 0: [AssignExpr] ...=... +# 274| 0: [AssignRemExpr] ...%=... # 274| 0: [VarAccess] updated -# 274| 1: [RemExpr] ... % ... -# 274| 0: [VarAccess] updated -# 274| 1: [IntegerLiteral] 1 +# 274| 1: [IntegerLiteral] 1 # 278| 12: [Method] getEnumValues #-----| 2: (Generic Parameters) # 278| 0: [TypeVariable] T diff --git a/java/ql/test-kotlin2/library-tests/exprs/binop.expected b/java/ql/test-kotlin2/library-tests/exprs/binop.expected index fc252e90fe3c..83dad7f94b51 100644 --- a/java/ql/test-kotlin2/library-tests/exprs/binop.expected +++ b/java/ql/test-kotlin2/library-tests/exprs/binop.expected @@ -123,9 +123,6 @@ | exprs.kt:261:11:261:17 | ... * ... | exprs.kt:261:11:261:12 | lx | exprs.kt:261:16:261:17 | ly | | exprs.kt:262:11:262:17 | ... * ... | exprs.kt:262:11:262:12 | dx | exprs.kt:262:16:262:17 | dy | | exprs.kt:263:11:263:17 | ... * ... | exprs.kt:263:11:263:12 | fx | exprs.kt:263:16:263:17 | fy | -| exprs.kt:272:3:272:14 | ... * ... | exprs.kt:272:3:272:9 | updated | exprs.kt:272:14:272:14 | 1 | -| exprs.kt:273:3:273:14 | ... / ... | exprs.kt:273:3:273:9 | updated | exprs.kt:273:14:273:14 | 1 | -| exprs.kt:274:3:274:14 | ... % ... | exprs.kt:274:3:274:9 | updated | exprs.kt:274:14:274:14 | 1 | | funcExprs.kt:32:35:32:42 | ... + ... | funcExprs.kt:32:35:32:38 | this | funcExprs.kt:32:42:32:42 | a | | localFunctionCalls.kt:5:25:5:29 | ... + ... | localFunctionCalls.kt:5:25:5:25 | i | localFunctionCalls.kt:5:29:5:29 | x | | samConversion.kt:2:33:2:38 | ... % ... | samConversion.kt:2:33:2:34 | it | samConversion.kt:2:38:2:38 | 2 | diff --git a/java/ql/test-kotlin2/library-tests/exprs/delegatedProperties.expected b/java/ql/test-kotlin2/library-tests/exprs/delegatedProperties.expected index a530d0ee5607..c62d740a644a 100644 --- a/java/ql/test-kotlin2/library-tests/exprs/delegatedProperties.expected +++ b/java/ql/test-kotlin2/library-tests/exprs/delegatedProperties.expected @@ -43,18 +43,18 @@ delegatedPropertyGetters | delegatedProperties.kt:33:9:33:76 | readOnly | delegatedProperties.kt:33:9:33:76 | | | delegatedProperties.kt:34:9:34:48 | readWrite | delegatedProperties.kt:34:9:34:48 | | | delegatedProperties.kt:39:9:39:51 | varResource2 | delegatedProperties.kt:39:9:39:51 | | -| delegatedProperties.kt:42:5:42:47 | varResource0 | delegatedProperties.kt:42:30:42:47 | getVarResource0 | -| delegatedProperties.kt:66:5:66:50 | delegatedToMember1 | delegatedProperties.kt:66:36:66:50 | getDelegatedToMember1 | -| delegatedProperties.kt:67:5:67:53 | delegatedToMember2 | delegatedProperties.kt:67:36:67:53 | getDelegatedToMember2 | -| delegatedProperties.kt:69:5:69:56 | delegatedToExtMember1 | delegatedProperties.kt:69:39:69:56 | getDelegatedToExtMember1 | -| delegatedProperties.kt:70:5:70:59 | delegatedToExtMember2 | delegatedProperties.kt:70:39:70:59 | getDelegatedToExtMember2 | -| delegatedProperties.kt:72:5:72:56 | delegatedToBaseClass1 | delegatedProperties.kt:72:39:72:56 | getDelegatedToBaseClass1 | -| delegatedProperties.kt:73:5:73:56 | delegatedToBaseClass2 | delegatedProperties.kt:73:39:73:56 | getDelegatedToBaseClass2 | -| delegatedProperties.kt:75:5:75:78 | delegatedToAnotherClass1 | delegatedProperties.kt:75:42:75:78 | getDelegatedToAnotherClass1 | -| delegatedProperties.kt:77:5:77:49 | delegatedToTopLevel | delegatedProperties.kt:77:37:77:49 | getDelegatedToTopLevel | -| delegatedProperties.kt:79:5:79:38 | max | delegatedProperties.kt:79:21:79:38 | getMax | +| delegatedProperties.kt:42:5:42:47 | varResource0 | delegatedProperties.kt:42:5:42:47 | getVarResource0 | +| delegatedProperties.kt:66:5:66:50 | delegatedToMember1 | delegatedProperties.kt:66:5:66:50 | getDelegatedToMember1 | +| delegatedProperties.kt:67:5:67:53 | delegatedToMember2 | delegatedProperties.kt:67:5:67:53 | getDelegatedToMember2 | +| delegatedProperties.kt:69:5:69:56 | delegatedToExtMember1 | delegatedProperties.kt:69:5:69:56 | getDelegatedToExtMember1 | +| delegatedProperties.kt:70:5:70:59 | delegatedToExtMember2 | delegatedProperties.kt:70:5:70:59 | getDelegatedToExtMember2 | +| delegatedProperties.kt:72:5:72:56 | delegatedToBaseClass1 | delegatedProperties.kt:72:5:72:56 | getDelegatedToBaseClass1 | +| delegatedProperties.kt:73:5:73:56 | delegatedToBaseClass2 | delegatedProperties.kt:73:5:73:56 | getDelegatedToBaseClass2 | +| delegatedProperties.kt:75:5:75:78 | delegatedToAnotherClass1 | delegatedProperties.kt:75:5:75:78 | getDelegatedToAnotherClass1 | +| delegatedProperties.kt:77:5:77:49 | delegatedToTopLevel | delegatedProperties.kt:77:5:77:49 | getDelegatedToTopLevel | +| delegatedProperties.kt:79:5:79:38 | max | delegatedProperties.kt:79:5:79:38 | getMax | | delegatedProperties.kt:82:9:82:54 | delegatedToMember3 | delegatedProperties.kt:82:9:82:54 | | -| delegatedProperties.kt:87:1:87:46 | extDelegated | delegatedProperties.kt:87:34:87:46 | getExtDelegated | +| delegatedProperties.kt:87:1:87:46 | extDelegated | delegatedProperties.kt:87:1:87:46 | getExtDelegated | delegatedPropertySetters | delegatedProperties.kt:19:9:19:51 | varResource1 | delegatedProperties.kt:19:9:19:51 | | | delegatedProperties.kt:34:9:34:48 | readWrite | delegatedProperties.kt:34:9:34:48 | | diff --git a/java/ql/test-kotlin2/library-tests/exprs/exprs.expected b/java/ql/test-kotlin2/library-tests/exprs/exprs.expected index 40ef48d8916b..0acb9c221430 100644 --- a/java/ql/test-kotlin2/library-tests/exprs/exprs.expected +++ b/java/ql/test-kotlin2/library-tests/exprs/exprs.expected @@ -52,6 +52,7 @@ | delegatedProperties.kt:18:12:18:33 | String | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:19:9:19:51 | Unit | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:19:9:19:51 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:19:9:19:51 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:19:9:19:51 | varResource1$delegate | delegatedProperties.kt:18:5:40:5 | fn | LocalVariableDeclExpr | | delegatedProperties.kt:19:34:19:51 | ...::... | delegatedProperties.kt:19:9:19:51 | | PropertyRefExpr | | delegatedProperties.kt:19:34:19:51 | ...::... | delegatedProperties.kt:19:9:19:51 | | PropertyRefExpr | @@ -74,7 +75,6 @@ | delegatedProperties.kt:19:34:19:51 | get(...) | delegatedProperties.kt:19:34:19:51 | invoke | MethodCall | | delegatedProperties.kt:19:34:19:51 | get(...) | delegatedProperties.kt:19:34:19:51 | invoke | MethodCall | | delegatedProperties.kt:19:34:19:51 | getValue(...) | delegatedProperties.kt:19:9:19:51 | | MethodCall | -| delegatedProperties.kt:19:34:19:51 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:19:34:19:51 | new (...) | delegatedProperties.kt:19:34:19:51 | get | ClassInstanceExpr | | delegatedProperties.kt:19:34:19:51 | new (...) | delegatedProperties.kt:19:34:19:51 | get | ClassInstanceExpr | | delegatedProperties.kt:19:34:19:51 | new (...) | delegatedProperties.kt:19:34:19:51 | set | ClassInstanceExpr | @@ -116,18 +116,18 @@ | delegatedProperties.kt:25:64:31:9 | | delegatedProperties.kt:25:9:31:9 | resourceDelegate | StmtExpr | | delegatedProperties.kt:25:64:31:9 | ReadWriteProperty | delegatedProperties.kt:25:9:31:9 | resourceDelegate | TypeAccess | | delegatedProperties.kt:25:64:31:9 | new (...) | delegatedProperties.kt:25:9:31:9 | resourceDelegate | ClassInstanceExpr | +| delegatedProperties.kt:26:13:26:24 | ...=... | delegatedProperties.kt:26:13:26:24 | setCurValue | AssignExpr | +| delegatedProperties.kt:26:13:26:24 | | delegatedProperties.kt:26:13:26:24 | setCurValue | VarAccess | +| delegatedProperties.kt:26:13:26:24 | Unit | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:26:13:26:24 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:26:13:26:24 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:26:13:26:24 | this | delegatedProperties.kt:26:13:26:24 | getCurValue | ThisAccess | +| delegatedProperties.kt:26:13:26:24 | this | delegatedProperties.kt:26:13:26:24 | setCurValue | ThisAccess | +| delegatedProperties.kt:26:13:26:24 | this.curValue | delegatedProperties.kt:26:13:26:24 | getCurValue | VarAccess | +| delegatedProperties.kt:26:13:26:24 | this.curValue | delegatedProperties.kt:26:13:26:24 | setCurValue | VarAccess | | delegatedProperties.kt:26:13:26:28 | ...=... | delegatedProperties.kt:25:64:31:9 | | KtInitializerAssignExpr | -| delegatedProperties.kt:26:13:26:28 | ...=... | delegatedProperties.kt:26:13:26:28 | setCurValue | AssignExpr | -| delegatedProperties.kt:26:13:26:28 | | delegatedProperties.kt:26:13:26:28 | setCurValue | VarAccess | -| delegatedProperties.kt:26:13:26:28 | Unit | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:26:13:26:28 | curValue | delegatedProperties.kt:25:64:31:9 | | VarAccess | | delegatedProperties.kt:26:13:26:28 | int | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:26:13:26:28 | int | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:26:13:26:28 | int | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:26:13:26:28 | this | delegatedProperties.kt:26:13:26:28 | getCurValue | ThisAccess | -| delegatedProperties.kt:26:13:26:28 | this | delegatedProperties.kt:26:13:26:28 | setCurValue | ThisAccess | -| delegatedProperties.kt:26:13:26:28 | this.curValue | delegatedProperties.kt:26:13:26:28 | getCurValue | VarAccess | -| delegatedProperties.kt:26:13:26:28 | this.curValue | delegatedProperties.kt:26:13:26:28 | setCurValue | VarAccess | | delegatedProperties.kt:26:28:26:28 | 0 | delegatedProperties.kt:25:64:31:9 | | IntegerLiteral | | delegatedProperties.kt:27:13:27:88 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:27:35:27:47 | Object | file://:0:0:0:0 | | TypeAccess | @@ -160,6 +160,7 @@ | delegatedProperties.kt:33:30:33:47 | this | delegatedProperties.kt:33:30:33:47 | invoke | ThisAccess | | delegatedProperties.kt:34:9:34:48 | Unit | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:34:9:34:48 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:34:9:34:48 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:34:9:34:48 | readWrite$delegate | delegatedProperties.kt:18:5:40:5 | fn | LocalVariableDeclExpr | | delegatedProperties.kt:34:31:34:48 | ...::... | delegatedProperties.kt:34:9:34:48 | | PropertyRefExpr | | delegatedProperties.kt:34:31:34:48 | ...::... | delegatedProperties.kt:34:9:34:48 | | PropertyRefExpr | @@ -182,7 +183,6 @@ | delegatedProperties.kt:34:31:34:48 | get(...) | delegatedProperties.kt:34:31:34:48 | invoke | MethodCall | | delegatedProperties.kt:34:31:34:48 | get(...) | delegatedProperties.kt:34:31:34:48 | invoke | MethodCall | | delegatedProperties.kt:34:31:34:48 | getValue(...) | delegatedProperties.kt:34:9:34:48 | | MethodCall | -| delegatedProperties.kt:34:31:34:48 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:34:31:34:48 | new (...) | delegatedProperties.kt:18:5:40:5 | fn | ClassInstanceExpr | | delegatedProperties.kt:34:31:34:48 | new (...) | delegatedProperties.kt:34:31:34:48 | get | ClassInstanceExpr | | delegatedProperties.kt:34:31:34:48 | new (...) | delegatedProperties.kt:34:31:34:48 | get | ClassInstanceExpr | @@ -225,16 +225,18 @@ | delegatedProperties.kt:39:34:39:51 | this | delegatedProperties.kt:39:34:39:51 | invoke | ThisAccess | | delegatedProperties.kt:39:34:39:51 | varResource2$delegate | delegatedProperties.kt:39:9:39:51 | | VarAccess | | delegatedProperties.kt:42:5:42:47 | Unit | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:42:5:42:47 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:42:5:42:47 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:42:30:42:47 | ...::... | delegatedProperties.kt:42:5:42:47 | getVarResource0 | PropertyRefExpr | | delegatedProperties.kt:42:30:42:47 | ...::... | delegatedProperties.kt:42:5:42:47 | setVarResource0 | PropertyRefExpr | -| delegatedProperties.kt:42:30:42:47 | ...::... | delegatedProperties.kt:42:30:42:47 | getVarResource0 | PropertyRefExpr | | delegatedProperties.kt:42:30:42:47 | ...=... | delegatedProperties.kt:17:1:43:1 | Owner | KtInitializerAssignExpr | | delegatedProperties.kt:42:30:42:47 | | delegatedProperties.kt:42:5:42:47 | setVarResource0 | VarAccess | +| delegatedProperties.kt:42:30:42:47 | Integer | delegatedProperties.kt:42:5:42:47 | getVarResource0 | TypeAccess | | delegatedProperties.kt:42:30:42:47 | Integer | delegatedProperties.kt:42:5:42:47 | setVarResource0 | TypeAccess | -| delegatedProperties.kt:42:30:42:47 | Integer | delegatedProperties.kt:42:30:42:47 | getVarResource0 | TypeAccess | +| delegatedProperties.kt:42:30:42:47 | KMutableProperty1 | delegatedProperties.kt:42:5:42:47 | getVarResource0 | TypeAccess | | delegatedProperties.kt:42:30:42:47 | KMutableProperty1 | delegatedProperties.kt:42:5:42:47 | setVarResource0 | TypeAccess | -| delegatedProperties.kt:42:30:42:47 | KMutableProperty1 | delegatedProperties.kt:42:30:42:47 | getVarResource0 | TypeAccess | +| delegatedProperties.kt:42:30:42:47 | Owner | delegatedProperties.kt:42:5:42:47 | getVarResource0 | TypeAccess | | delegatedProperties.kt:42:30:42:47 | Owner | delegatedProperties.kt:42:5:42:47 | setVarResource0 | TypeAccess | -| delegatedProperties.kt:42:30:42:47 | Owner | delegatedProperties.kt:42:30:42:47 | getVarResource0 | TypeAccess | | delegatedProperties.kt:42:30:42:47 | ResourceDelegate | delegatedProperties.kt:17:1:43:1 | Owner | TypeAccess | | delegatedProperties.kt:42:30:42:47 | ResourceDelegate | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:42:30:42:47 | a0 | delegatedProperties.kt:42:30:42:47 | get | VarAccess | @@ -247,23 +249,21 @@ | delegatedProperties.kt:42:30:42:47 | a1 | delegatedProperties.kt:42:30:42:47 | set | VarAccess | | delegatedProperties.kt:42:30:42:47 | get(...) | delegatedProperties.kt:42:30:42:47 | invoke | MethodCall | | delegatedProperties.kt:42:30:42:47 | get(...) | delegatedProperties.kt:42:30:42:47 | invoke | MethodCall | -| delegatedProperties.kt:42:30:42:47 | getValue(...) | delegatedProperties.kt:42:30:42:47 | getVarResource0 | MethodCall | +| delegatedProperties.kt:42:30:42:47 | getValue(...) | delegatedProperties.kt:42:5:42:47 | getVarResource0 | MethodCall | | delegatedProperties.kt:42:30:42:47 | getVarResource0(...) | delegatedProperties.kt:42:30:42:47 | get | MethodCall | | delegatedProperties.kt:42:30:42:47 | getVarResource0(...) | delegatedProperties.kt:42:30:42:47 | get | MethodCall | -| delegatedProperties.kt:42:30:42:47 | int | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:42:30:42:47 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:42:30:42:47 | new ResourceDelegate(...) | delegatedProperties.kt:17:1:43:1 | Owner | ClassInstanceExpr | | delegatedProperties.kt:42:30:42:47 | setValue(...) | delegatedProperties.kt:42:5:42:47 | setVarResource0 | MethodCall | | delegatedProperties.kt:42:30:42:47 | setVarResource0(...) | delegatedProperties.kt:42:30:42:47 | set | MethodCall | | delegatedProperties.kt:42:30:42:47 | setVarResource0(...) | delegatedProperties.kt:42:30:42:47 | set | MethodCall | +| delegatedProperties.kt:42:30:42:47 | this | delegatedProperties.kt:42:5:42:47 | getVarResource0 | ThisAccess | +| delegatedProperties.kt:42:30:42:47 | this | delegatedProperties.kt:42:5:42:47 | getVarResource0 | ThisAccess | | delegatedProperties.kt:42:30:42:47 | this | delegatedProperties.kt:42:5:42:47 | setVarResource0 | ThisAccess | | delegatedProperties.kt:42:30:42:47 | this | delegatedProperties.kt:42:5:42:47 | setVarResource0 | ThisAccess | -| delegatedProperties.kt:42:30:42:47 | this | delegatedProperties.kt:42:30:42:47 | getVarResource0 | ThisAccess | -| delegatedProperties.kt:42:30:42:47 | this | delegatedProperties.kt:42:30:42:47 | getVarResource0 | ThisAccess | | delegatedProperties.kt:42:30:42:47 | this | delegatedProperties.kt:42:30:42:47 | invoke | ThisAccess | | delegatedProperties.kt:42:30:42:47 | this | delegatedProperties.kt:42:30:42:47 | invoke | ThisAccess | +| delegatedProperties.kt:42:30:42:47 | this.varResource0$delegate | delegatedProperties.kt:42:5:42:47 | getVarResource0 | VarAccess | | delegatedProperties.kt:42:30:42:47 | this.varResource0$delegate | delegatedProperties.kt:42:5:42:47 | setVarResource0 | VarAccess | -| delegatedProperties.kt:42:30:42:47 | this.varResource0$delegate | delegatedProperties.kt:42:30:42:47 | getVarResource0 | VarAccess | | delegatedProperties.kt:42:30:42:47 | varResource0$delegate | delegatedProperties.kt:17:1:43:1 | Owner | VarAccess | | delegatedProperties.kt:46:5:48:5 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:46:27:46:41 | Owner | file://:0:0:0:0 | | TypeAccess | @@ -281,18 +281,18 @@ | delegatedProperties.kt:54:51:54:68 | KProperty | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:56:16:56:33 | ResourceDelegate | delegatedProperties.kt:54:5:57:5 | provideDelegate | TypeAccess | | delegatedProperties.kt:56:16:56:33 | new ResourceDelegate(...) | delegatedProperties.kt:54:5:57:5 | provideDelegate | ClassInstanceExpr | +| delegatedProperties.kt:60:1:60:20 | ...=... | delegatedProperties.kt:60:1:60:20 | setTopLevelInt | AssignExpr | +| delegatedProperties.kt:60:1:60:20 | | delegatedProperties.kt:60:1:60:20 | setTopLevelInt | VarAccess | +| delegatedProperties.kt:60:1:60:20 | DelegatedPropertiesKt | delegatedProperties.kt:60:1:60:20 | getTopLevelInt | TypeAccess | +| delegatedProperties.kt:60:1:60:20 | DelegatedPropertiesKt | delegatedProperties.kt:60:1:60:20 | setTopLevelInt | TypeAccess | +| delegatedProperties.kt:60:1:60:20 | DelegatedPropertiesKt.topLevelInt | delegatedProperties.kt:60:1:60:20 | getTopLevelInt | VarAccess | +| delegatedProperties.kt:60:1:60:20 | DelegatedPropertiesKt.topLevelInt | delegatedProperties.kt:60:1:60:20 | setTopLevelInt | VarAccess | +| delegatedProperties.kt:60:1:60:20 | Unit | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:60:1:60:20 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:60:1:60:20 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:60:1:60:24 | ...=... | delegatedProperties.kt:0:0:0:0 | | KtInitializerAssignExpr | -| delegatedProperties.kt:60:1:60:24 | ...=... | delegatedProperties.kt:60:1:60:24 | setTopLevelInt | AssignExpr | -| delegatedProperties.kt:60:1:60:24 | | delegatedProperties.kt:60:1:60:24 | setTopLevelInt | VarAccess | | delegatedProperties.kt:60:1:60:24 | DelegatedPropertiesKt | delegatedProperties.kt:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:60:1:60:24 | DelegatedPropertiesKt | delegatedProperties.kt:60:1:60:24 | getTopLevelInt | TypeAccess | -| delegatedProperties.kt:60:1:60:24 | DelegatedPropertiesKt | delegatedProperties.kt:60:1:60:24 | setTopLevelInt | TypeAccess | | delegatedProperties.kt:60:1:60:24 | DelegatedPropertiesKt.topLevelInt | delegatedProperties.kt:0:0:0:0 | | VarAccess | -| delegatedProperties.kt:60:1:60:24 | DelegatedPropertiesKt.topLevelInt | delegatedProperties.kt:60:1:60:24 | getTopLevelInt | VarAccess | -| delegatedProperties.kt:60:1:60:24 | DelegatedPropertiesKt.topLevelInt | delegatedProperties.kt:60:1:60:24 | setTopLevelInt | VarAccess | -| delegatedProperties.kt:60:1:60:24 | Unit | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:60:1:60:24 | int | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:60:1:60:24 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:60:1:60:24 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:60:24:60:24 | 0 | delegatedProperties.kt:0:0:0:0 | | IntegerLiteral | | delegatedProperties.kt:62:25:62:48 | ...=... | delegatedProperties.kt:62:24:62:49 | ClassWithDelegate | KtInitializerAssignExpr | @@ -335,30 +335,32 @@ | delegatedProperties.kt:65:35:65:77 | this.anotherClassInstance | delegatedProperties.kt:65:35:65:77 | getAnotherClassInstance | VarAccess | | delegatedProperties.kt:65:87:65:95 | memberInt | delegatedProperties.kt:65:14:65:78 | MyClass | VarAccess | | delegatedProperties.kt:66:5:66:50 | Unit | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:66:5:66:50 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:66:5:66:50 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:66:36:66:39 | MyClass | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | | delegatedProperties.kt:66:36:66:39 | MyClass.this | delegatedProperties.kt:65:14:65:78 | MyClass | ThisAccess | | delegatedProperties.kt:66:36:66:50 | ...::... | delegatedProperties.kt:65:14:65:78 | MyClass | PropertyRefExpr | +| delegatedProperties.kt:66:36:66:50 | ...::... | delegatedProperties.kt:66:5:66:50 | getDelegatedToMember1 | PropertyRefExpr | | delegatedProperties.kt:66:36:66:50 | ...::... | delegatedProperties.kt:66:5:66:50 | setDelegatedToMember1 | PropertyRefExpr | -| delegatedProperties.kt:66:36:66:50 | ...::... | delegatedProperties.kt:66:36:66:50 | getDelegatedToMember1 | PropertyRefExpr | | delegatedProperties.kt:66:36:66:50 | ...=... | delegatedProperties.kt:65:14:65:78 | MyClass | KtInitializerAssignExpr | | delegatedProperties.kt:66:36:66:50 | ...=... | delegatedProperties.kt:66:36:66:50 | | AssignExpr | | delegatedProperties.kt:66:36:66:50 | | delegatedProperties.kt:66:36:66:50 | | VarAccess | | delegatedProperties.kt:66:36:66:50 | | delegatedProperties.kt:66:5:66:50 | setDelegatedToMember1 | VarAccess | | delegatedProperties.kt:66:36:66:50 | Integer | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | +| delegatedProperties.kt:66:36:66:50 | Integer | delegatedProperties.kt:66:5:66:50 | getDelegatedToMember1 | TypeAccess | +| delegatedProperties.kt:66:36:66:50 | Integer | delegatedProperties.kt:66:5:66:50 | getDelegatedToMember1 | TypeAccess | | delegatedProperties.kt:66:36:66:50 | Integer | delegatedProperties.kt:66:5:66:50 | setDelegatedToMember1 | TypeAccess | | delegatedProperties.kt:66:36:66:50 | Integer | delegatedProperties.kt:66:5:66:50 | setDelegatedToMember1 | TypeAccess | -| delegatedProperties.kt:66:36:66:50 | Integer | delegatedProperties.kt:66:36:66:50 | getDelegatedToMember1 | TypeAccess | -| delegatedProperties.kt:66:36:66:50 | Integer | delegatedProperties.kt:66:36:66:50 | getDelegatedToMember1 | TypeAccess | | delegatedProperties.kt:66:36:66:50 | Integer | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:66:36:66:50 | KMutableProperty0 | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | | delegatedProperties.kt:66:36:66:50 | KMutableProperty0 | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:66:36:66:50 | KMutableProperty1 | delegatedProperties.kt:66:5:66:50 | getDelegatedToMember1 | TypeAccess | | delegatedProperties.kt:66:36:66:50 | KMutableProperty1 | delegatedProperties.kt:66:5:66:50 | setDelegatedToMember1 | TypeAccess | -| delegatedProperties.kt:66:36:66:50 | KMutableProperty1 | delegatedProperties.kt:66:36:66:50 | getDelegatedToMember1 | TypeAccess | +| delegatedProperties.kt:66:36:66:50 | MyClass | delegatedProperties.kt:66:5:66:50 | getDelegatedToMember1 | TypeAccess | | delegatedProperties.kt:66:36:66:50 | MyClass | delegatedProperties.kt:66:5:66:50 | setDelegatedToMember1 | TypeAccess | -| delegatedProperties.kt:66:36:66:50 | MyClass | delegatedProperties.kt:66:36:66:50 | getDelegatedToMember1 | TypeAccess | | delegatedProperties.kt:66:36:66:50 | MyClass | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:66:36:66:50 | PropertyReferenceDelegatesKt | delegatedProperties.kt:66:5:66:50 | getDelegatedToMember1 | TypeAccess | | delegatedProperties.kt:66:36:66:50 | PropertyReferenceDelegatesKt | delegatedProperties.kt:66:5:66:50 | setDelegatedToMember1 | TypeAccess | -| delegatedProperties.kt:66:36:66:50 | PropertyReferenceDelegatesKt | delegatedProperties.kt:66:36:66:50 | getDelegatedToMember1 | TypeAccess | | delegatedProperties.kt:66:36:66:50 | a0 | delegatedProperties.kt:66:36:66:50 | get | VarAccess | | delegatedProperties.kt:66:36:66:50 | a0 | delegatedProperties.kt:66:36:66:50 | get | VarAccess | | delegatedProperties.kt:66:36:66:50 | a0 | delegatedProperties.kt:66:36:66:50 | invoke | VarAccess | @@ -375,19 +377,17 @@ | delegatedProperties.kt:66:36:66:50 | getDelegatedToMember1(...) | delegatedProperties.kt:66:36:66:50 | get | MethodCall | | delegatedProperties.kt:66:36:66:50 | getDelegatedToMember1(...) | delegatedProperties.kt:66:36:66:50 | get | MethodCall | | delegatedProperties.kt:66:36:66:50 | getMemberInt(...) | delegatedProperties.kt:66:36:66:50 | get | MethodCall | -| delegatedProperties.kt:66:36:66:50 | getValue(...) | delegatedProperties.kt:66:36:66:50 | getDelegatedToMember1 | MethodCall | -| delegatedProperties.kt:66:36:66:50 | int | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:66:36:66:50 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:66:36:66:50 | getValue(...) | delegatedProperties.kt:66:5:66:50 | getDelegatedToMember1 | MethodCall | | delegatedProperties.kt:66:36:66:50 | setDelegatedToMember1(...) | delegatedProperties.kt:66:36:66:50 | set | MethodCall | | delegatedProperties.kt:66:36:66:50 | setDelegatedToMember1(...) | delegatedProperties.kt:66:36:66:50 | set | MethodCall | | delegatedProperties.kt:66:36:66:50 | setMemberInt(...) | delegatedProperties.kt:66:36:66:50 | set | MethodCall | | delegatedProperties.kt:66:36:66:50 | setValue(...) | delegatedProperties.kt:66:5:66:50 | setDelegatedToMember1 | MethodCall | +| delegatedProperties.kt:66:36:66:50 | this | delegatedProperties.kt:66:5:66:50 | getDelegatedToMember1 | ThisAccess | +| delegatedProperties.kt:66:36:66:50 | this | delegatedProperties.kt:66:5:66:50 | getDelegatedToMember1 | ThisAccess | | delegatedProperties.kt:66:36:66:50 | this | delegatedProperties.kt:66:5:66:50 | setDelegatedToMember1 | ThisAccess | | delegatedProperties.kt:66:36:66:50 | this | delegatedProperties.kt:66:5:66:50 | setDelegatedToMember1 | ThisAccess | | delegatedProperties.kt:66:36:66:50 | this | delegatedProperties.kt:66:36:66:50 | | ThisAccess | | delegatedProperties.kt:66:36:66:50 | this | delegatedProperties.kt:66:36:66:50 | get | ThisAccess | -| delegatedProperties.kt:66:36:66:50 | this | delegatedProperties.kt:66:36:66:50 | getDelegatedToMember1 | ThisAccess | -| delegatedProperties.kt:66:36:66:50 | this | delegatedProperties.kt:66:36:66:50 | getDelegatedToMember1 | ThisAccess | | delegatedProperties.kt:66:36:66:50 | this | delegatedProperties.kt:66:36:66:50 | invoke | ThisAccess | | delegatedProperties.kt:66:36:66:50 | this | delegatedProperties.kt:66:36:66:50 | invoke | ThisAccess | | delegatedProperties.kt:66:36:66:50 | this | delegatedProperties.kt:66:36:66:50 | invoke | ThisAccess | @@ -395,32 +395,34 @@ | delegatedProperties.kt:66:36:66:50 | this. | delegatedProperties.kt:66:36:66:50 | | VarAccess | | delegatedProperties.kt:66:36:66:50 | this. | delegatedProperties.kt:66:36:66:50 | get | VarAccess | | delegatedProperties.kt:66:36:66:50 | this. | delegatedProperties.kt:66:36:66:50 | set | VarAccess | +| delegatedProperties.kt:66:36:66:50 | this.delegatedToMember1$delegate | delegatedProperties.kt:66:5:66:50 | getDelegatedToMember1 | VarAccess | | delegatedProperties.kt:66:36:66:50 | this.delegatedToMember1$delegate | delegatedProperties.kt:66:5:66:50 | setDelegatedToMember1 | VarAccess | -| delegatedProperties.kt:66:36:66:50 | this.delegatedToMember1$delegate | delegatedProperties.kt:66:36:66:50 | getDelegatedToMember1 | VarAccess | | delegatedProperties.kt:67:5:67:53 | Unit | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:67:5:67:53 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:67:5:67:53 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:67:36:67:53 | ...::... | delegatedProperties.kt:65:14:65:78 | MyClass | PropertyRefExpr | +| delegatedProperties.kt:67:36:67:53 | ...::... | delegatedProperties.kt:67:5:67:53 | getDelegatedToMember2 | PropertyRefExpr | | delegatedProperties.kt:67:36:67:53 | ...::... | delegatedProperties.kt:67:5:67:53 | setDelegatedToMember2 | PropertyRefExpr | -| delegatedProperties.kt:67:36:67:53 | ...::... | delegatedProperties.kt:67:36:67:53 | getDelegatedToMember2 | PropertyRefExpr | | delegatedProperties.kt:67:36:67:53 | ...=... | delegatedProperties.kt:65:14:65:78 | MyClass | KtInitializerAssignExpr | | delegatedProperties.kt:67:36:67:53 | | delegatedProperties.kt:67:5:67:53 | setDelegatedToMember2 | VarAccess | | delegatedProperties.kt:67:36:67:53 | Integer | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | +| delegatedProperties.kt:67:36:67:53 | Integer | delegatedProperties.kt:67:5:67:53 | getDelegatedToMember2 | TypeAccess | +| delegatedProperties.kt:67:36:67:53 | Integer | delegatedProperties.kt:67:5:67:53 | getDelegatedToMember2 | TypeAccess | | delegatedProperties.kt:67:36:67:53 | Integer | delegatedProperties.kt:67:5:67:53 | setDelegatedToMember2 | TypeAccess | | delegatedProperties.kt:67:36:67:53 | Integer | delegatedProperties.kt:67:5:67:53 | setDelegatedToMember2 | TypeAccess | -| delegatedProperties.kt:67:36:67:53 | Integer | delegatedProperties.kt:67:36:67:53 | getDelegatedToMember2 | TypeAccess | -| delegatedProperties.kt:67:36:67:53 | Integer | delegatedProperties.kt:67:36:67:53 | getDelegatedToMember2 | TypeAccess | | delegatedProperties.kt:67:36:67:53 | Integer | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:67:36:67:53 | KMutableProperty1 | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | +| delegatedProperties.kt:67:36:67:53 | KMutableProperty1 | delegatedProperties.kt:67:5:67:53 | getDelegatedToMember2 | TypeAccess | | delegatedProperties.kt:67:36:67:53 | KMutableProperty1 | delegatedProperties.kt:67:5:67:53 | setDelegatedToMember2 | TypeAccess | -| delegatedProperties.kt:67:36:67:53 | KMutableProperty1 | delegatedProperties.kt:67:36:67:53 | getDelegatedToMember2 | TypeAccess | | delegatedProperties.kt:67:36:67:53 | KMutableProperty1 | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:67:36:67:53 | MyClass | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | +| delegatedProperties.kt:67:36:67:53 | MyClass | delegatedProperties.kt:67:5:67:53 | getDelegatedToMember2 | TypeAccess | +| delegatedProperties.kt:67:36:67:53 | MyClass | delegatedProperties.kt:67:5:67:53 | getDelegatedToMember2 | TypeAccess | | delegatedProperties.kt:67:36:67:53 | MyClass | delegatedProperties.kt:67:5:67:53 | setDelegatedToMember2 | TypeAccess | | delegatedProperties.kt:67:36:67:53 | MyClass | delegatedProperties.kt:67:5:67:53 | setDelegatedToMember2 | TypeAccess | -| delegatedProperties.kt:67:36:67:53 | MyClass | delegatedProperties.kt:67:36:67:53 | getDelegatedToMember2 | TypeAccess | -| delegatedProperties.kt:67:36:67:53 | MyClass | delegatedProperties.kt:67:36:67:53 | getDelegatedToMember2 | TypeAccess | | delegatedProperties.kt:67:36:67:53 | MyClass | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:67:36:67:53 | PropertyReferenceDelegatesKt | delegatedProperties.kt:67:5:67:53 | getDelegatedToMember2 | TypeAccess | | delegatedProperties.kt:67:36:67:53 | PropertyReferenceDelegatesKt | delegatedProperties.kt:67:5:67:53 | setDelegatedToMember2 | TypeAccess | -| delegatedProperties.kt:67:36:67:53 | PropertyReferenceDelegatesKt | delegatedProperties.kt:67:36:67:53 | getDelegatedToMember2 | TypeAccess | | delegatedProperties.kt:67:36:67:53 | a0 | delegatedProperties.kt:67:36:67:53 | get | VarAccess | | delegatedProperties.kt:67:36:67:53 | a0 | delegatedProperties.kt:67:36:67:53 | get | VarAccess | | delegatedProperties.kt:67:36:67:53 | a0 | delegatedProperties.kt:67:36:67:53 | get | VarAccess | @@ -440,28 +442,28 @@ | delegatedProperties.kt:67:36:67:53 | getDelegatedToMember2(...) | delegatedProperties.kt:67:36:67:53 | get | MethodCall | | delegatedProperties.kt:67:36:67:53 | getDelegatedToMember2(...) | delegatedProperties.kt:67:36:67:53 | get | MethodCall | | delegatedProperties.kt:67:36:67:53 | getMemberInt(...) | delegatedProperties.kt:67:36:67:53 | get | MethodCall | -| delegatedProperties.kt:67:36:67:53 | getValue(...) | delegatedProperties.kt:67:36:67:53 | getDelegatedToMember2 | MethodCall | -| delegatedProperties.kt:67:36:67:53 | int | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:67:36:67:53 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:67:36:67:53 | getValue(...) | delegatedProperties.kt:67:5:67:53 | getDelegatedToMember2 | MethodCall | | delegatedProperties.kt:67:36:67:53 | setDelegatedToMember2(...) | delegatedProperties.kt:67:36:67:53 | set | MethodCall | | delegatedProperties.kt:67:36:67:53 | setDelegatedToMember2(...) | delegatedProperties.kt:67:36:67:53 | set | MethodCall | | delegatedProperties.kt:67:36:67:53 | setMemberInt(...) | delegatedProperties.kt:67:36:67:53 | set | MethodCall | | delegatedProperties.kt:67:36:67:53 | setValue(...) | delegatedProperties.kt:67:5:67:53 | setDelegatedToMember2 | MethodCall | +| delegatedProperties.kt:67:36:67:53 | this | delegatedProperties.kt:67:5:67:53 | getDelegatedToMember2 | ThisAccess | +| delegatedProperties.kt:67:36:67:53 | this | delegatedProperties.kt:67:5:67:53 | getDelegatedToMember2 | ThisAccess | | delegatedProperties.kt:67:36:67:53 | this | delegatedProperties.kt:67:5:67:53 | setDelegatedToMember2 | ThisAccess | | delegatedProperties.kt:67:36:67:53 | this | delegatedProperties.kt:67:5:67:53 | setDelegatedToMember2 | ThisAccess | -| delegatedProperties.kt:67:36:67:53 | this | delegatedProperties.kt:67:36:67:53 | getDelegatedToMember2 | ThisAccess | -| delegatedProperties.kt:67:36:67:53 | this | delegatedProperties.kt:67:36:67:53 | getDelegatedToMember2 | ThisAccess | | delegatedProperties.kt:67:36:67:53 | this | delegatedProperties.kt:67:36:67:53 | invoke | ThisAccess | | delegatedProperties.kt:67:36:67:53 | this | delegatedProperties.kt:67:36:67:53 | invoke | ThisAccess | | delegatedProperties.kt:67:36:67:53 | this | delegatedProperties.kt:67:36:67:53 | invoke | ThisAccess | +| delegatedProperties.kt:67:36:67:53 | this.delegatedToMember2$delegate | delegatedProperties.kt:67:5:67:53 | getDelegatedToMember2 | VarAccess | | delegatedProperties.kt:67:36:67:53 | this.delegatedToMember2$delegate | delegatedProperties.kt:67:5:67:53 | setDelegatedToMember2 | VarAccess | -| delegatedProperties.kt:67:36:67:53 | this.delegatedToMember2$delegate | delegatedProperties.kt:67:36:67:53 | getDelegatedToMember2 | VarAccess | | delegatedProperties.kt:69:5:69:56 | Unit | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:69:5:69:56 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:69:5:69:56 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:69:39:69:42 | MyClass | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | | delegatedProperties.kt:69:39:69:42 | MyClass.this | delegatedProperties.kt:65:14:65:78 | MyClass | ThisAccess | | delegatedProperties.kt:69:39:69:56 | ...::... | delegatedProperties.kt:65:14:65:78 | MyClass | PropertyRefExpr | +| delegatedProperties.kt:69:39:69:56 | ...::... | delegatedProperties.kt:69:5:69:56 | getDelegatedToExtMember1 | PropertyRefExpr | | delegatedProperties.kt:69:39:69:56 | ...::... | delegatedProperties.kt:69:5:69:56 | setDelegatedToExtMember1 | PropertyRefExpr | -| delegatedProperties.kt:69:39:69:56 | ...::... | delegatedProperties.kt:69:39:69:56 | getDelegatedToExtMember1 | PropertyRefExpr | | delegatedProperties.kt:69:39:69:56 | ...=... | delegatedProperties.kt:65:14:65:78 | MyClass | KtInitializerAssignExpr | | delegatedProperties.kt:69:39:69:56 | ...=... | delegatedProperties.kt:69:39:69:56 | | AssignExpr | | delegatedProperties.kt:69:39:69:56 | | delegatedProperties.kt:69:39:69:56 | | VarAccess | @@ -469,20 +471,20 @@ | delegatedProperties.kt:69:39:69:56 | DelegatedPropertiesKt | delegatedProperties.kt:69:39:69:56 | get | TypeAccess | | delegatedProperties.kt:69:39:69:56 | DelegatedPropertiesKt | delegatedProperties.kt:69:39:69:56 | set | TypeAccess | | delegatedProperties.kt:69:39:69:56 | Integer | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | +| delegatedProperties.kt:69:39:69:56 | Integer | delegatedProperties.kt:69:5:69:56 | getDelegatedToExtMember1 | TypeAccess | +| delegatedProperties.kt:69:39:69:56 | Integer | delegatedProperties.kt:69:5:69:56 | getDelegatedToExtMember1 | TypeAccess | | delegatedProperties.kt:69:39:69:56 | Integer | delegatedProperties.kt:69:5:69:56 | setDelegatedToExtMember1 | TypeAccess | | delegatedProperties.kt:69:39:69:56 | Integer | delegatedProperties.kt:69:5:69:56 | setDelegatedToExtMember1 | TypeAccess | -| delegatedProperties.kt:69:39:69:56 | Integer | delegatedProperties.kt:69:39:69:56 | getDelegatedToExtMember1 | TypeAccess | -| delegatedProperties.kt:69:39:69:56 | Integer | delegatedProperties.kt:69:39:69:56 | getDelegatedToExtMember1 | TypeAccess | | delegatedProperties.kt:69:39:69:56 | Integer | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:69:39:69:56 | KMutableProperty0 | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | | delegatedProperties.kt:69:39:69:56 | KMutableProperty0 | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:69:39:69:56 | KMutableProperty1 | delegatedProperties.kt:69:5:69:56 | getDelegatedToExtMember1 | TypeAccess | | delegatedProperties.kt:69:39:69:56 | KMutableProperty1 | delegatedProperties.kt:69:5:69:56 | setDelegatedToExtMember1 | TypeAccess | -| delegatedProperties.kt:69:39:69:56 | KMutableProperty1 | delegatedProperties.kt:69:39:69:56 | getDelegatedToExtMember1 | TypeAccess | +| delegatedProperties.kt:69:39:69:56 | MyClass | delegatedProperties.kt:69:5:69:56 | getDelegatedToExtMember1 | TypeAccess | | delegatedProperties.kt:69:39:69:56 | MyClass | delegatedProperties.kt:69:5:69:56 | setDelegatedToExtMember1 | TypeAccess | -| delegatedProperties.kt:69:39:69:56 | MyClass | delegatedProperties.kt:69:39:69:56 | getDelegatedToExtMember1 | TypeAccess | | delegatedProperties.kt:69:39:69:56 | MyClass | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:69:39:69:56 | PropertyReferenceDelegatesKt | delegatedProperties.kt:69:5:69:56 | getDelegatedToExtMember1 | TypeAccess | | delegatedProperties.kt:69:39:69:56 | PropertyReferenceDelegatesKt | delegatedProperties.kt:69:5:69:56 | setDelegatedToExtMember1 | TypeAccess | -| delegatedProperties.kt:69:39:69:56 | PropertyReferenceDelegatesKt | delegatedProperties.kt:69:39:69:56 | getDelegatedToExtMember1 | TypeAccess | | delegatedProperties.kt:69:39:69:56 | a0 | delegatedProperties.kt:69:39:69:56 | get | VarAccess | | delegatedProperties.kt:69:39:69:56 | a0 | delegatedProperties.kt:69:39:69:56 | get | VarAccess | | delegatedProperties.kt:69:39:69:56 | a0 | delegatedProperties.kt:69:39:69:56 | invoke | VarAccess | @@ -499,19 +501,17 @@ | delegatedProperties.kt:69:39:69:56 | getDelegatedToExtMember1(...) | delegatedProperties.kt:69:39:69:56 | get | MethodCall | | delegatedProperties.kt:69:39:69:56 | getDelegatedToExtMember1(...) | delegatedProperties.kt:69:39:69:56 | get | MethodCall | | delegatedProperties.kt:69:39:69:56 | getExtDelegated(...) | delegatedProperties.kt:69:39:69:56 | get | MethodCall | -| delegatedProperties.kt:69:39:69:56 | getValue(...) | delegatedProperties.kt:69:39:69:56 | getDelegatedToExtMember1 | MethodCall | -| delegatedProperties.kt:69:39:69:56 | int | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:69:39:69:56 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:69:39:69:56 | getValue(...) | delegatedProperties.kt:69:5:69:56 | getDelegatedToExtMember1 | MethodCall | | delegatedProperties.kt:69:39:69:56 | setDelegatedToExtMember1(...) | delegatedProperties.kt:69:39:69:56 | set | MethodCall | | delegatedProperties.kt:69:39:69:56 | setDelegatedToExtMember1(...) | delegatedProperties.kt:69:39:69:56 | set | MethodCall | | delegatedProperties.kt:69:39:69:56 | setExtDelegated(...) | delegatedProperties.kt:69:39:69:56 | set | MethodCall | | delegatedProperties.kt:69:39:69:56 | setValue(...) | delegatedProperties.kt:69:5:69:56 | setDelegatedToExtMember1 | MethodCall | +| delegatedProperties.kt:69:39:69:56 | this | delegatedProperties.kt:69:5:69:56 | getDelegatedToExtMember1 | ThisAccess | +| delegatedProperties.kt:69:39:69:56 | this | delegatedProperties.kt:69:5:69:56 | getDelegatedToExtMember1 | ThisAccess | | delegatedProperties.kt:69:39:69:56 | this | delegatedProperties.kt:69:5:69:56 | setDelegatedToExtMember1 | ThisAccess | | delegatedProperties.kt:69:39:69:56 | this | delegatedProperties.kt:69:5:69:56 | setDelegatedToExtMember1 | ThisAccess | | delegatedProperties.kt:69:39:69:56 | this | delegatedProperties.kt:69:39:69:56 | | ThisAccess | | delegatedProperties.kt:69:39:69:56 | this | delegatedProperties.kt:69:39:69:56 | get | ThisAccess | -| delegatedProperties.kt:69:39:69:56 | this | delegatedProperties.kt:69:39:69:56 | getDelegatedToExtMember1 | ThisAccess | -| delegatedProperties.kt:69:39:69:56 | this | delegatedProperties.kt:69:39:69:56 | getDelegatedToExtMember1 | ThisAccess | | delegatedProperties.kt:69:39:69:56 | this | delegatedProperties.kt:69:39:69:56 | invoke | ThisAccess | | delegatedProperties.kt:69:39:69:56 | this | delegatedProperties.kt:69:39:69:56 | invoke | ThisAccess | | delegatedProperties.kt:69:39:69:56 | this | delegatedProperties.kt:69:39:69:56 | invoke | ThisAccess | @@ -519,34 +519,36 @@ | delegatedProperties.kt:69:39:69:56 | this. | delegatedProperties.kt:69:39:69:56 | | VarAccess | | delegatedProperties.kt:69:39:69:56 | this. | delegatedProperties.kt:69:39:69:56 | get | VarAccess | | delegatedProperties.kt:69:39:69:56 | this. | delegatedProperties.kt:69:39:69:56 | set | VarAccess | +| delegatedProperties.kt:69:39:69:56 | this.delegatedToExtMember1$delegate | delegatedProperties.kt:69:5:69:56 | getDelegatedToExtMember1 | VarAccess | | delegatedProperties.kt:69:39:69:56 | this.delegatedToExtMember1$delegate | delegatedProperties.kt:69:5:69:56 | setDelegatedToExtMember1 | VarAccess | -| delegatedProperties.kt:69:39:69:56 | this.delegatedToExtMember1$delegate | delegatedProperties.kt:69:39:69:56 | getDelegatedToExtMember1 | VarAccess | | delegatedProperties.kt:70:5:70:59 | Unit | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:70:5:70:59 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:70:5:70:59 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:70:39:70:59 | ...::... | delegatedProperties.kt:65:14:65:78 | MyClass | PropertyRefExpr | +| delegatedProperties.kt:70:39:70:59 | ...::... | delegatedProperties.kt:70:5:70:59 | getDelegatedToExtMember2 | PropertyRefExpr | | delegatedProperties.kt:70:39:70:59 | ...::... | delegatedProperties.kt:70:5:70:59 | setDelegatedToExtMember2 | PropertyRefExpr | -| delegatedProperties.kt:70:39:70:59 | ...::... | delegatedProperties.kt:70:39:70:59 | getDelegatedToExtMember2 | PropertyRefExpr | | delegatedProperties.kt:70:39:70:59 | ...=... | delegatedProperties.kt:65:14:65:78 | MyClass | KtInitializerAssignExpr | | delegatedProperties.kt:70:39:70:59 | | delegatedProperties.kt:70:5:70:59 | setDelegatedToExtMember2 | VarAccess | | delegatedProperties.kt:70:39:70:59 | DelegatedPropertiesKt | delegatedProperties.kt:70:39:70:59 | get | TypeAccess | | delegatedProperties.kt:70:39:70:59 | DelegatedPropertiesKt | delegatedProperties.kt:70:39:70:59 | set | TypeAccess | | delegatedProperties.kt:70:39:70:59 | Integer | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | +| delegatedProperties.kt:70:39:70:59 | Integer | delegatedProperties.kt:70:5:70:59 | getDelegatedToExtMember2 | TypeAccess | +| delegatedProperties.kt:70:39:70:59 | Integer | delegatedProperties.kt:70:5:70:59 | getDelegatedToExtMember2 | TypeAccess | | delegatedProperties.kt:70:39:70:59 | Integer | delegatedProperties.kt:70:5:70:59 | setDelegatedToExtMember2 | TypeAccess | | delegatedProperties.kt:70:39:70:59 | Integer | delegatedProperties.kt:70:5:70:59 | setDelegatedToExtMember2 | TypeAccess | -| delegatedProperties.kt:70:39:70:59 | Integer | delegatedProperties.kt:70:39:70:59 | getDelegatedToExtMember2 | TypeAccess | -| delegatedProperties.kt:70:39:70:59 | Integer | delegatedProperties.kt:70:39:70:59 | getDelegatedToExtMember2 | TypeAccess | | delegatedProperties.kt:70:39:70:59 | Integer | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:70:39:70:59 | KMutableProperty1 | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | +| delegatedProperties.kt:70:39:70:59 | KMutableProperty1 | delegatedProperties.kt:70:5:70:59 | getDelegatedToExtMember2 | TypeAccess | | delegatedProperties.kt:70:39:70:59 | KMutableProperty1 | delegatedProperties.kt:70:5:70:59 | setDelegatedToExtMember2 | TypeAccess | -| delegatedProperties.kt:70:39:70:59 | KMutableProperty1 | delegatedProperties.kt:70:39:70:59 | getDelegatedToExtMember2 | TypeAccess | | delegatedProperties.kt:70:39:70:59 | KMutableProperty1 | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:70:39:70:59 | MyClass | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | +| delegatedProperties.kt:70:39:70:59 | MyClass | delegatedProperties.kt:70:5:70:59 | getDelegatedToExtMember2 | TypeAccess | +| delegatedProperties.kt:70:39:70:59 | MyClass | delegatedProperties.kt:70:5:70:59 | getDelegatedToExtMember2 | TypeAccess | | delegatedProperties.kt:70:39:70:59 | MyClass | delegatedProperties.kt:70:5:70:59 | setDelegatedToExtMember2 | TypeAccess | | delegatedProperties.kt:70:39:70:59 | MyClass | delegatedProperties.kt:70:5:70:59 | setDelegatedToExtMember2 | TypeAccess | -| delegatedProperties.kt:70:39:70:59 | MyClass | delegatedProperties.kt:70:39:70:59 | getDelegatedToExtMember2 | TypeAccess | -| delegatedProperties.kt:70:39:70:59 | MyClass | delegatedProperties.kt:70:39:70:59 | getDelegatedToExtMember2 | TypeAccess | | delegatedProperties.kt:70:39:70:59 | MyClass | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:70:39:70:59 | PropertyReferenceDelegatesKt | delegatedProperties.kt:70:5:70:59 | getDelegatedToExtMember2 | TypeAccess | | delegatedProperties.kt:70:39:70:59 | PropertyReferenceDelegatesKt | delegatedProperties.kt:70:5:70:59 | setDelegatedToExtMember2 | TypeAccess | -| delegatedProperties.kt:70:39:70:59 | PropertyReferenceDelegatesKt | delegatedProperties.kt:70:39:70:59 | getDelegatedToExtMember2 | TypeAccess | | delegatedProperties.kt:70:39:70:59 | a0 | delegatedProperties.kt:70:39:70:59 | get | VarAccess | | delegatedProperties.kt:70:39:70:59 | a0 | delegatedProperties.kt:70:39:70:59 | get | VarAccess | | delegatedProperties.kt:70:39:70:59 | a0 | delegatedProperties.kt:70:39:70:59 | get | VarAccess | @@ -566,39 +568,38 @@ | delegatedProperties.kt:70:39:70:59 | getDelegatedToExtMember2(...) | delegatedProperties.kt:70:39:70:59 | get | MethodCall | | delegatedProperties.kt:70:39:70:59 | getDelegatedToExtMember2(...) | delegatedProperties.kt:70:39:70:59 | get | MethodCall | | delegatedProperties.kt:70:39:70:59 | getExtDelegated(...) | delegatedProperties.kt:70:39:70:59 | get | MethodCall | -| delegatedProperties.kt:70:39:70:59 | getValue(...) | delegatedProperties.kt:70:39:70:59 | getDelegatedToExtMember2 | MethodCall | -| delegatedProperties.kt:70:39:70:59 | int | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:70:39:70:59 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:70:39:70:59 | getValue(...) | delegatedProperties.kt:70:5:70:59 | getDelegatedToExtMember2 | MethodCall | | delegatedProperties.kt:70:39:70:59 | setDelegatedToExtMember2(...) | delegatedProperties.kt:70:39:70:59 | set | MethodCall | | delegatedProperties.kt:70:39:70:59 | setDelegatedToExtMember2(...) | delegatedProperties.kt:70:39:70:59 | set | MethodCall | | delegatedProperties.kt:70:39:70:59 | setExtDelegated(...) | delegatedProperties.kt:70:39:70:59 | set | MethodCall | | delegatedProperties.kt:70:39:70:59 | setValue(...) | delegatedProperties.kt:70:5:70:59 | setDelegatedToExtMember2 | MethodCall | +| delegatedProperties.kt:70:39:70:59 | this | delegatedProperties.kt:70:5:70:59 | getDelegatedToExtMember2 | ThisAccess | +| delegatedProperties.kt:70:39:70:59 | this | delegatedProperties.kt:70:5:70:59 | getDelegatedToExtMember2 | ThisAccess | | delegatedProperties.kt:70:39:70:59 | this | delegatedProperties.kt:70:5:70:59 | setDelegatedToExtMember2 | ThisAccess | | delegatedProperties.kt:70:39:70:59 | this | delegatedProperties.kt:70:5:70:59 | setDelegatedToExtMember2 | ThisAccess | -| delegatedProperties.kt:70:39:70:59 | this | delegatedProperties.kt:70:39:70:59 | getDelegatedToExtMember2 | ThisAccess | -| delegatedProperties.kt:70:39:70:59 | this | delegatedProperties.kt:70:39:70:59 | getDelegatedToExtMember2 | ThisAccess | | delegatedProperties.kt:70:39:70:59 | this | delegatedProperties.kt:70:39:70:59 | invoke | ThisAccess | | delegatedProperties.kt:70:39:70:59 | this | delegatedProperties.kt:70:39:70:59 | invoke | ThisAccess | | delegatedProperties.kt:70:39:70:59 | this | delegatedProperties.kt:70:39:70:59 | invoke | ThisAccess | +| delegatedProperties.kt:70:39:70:59 | this.delegatedToExtMember2$delegate | delegatedProperties.kt:70:5:70:59 | getDelegatedToExtMember2 | VarAccess | | delegatedProperties.kt:70:39:70:59 | this.delegatedToExtMember2$delegate | delegatedProperties.kt:70:5:70:59 | setDelegatedToExtMember2 | VarAccess | -| delegatedProperties.kt:70:39:70:59 | this.delegatedToExtMember2$delegate | delegatedProperties.kt:70:39:70:59 | getDelegatedToExtMember2 | VarAccess | +| delegatedProperties.kt:72:5:72:56 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:72:39:72:42 | MyClass | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | | delegatedProperties.kt:72:39:72:42 | MyClass.this | delegatedProperties.kt:65:14:65:78 | MyClass | ThisAccess | | delegatedProperties.kt:72:39:72:56 | ...::... | delegatedProperties.kt:65:14:65:78 | MyClass | PropertyRefExpr | -| delegatedProperties.kt:72:39:72:56 | ...::... | delegatedProperties.kt:72:39:72:56 | getDelegatedToBaseClass1 | PropertyRefExpr | +| delegatedProperties.kt:72:39:72:56 | ...::... | delegatedProperties.kt:72:5:72:56 | getDelegatedToBaseClass1 | PropertyRefExpr | | delegatedProperties.kt:72:39:72:56 | ...=... | delegatedProperties.kt:65:14:65:78 | MyClass | KtInitializerAssignExpr | | delegatedProperties.kt:72:39:72:56 | ...=... | delegatedProperties.kt:72:39:72:56 | | AssignExpr | | delegatedProperties.kt:72:39:72:56 | | delegatedProperties.kt:72:39:72:56 | | VarAccess | | delegatedProperties.kt:72:39:72:56 | Integer | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | -| delegatedProperties.kt:72:39:72:56 | Integer | delegatedProperties.kt:72:39:72:56 | getDelegatedToBaseClass1 | TypeAccess | -| delegatedProperties.kt:72:39:72:56 | Integer | delegatedProperties.kt:72:39:72:56 | getDelegatedToBaseClass1 | TypeAccess | +| delegatedProperties.kt:72:39:72:56 | Integer | delegatedProperties.kt:72:5:72:56 | getDelegatedToBaseClass1 | TypeAccess | +| delegatedProperties.kt:72:39:72:56 | Integer | delegatedProperties.kt:72:5:72:56 | getDelegatedToBaseClass1 | TypeAccess | | delegatedProperties.kt:72:39:72:56 | Integer | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:72:39:72:56 | KProperty0 | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | | delegatedProperties.kt:72:39:72:56 | KProperty0 | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:72:39:72:56 | KProperty1 | delegatedProperties.kt:72:39:72:56 | getDelegatedToBaseClass1 | TypeAccess | -| delegatedProperties.kt:72:39:72:56 | MyClass | delegatedProperties.kt:72:39:72:56 | getDelegatedToBaseClass1 | TypeAccess | +| delegatedProperties.kt:72:39:72:56 | KProperty1 | delegatedProperties.kt:72:5:72:56 | getDelegatedToBaseClass1 | TypeAccess | +| delegatedProperties.kt:72:39:72:56 | MyClass | delegatedProperties.kt:72:5:72:56 | getDelegatedToBaseClass1 | TypeAccess | | delegatedProperties.kt:72:39:72:56 | MyClass | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:72:39:72:56 | PropertyReferenceDelegatesKt | delegatedProperties.kt:72:39:72:56 | getDelegatedToBaseClass1 | TypeAccess | +| delegatedProperties.kt:72:39:72:56 | PropertyReferenceDelegatesKt | delegatedProperties.kt:72:5:72:56 | getDelegatedToBaseClass1 | TypeAccess | | delegatedProperties.kt:72:39:72:56 | a0 | delegatedProperties.kt:72:39:72:56 | get | VarAccess | | delegatedProperties.kt:72:39:72:56 | a0 | delegatedProperties.kt:72:39:72:56 | invoke | VarAccess | | delegatedProperties.kt:72:39:72:56 | delegatedToBaseClass1$delegate | delegatedProperties.kt:65:14:65:78 | MyClass | VarAccess | @@ -606,32 +607,32 @@ | delegatedProperties.kt:72:39:72:56 | get(...) | delegatedProperties.kt:72:39:72:56 | invoke | MethodCall | | delegatedProperties.kt:72:39:72:56 | getBaseClassInt(...) | delegatedProperties.kt:72:39:72:56 | get | MethodCall | | delegatedProperties.kt:72:39:72:56 | getDelegatedToBaseClass1(...) | delegatedProperties.kt:72:39:72:56 | get | MethodCall | -| delegatedProperties.kt:72:39:72:56 | getValue(...) | delegatedProperties.kt:72:39:72:56 | getDelegatedToBaseClass1 | MethodCall | -| delegatedProperties.kt:72:39:72:56 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:72:39:72:56 | getValue(...) | delegatedProperties.kt:72:5:72:56 | getDelegatedToBaseClass1 | MethodCall | +| delegatedProperties.kt:72:39:72:56 | this | delegatedProperties.kt:72:5:72:56 | getDelegatedToBaseClass1 | ThisAccess | +| delegatedProperties.kt:72:39:72:56 | this | delegatedProperties.kt:72:5:72:56 | getDelegatedToBaseClass1 | ThisAccess | | delegatedProperties.kt:72:39:72:56 | this | delegatedProperties.kt:72:39:72:56 | | ThisAccess | | delegatedProperties.kt:72:39:72:56 | this | delegatedProperties.kt:72:39:72:56 | get | ThisAccess | -| delegatedProperties.kt:72:39:72:56 | this | delegatedProperties.kt:72:39:72:56 | getDelegatedToBaseClass1 | ThisAccess | -| delegatedProperties.kt:72:39:72:56 | this | delegatedProperties.kt:72:39:72:56 | getDelegatedToBaseClass1 | ThisAccess | | delegatedProperties.kt:72:39:72:56 | this | delegatedProperties.kt:72:39:72:56 | invoke | ThisAccess | | delegatedProperties.kt:72:39:72:56 | this | delegatedProperties.kt:72:39:72:56 | invoke | ThisAccess | | delegatedProperties.kt:72:39:72:56 | this. | delegatedProperties.kt:72:39:72:56 | | VarAccess | | delegatedProperties.kt:72:39:72:56 | this. | delegatedProperties.kt:72:39:72:56 | get | VarAccess | -| delegatedProperties.kt:72:39:72:56 | this.delegatedToBaseClass1$delegate | delegatedProperties.kt:72:39:72:56 | getDelegatedToBaseClass1 | VarAccess | +| delegatedProperties.kt:72:39:72:56 | this.delegatedToBaseClass1$delegate | delegatedProperties.kt:72:5:72:56 | getDelegatedToBaseClass1 | VarAccess | +| delegatedProperties.kt:73:5:73:56 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:73:39:73:56 | ...::... | delegatedProperties.kt:65:14:65:78 | MyClass | PropertyRefExpr | -| delegatedProperties.kt:73:39:73:56 | ...::... | delegatedProperties.kt:73:39:73:56 | getDelegatedToBaseClass2 | PropertyRefExpr | +| delegatedProperties.kt:73:39:73:56 | ...::... | delegatedProperties.kt:73:5:73:56 | getDelegatedToBaseClass2 | PropertyRefExpr | | delegatedProperties.kt:73:39:73:56 | ...=... | delegatedProperties.kt:65:14:65:78 | MyClass | KtInitializerAssignExpr | | delegatedProperties.kt:73:39:73:56 | Base | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | -| delegatedProperties.kt:73:39:73:56 | Base | delegatedProperties.kt:73:39:73:56 | getDelegatedToBaseClass2 | TypeAccess | +| delegatedProperties.kt:73:39:73:56 | Base | delegatedProperties.kt:73:5:73:56 | getDelegatedToBaseClass2 | TypeAccess | | delegatedProperties.kt:73:39:73:56 | Base | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:73:39:73:56 | Integer | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | -| delegatedProperties.kt:73:39:73:56 | Integer | delegatedProperties.kt:73:39:73:56 | getDelegatedToBaseClass2 | TypeAccess | -| delegatedProperties.kt:73:39:73:56 | Integer | delegatedProperties.kt:73:39:73:56 | getDelegatedToBaseClass2 | TypeAccess | +| delegatedProperties.kt:73:39:73:56 | Integer | delegatedProperties.kt:73:5:73:56 | getDelegatedToBaseClass2 | TypeAccess | +| delegatedProperties.kt:73:39:73:56 | Integer | delegatedProperties.kt:73:5:73:56 | getDelegatedToBaseClass2 | TypeAccess | | delegatedProperties.kt:73:39:73:56 | Integer | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:73:39:73:56 | KProperty1 | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | | delegatedProperties.kt:73:39:73:56 | KProperty1 | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:73:39:73:56 | KProperty1 | delegatedProperties.kt:73:39:73:56 | getDelegatedToBaseClass2 | TypeAccess | -| delegatedProperties.kt:73:39:73:56 | MyClass | delegatedProperties.kt:73:39:73:56 | getDelegatedToBaseClass2 | TypeAccess | -| delegatedProperties.kt:73:39:73:56 | PropertyReferenceDelegatesKt | delegatedProperties.kt:73:39:73:56 | getDelegatedToBaseClass2 | TypeAccess | +| delegatedProperties.kt:73:39:73:56 | KProperty1 | delegatedProperties.kt:73:5:73:56 | getDelegatedToBaseClass2 | TypeAccess | +| delegatedProperties.kt:73:39:73:56 | MyClass | delegatedProperties.kt:73:5:73:56 | getDelegatedToBaseClass2 | TypeAccess | +| delegatedProperties.kt:73:39:73:56 | PropertyReferenceDelegatesKt | delegatedProperties.kt:73:5:73:56 | getDelegatedToBaseClass2 | TypeAccess | | delegatedProperties.kt:73:39:73:56 | a0 | delegatedProperties.kt:73:39:73:56 | get | VarAccess | | delegatedProperties.kt:73:39:73:56 | a0 | delegatedProperties.kt:73:39:73:56 | get | VarAccess | | delegatedProperties.kt:73:39:73:56 | a0 | delegatedProperties.kt:73:39:73:56 | invoke | VarAccess | @@ -641,31 +642,31 @@ | delegatedProperties.kt:73:39:73:56 | get(...) | delegatedProperties.kt:73:39:73:56 | invoke | MethodCall | | delegatedProperties.kt:73:39:73:56 | getBaseClassInt(...) | delegatedProperties.kt:73:39:73:56 | get | MethodCall | | delegatedProperties.kt:73:39:73:56 | getDelegatedToBaseClass2(...) | delegatedProperties.kt:73:39:73:56 | get | MethodCall | -| delegatedProperties.kt:73:39:73:56 | getValue(...) | delegatedProperties.kt:73:39:73:56 | getDelegatedToBaseClass2 | MethodCall | -| delegatedProperties.kt:73:39:73:56 | int | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:73:39:73:56 | this | delegatedProperties.kt:73:39:73:56 | getDelegatedToBaseClass2 | ThisAccess | -| delegatedProperties.kt:73:39:73:56 | this | delegatedProperties.kt:73:39:73:56 | getDelegatedToBaseClass2 | ThisAccess | +| delegatedProperties.kt:73:39:73:56 | getValue(...) | delegatedProperties.kt:73:5:73:56 | getDelegatedToBaseClass2 | MethodCall | +| delegatedProperties.kt:73:39:73:56 | this | delegatedProperties.kt:73:5:73:56 | getDelegatedToBaseClass2 | ThisAccess | +| delegatedProperties.kt:73:39:73:56 | this | delegatedProperties.kt:73:5:73:56 | getDelegatedToBaseClass2 | ThisAccess | | delegatedProperties.kt:73:39:73:56 | this | delegatedProperties.kt:73:39:73:56 | invoke | ThisAccess | | delegatedProperties.kt:73:39:73:56 | this | delegatedProperties.kt:73:39:73:56 | invoke | ThisAccess | -| delegatedProperties.kt:73:39:73:56 | this.delegatedToBaseClass2$delegate | delegatedProperties.kt:73:39:73:56 | getDelegatedToBaseClass2 | VarAccess | +| delegatedProperties.kt:73:39:73:56 | this.delegatedToBaseClass2$delegate | delegatedProperties.kt:73:5:73:56 | getDelegatedToBaseClass2 | VarAccess | +| delegatedProperties.kt:75:5:75:78 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:75:42:75:61 | MyClass | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | | delegatedProperties.kt:75:42:75:61 | MyClass.this | delegatedProperties.kt:65:14:65:78 | MyClass | ThisAccess | | delegatedProperties.kt:75:42:75:61 | getAnotherClassInstance(...) | delegatedProperties.kt:65:14:65:78 | MyClass | MethodCall | | delegatedProperties.kt:75:42:75:78 | ...::... | delegatedProperties.kt:65:14:65:78 | MyClass | PropertyRefExpr | -| delegatedProperties.kt:75:42:75:78 | ...::... | delegatedProperties.kt:75:42:75:78 | getDelegatedToAnotherClass1 | PropertyRefExpr | +| delegatedProperties.kt:75:42:75:78 | ...::... | delegatedProperties.kt:75:5:75:78 | getDelegatedToAnotherClass1 | PropertyRefExpr | | delegatedProperties.kt:75:42:75:78 | ...=... | delegatedProperties.kt:65:14:65:78 | MyClass | KtInitializerAssignExpr | | delegatedProperties.kt:75:42:75:78 | ...=... | delegatedProperties.kt:75:42:75:78 | | AssignExpr | | delegatedProperties.kt:75:42:75:78 | | delegatedProperties.kt:75:42:75:78 | | VarAccess | | delegatedProperties.kt:75:42:75:78 | ClassWithDelegate | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:75:42:75:78 | Integer | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | -| delegatedProperties.kt:75:42:75:78 | Integer | delegatedProperties.kt:75:42:75:78 | getDelegatedToAnotherClass1 | TypeAccess | -| delegatedProperties.kt:75:42:75:78 | Integer | delegatedProperties.kt:75:42:75:78 | getDelegatedToAnotherClass1 | TypeAccess | +| delegatedProperties.kt:75:42:75:78 | Integer | delegatedProperties.kt:75:5:75:78 | getDelegatedToAnotherClass1 | TypeAccess | +| delegatedProperties.kt:75:42:75:78 | Integer | delegatedProperties.kt:75:5:75:78 | getDelegatedToAnotherClass1 | TypeAccess | | delegatedProperties.kt:75:42:75:78 | Integer | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:75:42:75:78 | KProperty0 | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | | delegatedProperties.kt:75:42:75:78 | KProperty0 | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:75:42:75:78 | KProperty1 | delegatedProperties.kt:75:42:75:78 | getDelegatedToAnotherClass1 | TypeAccess | -| delegatedProperties.kt:75:42:75:78 | MyClass | delegatedProperties.kt:75:42:75:78 | getDelegatedToAnotherClass1 | TypeAccess | -| delegatedProperties.kt:75:42:75:78 | PropertyReferenceDelegatesKt | delegatedProperties.kt:75:42:75:78 | getDelegatedToAnotherClass1 | TypeAccess | +| delegatedProperties.kt:75:42:75:78 | KProperty1 | delegatedProperties.kt:75:5:75:78 | getDelegatedToAnotherClass1 | TypeAccess | +| delegatedProperties.kt:75:42:75:78 | MyClass | delegatedProperties.kt:75:5:75:78 | getDelegatedToAnotherClass1 | TypeAccess | +| delegatedProperties.kt:75:42:75:78 | PropertyReferenceDelegatesKt | delegatedProperties.kt:75:5:75:78 | getDelegatedToAnotherClass1 | TypeAccess | | delegatedProperties.kt:75:42:75:78 | a0 | delegatedProperties.kt:75:42:75:78 | get | VarAccess | | delegatedProperties.kt:75:42:75:78 | a0 | delegatedProperties.kt:75:42:75:78 | invoke | VarAccess | | delegatedProperties.kt:75:42:75:78 | delegatedToAnotherClass1$delegate | delegatedProperties.kt:65:14:65:78 | MyClass | VarAccess | @@ -673,39 +674,40 @@ | delegatedProperties.kt:75:42:75:78 | get(...) | delegatedProperties.kt:75:42:75:78 | invoke | MethodCall | | delegatedProperties.kt:75:42:75:78 | getAnotherClassInt(...) | delegatedProperties.kt:75:42:75:78 | get | MethodCall | | delegatedProperties.kt:75:42:75:78 | getDelegatedToAnotherClass1(...) | delegatedProperties.kt:75:42:75:78 | get | MethodCall | -| delegatedProperties.kt:75:42:75:78 | getValue(...) | delegatedProperties.kt:75:42:75:78 | getDelegatedToAnotherClass1 | MethodCall | -| delegatedProperties.kt:75:42:75:78 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:75:42:75:78 | getValue(...) | delegatedProperties.kt:75:5:75:78 | getDelegatedToAnotherClass1 | MethodCall | +| delegatedProperties.kt:75:42:75:78 | this | delegatedProperties.kt:75:5:75:78 | getDelegatedToAnotherClass1 | ThisAccess | +| delegatedProperties.kt:75:42:75:78 | this | delegatedProperties.kt:75:5:75:78 | getDelegatedToAnotherClass1 | ThisAccess | | delegatedProperties.kt:75:42:75:78 | this | delegatedProperties.kt:75:42:75:78 | | ThisAccess | | delegatedProperties.kt:75:42:75:78 | this | delegatedProperties.kt:75:42:75:78 | get | ThisAccess | -| delegatedProperties.kt:75:42:75:78 | this | delegatedProperties.kt:75:42:75:78 | getDelegatedToAnotherClass1 | ThisAccess | -| delegatedProperties.kt:75:42:75:78 | this | delegatedProperties.kt:75:42:75:78 | getDelegatedToAnotherClass1 | ThisAccess | | delegatedProperties.kt:75:42:75:78 | this | delegatedProperties.kt:75:42:75:78 | invoke | ThisAccess | | delegatedProperties.kt:75:42:75:78 | this | delegatedProperties.kt:75:42:75:78 | invoke | ThisAccess | | delegatedProperties.kt:75:42:75:78 | this. | delegatedProperties.kt:75:42:75:78 | | VarAccess | | delegatedProperties.kt:75:42:75:78 | this. | delegatedProperties.kt:75:42:75:78 | get | VarAccess | -| delegatedProperties.kt:75:42:75:78 | this.delegatedToAnotherClass1$delegate | delegatedProperties.kt:75:42:75:78 | getDelegatedToAnotherClass1 | VarAccess | +| delegatedProperties.kt:75:42:75:78 | this.delegatedToAnotherClass1$delegate | delegatedProperties.kt:75:5:75:78 | getDelegatedToAnotherClass1 | VarAccess | | delegatedProperties.kt:77:5:77:49 | Unit | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:77:5:77:49 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:77:5:77:49 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:77:37:77:49 | ...::... | delegatedProperties.kt:65:14:65:78 | MyClass | PropertyRefExpr | +| delegatedProperties.kt:77:37:77:49 | ...::... | delegatedProperties.kt:77:5:77:49 | getDelegatedToTopLevel | PropertyRefExpr | | delegatedProperties.kt:77:37:77:49 | ...::... | delegatedProperties.kt:77:5:77:49 | setDelegatedToTopLevel | PropertyRefExpr | -| delegatedProperties.kt:77:37:77:49 | ...::... | delegatedProperties.kt:77:37:77:49 | getDelegatedToTopLevel | PropertyRefExpr | | delegatedProperties.kt:77:37:77:49 | ...=... | delegatedProperties.kt:65:14:65:78 | MyClass | KtInitializerAssignExpr | | delegatedProperties.kt:77:37:77:49 | | delegatedProperties.kt:77:5:77:49 | setDelegatedToTopLevel | VarAccess | | delegatedProperties.kt:77:37:77:49 | DelegatedPropertiesKt | delegatedProperties.kt:77:37:77:49 | get | TypeAccess | | delegatedProperties.kt:77:37:77:49 | DelegatedPropertiesKt | delegatedProperties.kt:77:37:77:49 | set | TypeAccess | | delegatedProperties.kt:77:37:77:49 | Integer | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | +| delegatedProperties.kt:77:37:77:49 | Integer | delegatedProperties.kt:77:5:77:49 | getDelegatedToTopLevel | TypeAccess | +| delegatedProperties.kt:77:37:77:49 | Integer | delegatedProperties.kt:77:5:77:49 | getDelegatedToTopLevel | TypeAccess | | delegatedProperties.kt:77:37:77:49 | Integer | delegatedProperties.kt:77:5:77:49 | setDelegatedToTopLevel | TypeAccess | | delegatedProperties.kt:77:37:77:49 | Integer | delegatedProperties.kt:77:5:77:49 | setDelegatedToTopLevel | TypeAccess | -| delegatedProperties.kt:77:37:77:49 | Integer | delegatedProperties.kt:77:37:77:49 | getDelegatedToTopLevel | TypeAccess | -| delegatedProperties.kt:77:37:77:49 | Integer | delegatedProperties.kt:77:37:77:49 | getDelegatedToTopLevel | TypeAccess | | delegatedProperties.kt:77:37:77:49 | Integer | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:77:37:77:49 | KMutableProperty0 | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | | delegatedProperties.kt:77:37:77:49 | KMutableProperty0 | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:77:37:77:49 | KMutableProperty1 | delegatedProperties.kt:77:5:77:49 | getDelegatedToTopLevel | TypeAccess | | delegatedProperties.kt:77:37:77:49 | KMutableProperty1 | delegatedProperties.kt:77:5:77:49 | setDelegatedToTopLevel | TypeAccess | -| delegatedProperties.kt:77:37:77:49 | KMutableProperty1 | delegatedProperties.kt:77:37:77:49 | getDelegatedToTopLevel | TypeAccess | +| delegatedProperties.kt:77:37:77:49 | MyClass | delegatedProperties.kt:77:5:77:49 | getDelegatedToTopLevel | TypeAccess | | delegatedProperties.kt:77:37:77:49 | MyClass | delegatedProperties.kt:77:5:77:49 | setDelegatedToTopLevel | TypeAccess | -| delegatedProperties.kt:77:37:77:49 | MyClass | delegatedProperties.kt:77:37:77:49 | getDelegatedToTopLevel | TypeAccess | +| delegatedProperties.kt:77:37:77:49 | PropertyReferenceDelegatesKt | delegatedProperties.kt:77:5:77:49 | getDelegatedToTopLevel | TypeAccess | | delegatedProperties.kt:77:37:77:49 | PropertyReferenceDelegatesKt | delegatedProperties.kt:77:5:77:49 | setDelegatedToTopLevel | TypeAccess | -| delegatedProperties.kt:77:37:77:49 | PropertyReferenceDelegatesKt | delegatedProperties.kt:77:37:77:49 | getDelegatedToTopLevel | TypeAccess | | delegatedProperties.kt:77:37:77:49 | a0 | delegatedProperties.kt:77:37:77:49 | get | VarAccess | | delegatedProperties.kt:77:37:77:49 | a0 | delegatedProperties.kt:77:37:77:49 | get | VarAccess | | delegatedProperties.kt:77:37:77:49 | a0 | delegatedProperties.kt:77:37:77:49 | invoke | VarAccess | @@ -722,52 +724,51 @@ | delegatedProperties.kt:77:37:77:49 | getDelegatedToTopLevel(...) | delegatedProperties.kt:77:37:77:49 | get | MethodCall | | delegatedProperties.kt:77:37:77:49 | getDelegatedToTopLevel(...) | delegatedProperties.kt:77:37:77:49 | get | MethodCall | | delegatedProperties.kt:77:37:77:49 | getTopLevelInt(...) | delegatedProperties.kt:77:37:77:49 | get | MethodCall | -| delegatedProperties.kt:77:37:77:49 | getValue(...) | delegatedProperties.kt:77:37:77:49 | getDelegatedToTopLevel | MethodCall | -| delegatedProperties.kt:77:37:77:49 | int | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:77:37:77:49 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:77:37:77:49 | getValue(...) | delegatedProperties.kt:77:5:77:49 | getDelegatedToTopLevel | MethodCall | | delegatedProperties.kt:77:37:77:49 | setDelegatedToTopLevel(...) | delegatedProperties.kt:77:37:77:49 | set | MethodCall | | delegatedProperties.kt:77:37:77:49 | setDelegatedToTopLevel(...) | delegatedProperties.kt:77:37:77:49 | set | MethodCall | | delegatedProperties.kt:77:37:77:49 | setTopLevelInt(...) | delegatedProperties.kt:77:37:77:49 | set | MethodCall | | delegatedProperties.kt:77:37:77:49 | setValue(...) | delegatedProperties.kt:77:5:77:49 | setDelegatedToTopLevel | MethodCall | +| delegatedProperties.kt:77:37:77:49 | this | delegatedProperties.kt:77:5:77:49 | getDelegatedToTopLevel | ThisAccess | +| delegatedProperties.kt:77:37:77:49 | this | delegatedProperties.kt:77:5:77:49 | getDelegatedToTopLevel | ThisAccess | | delegatedProperties.kt:77:37:77:49 | this | delegatedProperties.kt:77:5:77:49 | setDelegatedToTopLevel | ThisAccess | | delegatedProperties.kt:77:37:77:49 | this | delegatedProperties.kt:77:5:77:49 | setDelegatedToTopLevel | ThisAccess | -| delegatedProperties.kt:77:37:77:49 | this | delegatedProperties.kt:77:37:77:49 | getDelegatedToTopLevel | ThisAccess | -| delegatedProperties.kt:77:37:77:49 | this | delegatedProperties.kt:77:37:77:49 | getDelegatedToTopLevel | ThisAccess | | delegatedProperties.kt:77:37:77:49 | this | delegatedProperties.kt:77:37:77:49 | invoke | ThisAccess | | delegatedProperties.kt:77:37:77:49 | this | delegatedProperties.kt:77:37:77:49 | invoke | ThisAccess | | delegatedProperties.kt:77:37:77:49 | this | delegatedProperties.kt:77:37:77:49 | invoke | ThisAccess | +| delegatedProperties.kt:77:37:77:49 | this.delegatedToTopLevel$delegate | delegatedProperties.kt:77:5:77:49 | getDelegatedToTopLevel | VarAccess | | delegatedProperties.kt:77:37:77:49 | this.delegatedToTopLevel$delegate | delegatedProperties.kt:77:5:77:49 | setDelegatedToTopLevel | VarAccess | -| delegatedProperties.kt:77:37:77:49 | this.delegatedToTopLevel$delegate | delegatedProperties.kt:77:37:77:49 | getDelegatedToTopLevel | VarAccess | +| delegatedProperties.kt:79:5:79:38 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:79:21:79:38 | ...::... | delegatedProperties.kt:65:14:65:78 | MyClass | PropertyRefExpr | -| delegatedProperties.kt:79:21:79:38 | ...::... | delegatedProperties.kt:79:21:79:38 | getMax | PropertyRefExpr | +| delegatedProperties.kt:79:21:79:38 | ...::... | delegatedProperties.kt:79:5:79:38 | getMax | PropertyRefExpr | | delegatedProperties.kt:79:21:79:38 | ...=... | delegatedProperties.kt:65:14:65:78 | MyClass | KtInitializerAssignExpr | | delegatedProperties.kt:79:21:79:38 | Integer | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | -| delegatedProperties.kt:79:21:79:38 | Integer | delegatedProperties.kt:79:21:79:38 | getMax | TypeAccess | -| delegatedProperties.kt:79:21:79:38 | Integer | delegatedProperties.kt:79:21:79:38 | getMax | TypeAccess | +| delegatedProperties.kt:79:21:79:38 | Integer | delegatedProperties.kt:79:5:79:38 | getMax | TypeAccess | +| delegatedProperties.kt:79:21:79:38 | Integer | delegatedProperties.kt:79:5:79:38 | getMax | TypeAccess | | delegatedProperties.kt:79:21:79:38 | Integer | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:79:21:79:38 | KProperty0 | delegatedProperties.kt:65:14:65:78 | MyClass | TypeAccess | | delegatedProperties.kt:79:21:79:38 | KProperty0 | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:79:21:79:38 | KProperty1 | delegatedProperties.kt:79:21:79:38 | getMax | TypeAccess | +| delegatedProperties.kt:79:21:79:38 | KProperty1 | delegatedProperties.kt:79:5:79:38 | getMax | TypeAccess | | delegatedProperties.kt:79:21:79:38 | MAX_VALUE | delegatedProperties.kt:79:21:79:38 | get | VarAccess | -| delegatedProperties.kt:79:21:79:38 | MyClass | delegatedProperties.kt:79:21:79:38 | getMax | TypeAccess | -| delegatedProperties.kt:79:21:79:38 | PropertyReferenceDelegatesKt | delegatedProperties.kt:79:21:79:38 | getMax | TypeAccess | +| delegatedProperties.kt:79:21:79:38 | MyClass | delegatedProperties.kt:79:5:79:38 | getMax | TypeAccess | +| delegatedProperties.kt:79:21:79:38 | PropertyReferenceDelegatesKt | delegatedProperties.kt:79:5:79:38 | getMax | TypeAccess | | delegatedProperties.kt:79:21:79:38 | a0 | delegatedProperties.kt:79:21:79:38 | get | VarAccess | | delegatedProperties.kt:79:21:79:38 | a0 | delegatedProperties.kt:79:21:79:38 | invoke | VarAccess | | delegatedProperties.kt:79:21:79:38 | get(...) | delegatedProperties.kt:79:21:79:38 | invoke | MethodCall | | delegatedProperties.kt:79:21:79:38 | get(...) | delegatedProperties.kt:79:21:79:38 | invoke | MethodCall | | delegatedProperties.kt:79:21:79:38 | getMax(...) | delegatedProperties.kt:79:21:79:38 | get | MethodCall | -| delegatedProperties.kt:79:21:79:38 | getValue(...) | delegatedProperties.kt:79:21:79:38 | getMax | MethodCall | -| delegatedProperties.kt:79:21:79:38 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:79:21:79:38 | getValue(...) | delegatedProperties.kt:79:5:79:38 | getMax | MethodCall | | delegatedProperties.kt:79:21:79:38 | max$delegate | delegatedProperties.kt:65:14:65:78 | MyClass | VarAccess | -| delegatedProperties.kt:79:21:79:38 | this | delegatedProperties.kt:79:21:79:38 | getMax | ThisAccess | -| delegatedProperties.kt:79:21:79:38 | this | delegatedProperties.kt:79:21:79:38 | getMax | ThisAccess | +| delegatedProperties.kt:79:21:79:38 | this | delegatedProperties.kt:79:5:79:38 | getMax | ThisAccess | +| delegatedProperties.kt:79:21:79:38 | this | delegatedProperties.kt:79:5:79:38 | getMax | ThisAccess | | delegatedProperties.kt:79:21:79:38 | this | delegatedProperties.kt:79:21:79:38 | invoke | ThisAccess | | delegatedProperties.kt:79:21:79:38 | this | delegatedProperties.kt:79:21:79:38 | invoke | ThisAccess | -| delegatedProperties.kt:79:21:79:38 | this.max$delegate | delegatedProperties.kt:79:21:79:38 | getMax | VarAccess | +| delegatedProperties.kt:79:21:79:38 | this.max$delegate | delegatedProperties.kt:79:5:79:38 | getMax | VarAccess | | delegatedProperties.kt:81:5:84:5 | Unit | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:82:9:82:54 | Unit | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:82:9:82:54 | delegatedToMember3$delegate | delegatedProperties.kt:81:5:84:5 | fn | LocalVariableDeclExpr | | delegatedProperties.kt:82:9:82:54 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:82:9:82:54 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:82:40:82:43 | this | delegatedProperties.kt:81:5:84:5 | fn | ThisAccess | | delegatedProperties.kt:82:40:82:54 | ...::... | delegatedProperties.kt:81:5:84:5 | fn | PropertyRefExpr | | delegatedProperties.kt:82:40:82:54 | ...::... | delegatedProperties.kt:82:9:82:54 | | PropertyRefExpr | @@ -804,7 +805,6 @@ | delegatedProperties.kt:82:40:82:54 | get(...) | delegatedProperties.kt:82:40:82:54 | invoke | MethodCall | | delegatedProperties.kt:82:40:82:54 | getMemberInt(...) | delegatedProperties.kt:82:40:82:54 | get | MethodCall | | delegatedProperties.kt:82:40:82:54 | getValue(...) | delegatedProperties.kt:82:9:82:54 | | MethodCall | -| delegatedProperties.kt:82:40:82:54 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:82:40:82:54 | new (...) | delegatedProperties.kt:82:40:82:54 | get | ClassInstanceExpr | | delegatedProperties.kt:82:40:82:54 | new (...) | delegatedProperties.kt:82:40:82:54 | get | ClassInstanceExpr | | delegatedProperties.kt:82:40:82:54 | new (...) | delegatedProperties.kt:82:40:82:54 | set | ClassInstanceExpr | @@ -823,39 +823,41 @@ | delegatedProperties.kt:83:9:83:12 | fn(...) | delegatedProperties.kt:81:5:84:5 | fn | MethodCall | | delegatedProperties.kt:83:9:83:12 | this | delegatedProperties.kt:81:5:84:5 | fn | ThisAccess | | delegatedProperties.kt:87:1:87:46 | Unit | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:87:1:87:46 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:87:1:87:46 | int | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:87:5:87:11 | MyClass | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:87:5:87:11 | MyClass | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:87:34:87:46 | ...::... | delegatedProperties.kt:0:0:0:0 | | PropertyRefExpr | +| delegatedProperties.kt:87:34:87:46 | ...::... | delegatedProperties.kt:87:1:87:46 | getExtDelegated | PropertyRefExpr | | delegatedProperties.kt:87:34:87:46 | ...::... | delegatedProperties.kt:87:1:87:46 | setExtDelegated | PropertyRefExpr | -| delegatedProperties.kt:87:34:87:46 | ...::... | delegatedProperties.kt:87:34:87:46 | getExtDelegated | PropertyRefExpr | | delegatedProperties.kt:87:34:87:46 | ...=... | delegatedProperties.kt:0:0:0:0 | | KtInitializerAssignExpr | | delegatedProperties.kt:87:34:87:46 | | delegatedProperties.kt:87:1:87:46 | setExtDelegated | VarAccess | | delegatedProperties.kt:87:34:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:87:34:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:87:1:87:46 | getExtDelegated | TypeAccess | | delegatedProperties.kt:87:34:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:87:1:87:46 | setExtDelegated | TypeAccess | | delegatedProperties.kt:87:34:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:87:34:87:46 | get | TypeAccess | | delegatedProperties.kt:87:34:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:87:34:87:46 | get | TypeAccess | | delegatedProperties.kt:87:34:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:87:34:87:46 | get | TypeAccess | -| delegatedProperties.kt:87:34:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:87:34:87:46 | getExtDelegated | TypeAccess | | delegatedProperties.kt:87:34:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:87:34:87:46 | set | TypeAccess | | delegatedProperties.kt:87:34:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:87:34:87:46 | set | TypeAccess | | delegatedProperties.kt:87:34:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:87:34:87:46 | set | TypeAccess | | delegatedProperties.kt:87:34:87:46 | DelegatedPropertiesKt.extDelegated$delegateMyClass | delegatedProperties.kt:0:0:0:0 | | VarAccess | +| delegatedProperties.kt:87:34:87:46 | DelegatedPropertiesKt.extDelegated$delegateMyClass | delegatedProperties.kt:87:1:87:46 | getExtDelegated | VarAccess | | delegatedProperties.kt:87:34:87:46 | DelegatedPropertiesKt.extDelegated$delegateMyClass | delegatedProperties.kt:87:1:87:46 | setExtDelegated | VarAccess | -| delegatedProperties.kt:87:34:87:46 | DelegatedPropertiesKt.extDelegated$delegateMyClass | delegatedProperties.kt:87:34:87:46 | getExtDelegated | VarAccess | | delegatedProperties.kt:87:34:87:46 | Integer | delegatedProperties.kt:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:87:34:87:46 | Integer | delegatedProperties.kt:87:1:87:46 | getExtDelegated | TypeAccess | +| delegatedProperties.kt:87:34:87:46 | Integer | delegatedProperties.kt:87:1:87:46 | getExtDelegated | TypeAccess | | delegatedProperties.kt:87:34:87:46 | Integer | delegatedProperties.kt:87:1:87:46 | setExtDelegated | TypeAccess | | delegatedProperties.kt:87:34:87:46 | Integer | delegatedProperties.kt:87:1:87:46 | setExtDelegated | TypeAccess | -| delegatedProperties.kt:87:34:87:46 | Integer | delegatedProperties.kt:87:34:87:46 | getExtDelegated | TypeAccess | -| delegatedProperties.kt:87:34:87:46 | Integer | delegatedProperties.kt:87:34:87:46 | getExtDelegated | TypeAccess | | delegatedProperties.kt:87:34:87:46 | Integer | file://:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:87:34:87:46 | KMutableProperty0 | delegatedProperties.kt:0:0:0:0 | | TypeAccess | | delegatedProperties.kt:87:34:87:46 | KMutableProperty0 | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:87:34:87:46 | KMutableProperty1 | delegatedProperties.kt:87:1:87:46 | getExtDelegated | TypeAccess | | delegatedProperties.kt:87:34:87:46 | KMutableProperty1 | delegatedProperties.kt:87:1:87:46 | setExtDelegated | TypeAccess | -| delegatedProperties.kt:87:34:87:46 | KMutableProperty1 | delegatedProperties.kt:87:34:87:46 | getExtDelegated | TypeAccess | +| delegatedProperties.kt:87:34:87:46 | MyClass | delegatedProperties.kt:87:1:87:46 | getExtDelegated | TypeAccess | | delegatedProperties.kt:87:34:87:46 | MyClass | delegatedProperties.kt:87:1:87:46 | setExtDelegated | TypeAccess | -| delegatedProperties.kt:87:34:87:46 | MyClass | delegatedProperties.kt:87:34:87:46 | getExtDelegated | TypeAccess | +| delegatedProperties.kt:87:34:87:46 | PropertyReferenceDelegatesKt | delegatedProperties.kt:87:1:87:46 | getExtDelegated | TypeAccess | | delegatedProperties.kt:87:34:87:46 | PropertyReferenceDelegatesKt | delegatedProperties.kt:87:1:87:46 | setExtDelegated | TypeAccess | -| delegatedProperties.kt:87:34:87:46 | PropertyReferenceDelegatesKt | delegatedProperties.kt:87:34:87:46 | getExtDelegated | TypeAccess | | delegatedProperties.kt:87:34:87:46 | a0 | delegatedProperties.kt:87:34:87:46 | get | VarAccess | | delegatedProperties.kt:87:34:87:46 | a0 | delegatedProperties.kt:87:34:87:46 | get | VarAccess | | delegatedProperties.kt:87:34:87:46 | a0 | delegatedProperties.kt:87:34:87:46 | invoke | VarAccess | @@ -871,15 +873,13 @@ | delegatedProperties.kt:87:34:87:46 | getExtDelegated(...) | delegatedProperties.kt:87:34:87:46 | get | MethodCall | | delegatedProperties.kt:87:34:87:46 | getExtDelegated(...) | delegatedProperties.kt:87:34:87:46 | get | MethodCall | | delegatedProperties.kt:87:34:87:46 | getTopLevelInt(...) | delegatedProperties.kt:87:34:87:46 | get | MethodCall | -| delegatedProperties.kt:87:34:87:46 | getValue(...) | delegatedProperties.kt:87:34:87:46 | getExtDelegated | MethodCall | -| delegatedProperties.kt:87:34:87:46 | int | file://:0:0:0:0 | | TypeAccess | -| delegatedProperties.kt:87:34:87:46 | int | file://:0:0:0:0 | | TypeAccess | +| delegatedProperties.kt:87:34:87:46 | getValue(...) | delegatedProperties.kt:87:1:87:46 | getExtDelegated | MethodCall | | delegatedProperties.kt:87:34:87:46 | setExtDelegated(...) | delegatedProperties.kt:87:34:87:46 | set | MethodCall | | delegatedProperties.kt:87:34:87:46 | setExtDelegated(...) | delegatedProperties.kt:87:34:87:46 | set | MethodCall | | delegatedProperties.kt:87:34:87:46 | setTopLevelInt(...) | delegatedProperties.kt:87:34:87:46 | set | MethodCall | | delegatedProperties.kt:87:34:87:46 | setValue(...) | delegatedProperties.kt:87:1:87:46 | setExtDelegated | MethodCall | +| delegatedProperties.kt:87:34:87:46 | this | delegatedProperties.kt:87:1:87:46 | getExtDelegated | ExtensionReceiverAccess | | delegatedProperties.kt:87:34:87:46 | this | delegatedProperties.kt:87:1:87:46 | setExtDelegated | ExtensionReceiverAccess | -| delegatedProperties.kt:87:34:87:46 | this | delegatedProperties.kt:87:34:87:46 | getExtDelegated | ExtensionReceiverAccess | | delegatedProperties.kt:87:34:87:46 | this | delegatedProperties.kt:87:34:87:46 | invoke | ThisAccess | | delegatedProperties.kt:87:34:87:46 | this | delegatedProperties.kt:87:34:87:46 | invoke | ThisAccess | | delegatedProperties.kt:87:34:87:46 | this | delegatedProperties.kt:87:34:87:46 | invoke | ThisAccess | @@ -1541,12 +1541,12 @@ | exprs.kt:186:5:186:27 | green | exprs.kt:184:1:187:1 | enums | LocalVariableDeclExpr | | exprs.kt:186:23:186:27 | Color | exprs.kt:184:1:187:1 | enums | TypeAccess | | exprs.kt:186:23:186:27 | Color.GREEN | exprs.kt:184:1:187:1 | enums | VarAccess | +| exprs.kt:192:5:192:10 | int | file://:0:0:0:0 | | TypeAccess | +| exprs.kt:192:5:192:10 | this | exprs.kt:192:5:192:10 | getA1 | ThisAccess | +| exprs.kt:192:5:192:10 | this.a1 | exprs.kt:192:5:192:10 | getA1 | VarAccess | | exprs.kt:192:5:192:14 | ...=... | exprs.kt:191:1:199:1 | Class1 | KtInitializerAssignExpr | | exprs.kt:192:5:192:14 | a1 | exprs.kt:191:1:199:1 | Class1 | VarAccess | | exprs.kt:192:5:192:14 | int | file://:0:0:0:0 | | TypeAccess | -| exprs.kt:192:5:192:14 | int | file://:0:0:0:0 | | TypeAccess | -| exprs.kt:192:5:192:14 | this | exprs.kt:192:5:192:14 | getA1 | ThisAccess | -| exprs.kt:192:5:192:14 | this.a1 | exprs.kt:192:5:192:14 | getA1 | VarAccess | | exprs.kt:192:14:192:14 | 1 | exprs.kt:191:1:199:1 | Class1 | IntegerLiteral | | exprs.kt:193:5:198:5 | Object | file://:0:0:0:0 | | TypeAccess | | exprs.kt:194:9:194:18 | a2 | exprs.kt:193:5:198:5 | getObject | LocalVariableDeclExpr | @@ -1554,12 +1554,12 @@ | exprs.kt:195:16:197:9 | | exprs.kt:193:5:198:5 | getObject | StmtExpr | | exprs.kt:195:16:197:9 | Interface1 | exprs.kt:193:5:198:5 | getObject | TypeAccess | | exprs.kt:195:16:197:9 | new (...) | exprs.kt:193:5:198:5 | getObject | ClassInstanceExpr | +| exprs.kt:196:13:196:26 | String | file://:0:0:0:0 | | TypeAccess | +| exprs.kt:196:13:196:26 | this | exprs.kt:196:13:196:26 | getA3 | ThisAccess | +| exprs.kt:196:13:196:26 | this.a3 | exprs.kt:196:13:196:26 | getA3 | VarAccess | | exprs.kt:196:13:196:49 | ...=... | exprs.kt:195:16:197:9 | | KtInitializerAssignExpr | | exprs.kt:196:13:196:49 | String | file://:0:0:0:0 | | TypeAccess | -| exprs.kt:196:13:196:49 | String | file://:0:0:0:0 | | TypeAccess | | exprs.kt:196:13:196:49 | a3 | exprs.kt:195:16:197:9 | | VarAccess | -| exprs.kt:196:13:196:49 | this | exprs.kt:196:13:196:49 | getA3 | ThisAccess | -| exprs.kt:196:13:196:49 | this.a3 | exprs.kt:196:13:196:49 | getA3 | VarAccess | | exprs.kt:196:31:196:32 | getA1(...) | exprs.kt:195:16:197:9 | | MethodCall | | exprs.kt:196:31:196:32 | this | exprs.kt:195:16:197:9 | | ThisAccess | | exprs.kt:196:31:196:37 | ... + ... | exprs.kt:195:16:197:9 | | AddExpr | @@ -1745,19 +1745,13 @@ | exprs.kt:271:3:271:14 | ...-=... | exprs.kt:267:1:276:1 | inPlaceOperators | AssignSubExpr | | exprs.kt:271:3:271:14 | updated | exprs.kt:267:1:276:1 | inPlaceOperators | VarAccess | | exprs.kt:271:14:271:14 | 1 | exprs.kt:267:1:276:1 | inPlaceOperators | IntegerLiteral | -| exprs.kt:272:3:272:9 | updated | exprs.kt:267:1:276:1 | inPlaceOperators | VarAccess | -| exprs.kt:272:3:272:14 | ... * ... | exprs.kt:267:1:276:1 | inPlaceOperators | MulExpr | -| exprs.kt:272:3:272:14 | ...=... | exprs.kt:267:1:276:1 | inPlaceOperators | AssignExpr | +| exprs.kt:272:3:272:14 | ...*=... | exprs.kt:267:1:276:1 | inPlaceOperators | AssignMulExpr | | exprs.kt:272:3:272:14 | updated | exprs.kt:267:1:276:1 | inPlaceOperators | VarAccess | | exprs.kt:272:14:272:14 | 1 | exprs.kt:267:1:276:1 | inPlaceOperators | IntegerLiteral | -| exprs.kt:273:3:273:9 | updated | exprs.kt:267:1:276:1 | inPlaceOperators | VarAccess | -| exprs.kt:273:3:273:14 | ... / ... | exprs.kt:267:1:276:1 | inPlaceOperators | DivExpr | -| exprs.kt:273:3:273:14 | ...=... | exprs.kt:267:1:276:1 | inPlaceOperators | AssignExpr | +| exprs.kt:273:3:273:14 | .../=... | exprs.kt:267:1:276:1 | inPlaceOperators | AssignDivExpr | | exprs.kt:273:3:273:14 | updated | exprs.kt:267:1:276:1 | inPlaceOperators | VarAccess | | exprs.kt:273:14:273:14 | 1 | exprs.kt:267:1:276:1 | inPlaceOperators | IntegerLiteral | -| exprs.kt:274:3:274:9 | updated | exprs.kt:267:1:276:1 | inPlaceOperators | VarAccess | -| exprs.kt:274:3:274:14 | ... % ... | exprs.kt:267:1:276:1 | inPlaceOperators | RemExpr | -| exprs.kt:274:3:274:14 | ...=... | exprs.kt:267:1:276:1 | inPlaceOperators | AssignExpr | +| exprs.kt:274:3:274:14 | ...%=... | exprs.kt:267:1:276:1 | inPlaceOperators | AssignRemExpr | | exprs.kt:274:3:274:14 | updated | exprs.kt:267:1:276:1 | inPlaceOperators | VarAccess | | exprs.kt:274:14:274:14 | 1 | exprs.kt:267:1:276:1 | inPlaceOperators | IntegerLiteral | | exprs.kt:278:1:278:66 | T | file://:0:0:0:0 | | TypeAccess | @@ -4297,11 +4291,11 @@ | samConversion.kt:59:5:59:15 | fn1(...) | samConversion.kt:57:1:60:1 | test | MethodCall | | samConversion.kt:59:12:59:12 | 1 | samConversion.kt:57:1:60:1 | test | IntegerLiteral | | samConversion.kt:59:14:59:14 | 2 | samConversion.kt:57:1:60:1 | test | IntegerLiteral | +| samConversion.kt:63:5:63:9 | int | file://:0:0:0:0 | | TypeAccess | +| samConversion.kt:63:5:63:9 | this | samConversion.kt:63:5:63:9 | getX | ThisAccess | +| samConversion.kt:63:5:63:9 | this.x | samConversion.kt:63:5:63:9 | getX | VarAccess | | samConversion.kt:63:5:63:13 | ...=... | samConversion.kt:62:1:64:1 | PropertyRefsTest | KtInitializerAssignExpr | | samConversion.kt:63:5:63:13 | int | file://:0:0:0:0 | | TypeAccess | -| samConversion.kt:63:5:63:13 | int | file://:0:0:0:0 | | TypeAccess | -| samConversion.kt:63:5:63:13 | this | samConversion.kt:63:5:63:13 | getX | ThisAccess | -| samConversion.kt:63:5:63:13 | this.x | samConversion.kt:63:5:63:13 | getX | VarAccess | | samConversion.kt:63:5:63:13 | x | samConversion.kt:62:1:64:1 | PropertyRefsTest | VarAccess | | samConversion.kt:63:13:63:13 | 1 | samConversion.kt:62:1:64:1 | PropertyRefsTest | IntegerLiteral | | samConversion.kt:67:5:67:37 | int | file://:0:0:0:0 | | TypeAccess | diff --git a/java/ql/test-kotlin2/library-tests/exprs/funcExprs.expected b/java/ql/test-kotlin2/library-tests/exprs/funcExprs.expected index 1328047196cd..94ef616bff83 100644 --- a/java/ql/test-kotlin2/library-tests/exprs/funcExprs.expected +++ b/java/ql/test-kotlin2/library-tests/exprs/funcExprs.expected @@ -86,8 +86,8 @@ anon_class_member_modifiers | delegatedProperties.kt:19:34:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:34:19:51 | set | override, public | | delegatedProperties.kt:23:29:23:31 | new KProperty0(...) { ... } | delegatedProperties.kt:23:29:23:31 | get | override, public | | delegatedProperties.kt:23:29:23:31 | new KProperty0(...) { ... } | delegatedProperties.kt:23:29:23:31 | invoke | override, public | -| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:26:13:26:28 | getCurValue | final, public | -| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:26:13:26:28 | setCurValue | final, public | +| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:26:13:26:24 | getCurValue | final, public | +| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:26:13:26:24 | setCurValue | final, public | | delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:27:13:27:88 | getValue | override, public | | delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:28:13:30:13 | setValue | override, public | | delegatedProperties.kt:33:30:33:47 | new KProperty0(...) { ... } | delegatedProperties.kt:33:30:33:47 | get | override, public | @@ -187,7 +187,7 @@ anon_class_member_modifiers | delegatedProperties.kt:87:34:87:46 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:87:34:87:46 | invoke | override, public | | delegatedProperties.kt:87:34:87:46 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:87:34:87:46 | set | override, public | | delegatedProperties.kt:87:34:87:46 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:87:34:87:46 | set | override, public | -| exprs.kt:195:16:197:9 | new Interface1(...) { ... } | exprs.kt:196:13:196:49 | getA3 | final, public | +| exprs.kt:195:16:197:9 | new Interface1(...) { ... } | exprs.kt:196:13:196:26 | getA3 | final, public | | funcExprs.kt:22:26:22:33 | new Function0(...) { ... } | funcExprs.kt:22:26:22:33 | invoke | final, override, public | | funcExprs.kt:23:26:23:33 | new Function0(...) { ... } | funcExprs.kt:23:26:23:33 | invoke | final, override, public | | funcExprs.kt:24:26:24:33 | new Function0(...) { ... } | funcExprs.kt:24:26:24:33 | invoke | final, override, public | diff --git a/java/ql/test-kotlin2/library-tests/exprs_typeaccess/PrintAst.expected b/java/ql/test-kotlin2/library-tests/exprs_typeaccess/PrintAst.expected index e3bd90271e6e..a9cce8a012fb 100644 --- a/java/ql/test-kotlin2/library-tests/exprs_typeaccess/PrintAst.expected +++ b/java/ql/test-kotlin2/library-tests/exprs_typeaccess/PrintAst.expected @@ -71,8 +71,7 @@ A.kt: # 19| 0: [VarAccess] Enu.A # 19| -1: [TypeAccess] Enu # 20| 2: [ReturnStmt] return ... -# 20| 0: [VarAccess] B.x -# 20| -1: [TypeAccess] B +# 20| 0: [IntegerLiteral] 5 # 23| 11: [Class] Enu # 23| 2: [Constructor] Enu # 23| 5: [BlockStmt] { ... } diff --git a/java/ql/test-kotlin2/library-tests/generic-instance-methods/test.expected b/java/ql/test-kotlin2/library-tests/generic-instance-methods/test.expected index d4a8aa109e85..2a6682ec3d85 100644 --- a/java/ql/test-kotlin2/library-tests/generic-instance-methods/test.expected +++ b/java/ql/test-kotlin2/library-tests/generic-instance-methods/test.expected @@ -6,8 +6,8 @@ calls | Test.java:26:5:26:35 | setter(...) | Test.java:16:22:16:25 | user | Test.java:14:14:14:17 | Test | Generic2.class:0:0:0:0 | setter | Generic2.class:0:0:0:0 | Generic2 | | Test.java:27:5:27:24 | getter(...) | Test.java:16:22:16:25 | user | Test.java:14:14:14:17 | Test | Generic2.class:0:0:0:0 | getter | Generic2.class:0:0:0:0 | Generic2 | | test.kt:5:32:5:46 | identity(...) | test.kt:5:3:5:46 | identity2 | test.kt:1:1:13:1 | Generic | test.kt:6:3:6:35 | identity | test.kt:1:1:13:1 | Generic | -| test.kt:7:21:7:26 | getStored(...) | test.kt:7:3:7:26 | getter | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:19 | getStored | test.kt:1:1:13:1 | Generic | -| test.kt:8:26:8:39 | setStored(...) | test.kt:8:3:8:41 | setter | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:19 | setStored | test.kt:1:1:13:1 | Generic | +| test.kt:7:21:7:26 | getStored(...) | test.kt:7:3:7:26 | getter | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:12 | getStored | test.kt:1:1:13:1 | Generic | +| test.kt:8:26:8:39 | setStored(...) | test.kt:8:3:8:41 | setter | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:12 | setStored | test.kt:1:1:13:1 | Generic | | test.kt:11:44:11:70 | privateid(...) | test.kt:11:3:11:70 | callPrivateId | test.kt:1:1:13:1 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | privateid | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | | test.kt:18:3:18:35 | identity(...) | test.kt:15:1:28:1 | user | test.kt:0:0:0:0 | TestKt | file:///!unknown-binary-location/Generic.class:0:0:0:0 | identity | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | | test.kt:19:3:19:36 | identity2(...) | test.kt:15:1:28:1 | user | test.kt:0:0:0:0 | TestKt | file:///!unknown-binary-location/Generic.class:0:0:0:0 | identity2 | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | @@ -53,30 +53,30 @@ refTypes | Test.java:1:7:1:14 | Generic2 | Test.java:10:8:10:13 | setter | setter(java.lang.Object) | T | void | Test.java:1:7:1:14 | Generic2 | Test.java:10:8:10:13 | setter | | Test.java:14:14:14:17 | Test | Test.java:16:22:16:25 | user | user() | No parameters | void | Test.java:14:14:14:17 | Test | Test.java:16:22:16:25 | user | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | callPrivateId | callPrivateId(Generic) | Generic | String | test.kt:1:1:13:1 | Generic | test.kt:11:3:11:70 | callPrivateId | -| file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | getStored | getStored() | No parameters | String | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:19 | getStored | +| file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | getStored | getStored() | No parameters | String | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:12 | getStored | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | getter | getter() | No parameters | String | test.kt:1:1:13:1 | Generic | test.kt:7:3:7:26 | getter | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | identity | identity(java.lang.Void) | Void | String | test.kt:1:1:13:1 | Generic | test.kt:6:3:6:35 | identity | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | identity2 | identity2(java.lang.Void) | Void | String | test.kt:1:1:13:1 | Generic | test.kt:5:3:5:46 | identity2 | -| file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | setStored | setStored(java.lang.Void) | Void | void | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:19 | setStored | +| file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | setStored | setStored(java.lang.Void) | Void | void | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:12 | setStored | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | setter | setter(java.lang.Void) | Void | void | test.kt:1:1:13:1 | Generic | test.kt:8:3:8:41 | setter | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | callPrivateId | callPrivateId(Generic) | Generic | String | test.kt:1:1:13:1 | Generic | test.kt:11:3:11:70 | callPrivateId | -| file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | getStored | getStored() | No parameters | Object | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:19 | getStored | +| file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | getStored | getStored() | No parameters | Object | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:12 | getStored | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | getter | getter() | No parameters | Object | test.kt:1:1:13:1 | Generic | test.kt:7:3:7:26 | getter | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | identity | identity(java.lang.String) | String | Object | test.kt:1:1:13:1 | Generic | test.kt:6:3:6:35 | identity | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | identity2 | identity2(java.lang.String) | String | Object | test.kt:1:1:13:1 | Generic | test.kt:5:3:5:46 | identity2 | -| file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | setStored | setStored(java.lang.String) | String | void | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:19 | setStored | +| file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | setStored | setStored(java.lang.String) | String | void | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:12 | setStored | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | setter | setter(java.lang.String) | String | void | test.kt:1:1:13:1 | Generic | test.kt:8:3:8:41 | setter | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | callPrivateId | callPrivateId(Generic) | Generic | String | test.kt:1:1:13:1 | Generic | test.kt:11:3:11:70 | callPrivateId | -| file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | getStored | getStored() | No parameters | String | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:19 | getStored | +| file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | getStored | getStored() | No parameters | String | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:12 | getStored | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | getter | getter() | No parameters | String | test.kt:1:1:13:1 | Generic | test.kt:7:3:7:26 | getter | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | identity | identity(java.lang.String) | String | String | test.kt:1:1:13:1 | Generic | test.kt:6:3:6:35 | identity | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | identity2 | identity2(java.lang.String) | String | String | test.kt:1:1:13:1 | Generic | test.kt:5:3:5:46 | identity2 | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | privateid | privateid(java.lang.String) | String | String | test.kt:1:1:13:1 | Generic | test.kt:10:3:10:41 | privateid | -| file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | setStored | setStored(java.lang.String) | String | void | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:19 | setStored | +| file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | setStored | setStored(java.lang.String) | String | void | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:12 | setStored | | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic | file:///!unknown-binary-location/Generic.class:0:0:0:0 | setter | setter(java.lang.String) | String | void | test.kt:1:1:13:1 | Generic | test.kt:8:3:8:41 | setter | | test.kt:0:0:0:0 | TestKt | test.kt:15:1:28:1 | user | user() | No parameters | void | test.kt:0:0:0:0 | TestKt | test.kt:15:1:28:1 | user | -| test.kt:1:1:13:1 | Generic | test.kt:3:3:3:19 | getStored | getStored() | No parameters | T | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:19 | getStored | -| test.kt:1:1:13:1 | Generic | test.kt:3:3:3:19 | setStored | setStored(java.lang.Object) | T | void | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:19 | setStored | +| test.kt:1:1:13:1 | Generic | test.kt:3:3:3:12 | getStored | getStored() | No parameters | T | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:12 | getStored | +| test.kt:1:1:13:1 | Generic | test.kt:3:3:3:12 | setStored | setStored(java.lang.Object) | T | void | test.kt:1:1:13:1 | Generic | test.kt:3:3:3:12 | setStored | | test.kt:1:1:13:1 | Generic | test.kt:5:3:5:46 | identity2 | identity2(java.lang.Object) | T | T | test.kt:1:1:13:1 | Generic | test.kt:5:3:5:46 | identity2 | | test.kt:1:1:13:1 | Generic | test.kt:6:3:6:35 | identity | identity(java.lang.Object) | T | T | test.kt:1:1:13:1 | Generic | test.kt:6:3:6:35 | identity | | test.kt:1:1:13:1 | Generic | test.kt:7:3:7:26 | getter | getter() | No parameters | T | test.kt:1:1:13:1 | Generic | test.kt:7:3:7:26 | getter | diff --git a/java/ql/test-kotlin2/library-tests/generic-selective-extraction/test.expected b/java/ql/test-kotlin2/library-tests/generic-selective-extraction/test.expected index d64054af2f72..fbc7f2519f65 100644 --- a/java/ql/test-kotlin2/library-tests/generic-selective-extraction/test.expected +++ b/java/ql/test-kotlin2/library-tests/generic-selective-extraction/test.expected @@ -12,12 +12,12 @@ | Test.java:13:7:13:10 | User | Test.java:13:7:13:10 | User | | Test.java:13:7:13:10 | User | Test.java:15:22:15:25 | test | | Test.kt:1:1:8:1 | TestKt | Test.kt:1:1:8:1 | TestKt | +| Test.kt:1:1:8:1 | TestKt | Test.kt:3:3:3:15 | getField | +| Test.kt:1:1:8:1 | TestKt | Test.kt:3:3:3:15 | setField | | Test.kt:1:1:8:1 | TestKt | Test.kt:3:3:3:22 | field | -| Test.kt:1:1:8:1 | TestKt | Test.kt:3:3:3:22 | getField | -| Test.kt:1:1:8:1 | TestKt | Test.kt:3:3:3:22 | setField | -| Test.kt:1:1:8:1 | TestKt | Test.kt:4:3:5:25 | getRawField | +| Test.kt:1:1:8:1 | TestKt | Test.kt:4:3:5:18 | getRawField | +| Test.kt:1:1:8:1 | TestKt | Test.kt:4:3:5:18 | setRawField | | Test.kt:1:1:8:1 | TestKt | Test.kt:4:3:5:25 | rawField | -| Test.kt:1:1:8:1 | TestKt | Test.kt:4:3:5:25 | setRawField | | Test.kt:1:1:8:1 | TestKt | Test.kt:6:3:6:22 | method | | Test.kt:10:1:10:20 | FieldUsedKt | Test.kt:10:1:10:20 | FieldUsedKt | | Test.kt:11:1:11:23 | RawFieldUsedKt | Test.kt:11:1:11:23 | RawFieldUsedKt | diff --git a/java/ql/test-kotlin2/library-tests/internal-public-alias/test.expected b/java/ql/test-kotlin2/library-tests/internal-public-alias/test.expected index a436af623037..09dae53df720 100644 --- a/java/ql/test-kotlin2/library-tests/internal-public-alias/test.expected +++ b/java/ql/test-kotlin2/library-tests/internal-public-alias/test.expected @@ -1,6 +1,6 @@ | User.java:3:21:3:24 | test | -| test.kt:3:3:3:30 | getInternalVal$main | +| test.kt:3:3:3:26 | getInternalVal$main | | test.kt:6:3:6:36 | getInternalVal | -| test.kt:8:3:8:30 | getInternalVar$main | -| test.kt:8:3:8:30 | setInternalVar$main | +| test.kt:8:3:8:26 | getInternalVar$main | +| test.kt:8:3:8:26 | setInternalVar$main | | test.kt:10:3:10:32 | internalFun$main | diff --git a/java/ql/test-kotlin2/library-tests/jvmstatic-annotation/test.expected b/java/ql/test-kotlin2/library-tests/jvmstatic-annotation/test.expected index 6ce063785ea5..71e45333654a 100644 --- a/java/ql/test-kotlin2/library-tests/jvmstatic-annotation/test.expected +++ b/java/ql/test-kotlin2/library-tests/jvmstatic-annotation/test.expected @@ -4,14 +4,14 @@ staticMembers | test.kt:9:1:29:1 | HasCompanion | test.kt:11:3:27:3 | Companion | Class | | test.kt:9:1:29:1 | HasCompanion | test.kt:11:3:27:3 | Companion | Field | | test.kt:9:1:29:1 | HasCompanion | test.kt:13:5:13:71 | staticMethod | Method | -| test.kt:9:1:29:1 | HasCompanion | test.kt:16:5:16:43 | getStaticProp | Method | -| test.kt:9:1:29:1 | HasCompanion | test.kt:16:5:16:43 | setStaticProp | Method | +| test.kt:9:1:29:1 | HasCompanion | test.kt:16:5:16:37 | getStaticProp | Method | +| test.kt:9:1:29:1 | HasCompanion | test.kt:16:5:16:37 | setStaticProp | Method | | test.kt:9:1:29:1 | HasCompanion | test.kt:20:7:20:45 | getPropWithStaticGetter | Method | | test.kt:9:1:29:1 | HasCompanion | test.kt:25:7:25:60 | setPropWithStaticSetter | Method | | test.kt:31:1:47:1 | NonCompanion | test.kt:31:1:47:1 | INSTANCE | Field | | test.kt:31:1:47:1 | NonCompanion | test.kt:33:3:33:69 | staticMethod | Method | -| test.kt:31:1:47:1 | NonCompanion | test.kt:36:3:36:41 | getStaticProp | Method | -| test.kt:31:1:47:1 | NonCompanion | test.kt:36:3:36:41 | setStaticProp | Method | +| test.kt:31:1:47:1 | NonCompanion | test.kt:36:3:36:35 | getStaticProp | Method | +| test.kt:31:1:47:1 | NonCompanion | test.kt:36:3:36:35 | setStaticProp | Method | | test.kt:31:1:47:1 | NonCompanion | test.kt:40:5:40:43 | getPropWithStaticGetter | Method | | test.kt:31:1:47:1 | NonCompanion | test.kt:45:5:45:58 | setPropWithStaticSetter | Method | #select @@ -28,8 +28,8 @@ staticMembers | test.kt:11:3:27:3 | Companion | test.kt:13:5:13:71 | staticMethod(...) | test.kt:13:5:13:71 | HasCompanion.Companion | instance | | test.kt:11:3:27:3 | Companion | test.kt:13:54:13:71 | nonStaticMethod(...) | test.kt:13:54:13:71 | this | instance | | test.kt:11:3:27:3 | Companion | test.kt:14:46:14:60 | staticMethod(...) | test.kt:14:46:14:60 | this | instance | -| test.kt:11:3:27:3 | Companion | test.kt:16:5:16:43 | getStaticProp(...) | test.kt:16:5:16:43 | HasCompanion.Companion | instance | -| test.kt:11:3:27:3 | Companion | test.kt:16:5:16:43 | setStaticProp(...) | test.kt:16:5:16:43 | HasCompanion.Companion | instance | +| test.kt:11:3:27:3 | Companion | test.kt:16:5:16:37 | getStaticProp(...) | test.kt:16:5:16:37 | HasCompanion.Companion | instance | +| test.kt:11:3:27:3 | Companion | test.kt:16:5:16:37 | setStaticProp(...) | test.kt:16:5:16:37 | HasCompanion.Companion | instance | | test.kt:11:3:27:3 | Companion | test.kt:20:7:20:45 | getPropWithStaticGetter(...) | test.kt:20:7:20:45 | HasCompanion.Companion | instance | | test.kt:11:3:27:3 | Companion | test.kt:20:26:20:45 | getPropWithStaticSetter(...) | test.kt:20:26:20:45 | this | instance | | test.kt:11:3:27:3 | Companion | test.kt:21:24:21:47 | setPropWithStaticSetter(...) | test.kt:21:24:21:47 | this | instance | diff --git a/java/ql/test-kotlin2/library-tests/methods/exprs.expected b/java/ql/test-kotlin2/library-tests/methods/exprs.expected index 4d7a0a6e85ae..041ef562dfbd 100644 --- a/java/ql/test-kotlin2/library-tests/methods/exprs.expected +++ b/java/ql/test-kotlin2/library-tests/methods/exprs.expected @@ -1,15 +1,15 @@ -| clinit.kt:3:1:3:24 | ...=... | AssignExpr | +| clinit.kt:3:1:3:20 | ...=... | AssignExpr | +| clinit.kt:3:1:3:20 | | VarAccess | +| clinit.kt:3:1:3:20 | ClinitKt | TypeAccess | +| clinit.kt:3:1:3:20 | ClinitKt | TypeAccess | +| clinit.kt:3:1:3:20 | ClinitKt.topLevelInt | VarAccess | +| clinit.kt:3:1:3:20 | ClinitKt.topLevelInt | VarAccess | +| clinit.kt:3:1:3:20 | Unit | TypeAccess | +| clinit.kt:3:1:3:20 | int | TypeAccess | +| clinit.kt:3:1:3:20 | int | TypeAccess | | clinit.kt:3:1:3:24 | ...=... | KtInitializerAssignExpr | -| clinit.kt:3:1:3:24 | | VarAccess | | clinit.kt:3:1:3:24 | ClinitKt | TypeAccess | -| clinit.kt:3:1:3:24 | ClinitKt | TypeAccess | -| clinit.kt:3:1:3:24 | ClinitKt | TypeAccess | -| clinit.kt:3:1:3:24 | ClinitKt.topLevelInt | VarAccess | -| clinit.kt:3:1:3:24 | ClinitKt.topLevelInt | VarAccess | | clinit.kt:3:1:3:24 | ClinitKt.topLevelInt | VarAccess | -| clinit.kt:3:1:3:24 | Unit | TypeAccess | -| clinit.kt:3:1:3:24 | int | TypeAccess | -| clinit.kt:3:1:3:24 | int | TypeAccess | | clinit.kt:3:1:3:24 | int | TypeAccess | | clinit.kt:3:24:3:24 | 0 | IntegerLiteral | | dataClass.kt:0:0:0:0 | 0 | IntegerLiteral | @@ -132,6 +132,7 @@ | dataClass.kt:1:34:1:46 | this.y | VarAccess | | dataClass.kt:1:34:1:46 | y | VarAccess | | dataClass.kt:1:34:1:46 | y | VarAccess | +| delegates.kt:4:5:6:5 | int | TypeAccess | | delegates.kt:4:21:6:5 | ...::... | PropertyRefExpr | | delegates.kt:4:21:6:5 | ...=... | KtInitializerAssignExpr | | delegates.kt:4:21:6:5 | Integer | TypeAccess | @@ -148,7 +149,6 @@ | delegates.kt:4:21:6:5 | get(...) | MethodCall | | delegates.kt:4:21:6:5 | getLazyProp(...) | MethodCall | | delegates.kt:4:21:6:5 | getValue(...) | MethodCall | -| delegates.kt:4:21:6:5 | int | TypeAccess | | delegates.kt:4:21:6:5 | lazy(...) | MethodCall | | delegates.kt:4:21:6:5 | lazyProp$delegate | VarAccess | | delegates.kt:4:21:6:5 | this | ThisAccess | @@ -160,6 +160,8 @@ | delegates.kt:4:26:6:5 | Integer | TypeAccess | | delegates.kt:4:26:6:5 | int | TypeAccess | | delegates.kt:5:9:5:9 | 5 | IntegerLiteral | +| delegates.kt:8:5:11:5 | String | TypeAccess | +| delegates.kt:8:5:11:5 | String | TypeAccess | | delegates.kt:8:5:11:5 | Unit | TypeAccess | | delegates.kt:8:35:8:43 | INSTANCE | VarAccess | | delegates.kt:8:35:11:5 | ...::... | PropertyRefExpr | @@ -176,8 +178,6 @@ | delegates.kt:8:35:11:5 | String | TypeAccess | | delegates.kt:8:35:11:5 | String | TypeAccess | | delegates.kt:8:35:11:5 | String | TypeAccess | -| delegates.kt:8:35:11:5 | String | TypeAccess | -| delegates.kt:8:35:11:5 | String | TypeAccess | | delegates.kt:8:35:11:5 | a0 | VarAccess | | delegates.kt:8:35:11:5 | a0 | VarAccess | | delegates.kt:8:35:11:5 | a0 | VarAccess | diff --git a/java/ql/test-kotlin2/library-tests/methods/methods.expected b/java/ql/test-kotlin2/library-tests/methods/methods.expected index 330c5b2f9199..79f674e4d7c4 100644 --- a/java/ql/test-kotlin2/library-tests/methods/methods.expected +++ b/java/ql/test-kotlin2/library-tests/methods/methods.expected @@ -1,7 +1,7 @@ methods | clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:0:0:0:0 | | () | static | Compiler generated | -| clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:3:1:3:24 | getTopLevelInt | getTopLevelInt() | final, public, static | Compiler generated | -| clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:3:1:3:24 | setTopLevelInt | setTopLevelInt(int) | final, public, static | Compiler generated | +| clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:3:1:3:20 | getTopLevelInt | getTopLevelInt() | final, public, static | Compiler generated | +| clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:3:1:3:20 | setTopLevelInt | setTopLevelInt(int) | final, public, static | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | component1 | component1() | final, public | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | component2 | component2() | final, public | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | copy | copy(int,java.lang.String) | final, public | Compiler generated | @@ -12,9 +12,9 @@ methods | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:1:22:1:31 | getX | getX() | final, public | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:1:34:1:46 | getY | getY() | final, public | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:1:34:1:46 | setY | setY(java.lang.String) | final, public | Compiler generated | -| delegates.kt:3:1:12:1 | MyClass | delegates.kt:4:21:6:5 | getLazyProp | getLazyProp() | final, public | Compiler generated | +| delegates.kt:3:1:12:1 | MyClass | delegates.kt:4:5:6:5 | getLazyProp | getLazyProp() | final, public | Compiler generated | +| delegates.kt:3:1:12:1 | MyClass | delegates.kt:8:5:11:5 | getObservableProp | getObservableProp() | final, public | Compiler generated | | delegates.kt:3:1:12:1 | MyClass | delegates.kt:8:5:11:5 | setObservableProp | setObservableProp(java.lang.String) | final, public | Compiler generated | -| delegates.kt:3:1:12:1 | MyClass | delegates.kt:8:35:11:5 | getObservableProp | getObservableProp() | final, public | Compiler generated | | delegates.kt:4:21:6:5 | new KProperty1(...) { ... } | delegates.kt:4:21:6:5 | get | get(MyClass) | override, public | | | delegates.kt:4:21:6:5 | new KProperty1(...) { ... } | delegates.kt:4:21:6:5 | invoke | invoke(MyClass) | override, public | | | delegates.kt:4:26:6:5 | new Function0(...) { ... } | delegates.kt:4:26:6:5 | invoke | invoke() | final, override, public | | diff --git a/java/ql/test-kotlin2/library-tests/methods/parameters.expected b/java/ql/test-kotlin2/library-tests/methods/parameters.expected index 76538cae775c..f0c4ad719468 100644 --- a/java/ql/test-kotlin2/library-tests/methods/parameters.expected +++ b/java/ql/test-kotlin2/library-tests/methods/parameters.expected @@ -1,4 +1,4 @@ -| clinit.kt:3:1:3:24 | setTopLevelInt | clinit.kt:3:1:3:24 | | 0 | +| clinit.kt:3:1:3:20 | setTopLevelInt | clinit.kt:3:1:3:20 | | 0 | | dataClass.kt:0:0:0:0 | copy | dataClass.kt:0:0:0:0 | x | 0 | | dataClass.kt:0:0:0:0 | copy | dataClass.kt:0:0:0:0 | y | 1 | | dataClass.kt:0:0:0:0 | copy$default | dataClass.kt:0:0:0:0 | p0 | 0 | @@ -10,7 +10,7 @@ | dataClass.kt:1:34:1:46 | setY | dataClass.kt:1:34:1:46 | | 0 | | delegates.kt:4:21:6:5 | get | delegates.kt:4:21:6:5 | a0 | 0 | | delegates.kt:4:21:6:5 | invoke | delegates.kt:4:21:6:5 | a0 | 0 | -| delegates.kt:8:5:11:5 | setObservableProp | delegates.kt:8:35:11:5 | | 0 | +| delegates.kt:8:5:11:5 | setObservableProp | delegates.kt:8:5:11:5 | | 0 | | delegates.kt:8:35:11:5 | get | delegates.kt:8:35:11:5 | a0 | 0 | | delegates.kt:8:35:11:5 | get | delegates.kt:8:35:11:5 | a0 | 0 | | delegates.kt:8:35:11:5 | invoke | delegates.kt:8:35:11:5 | a0 | 0 | diff --git a/java/ql/test-kotlin2/library-tests/modifiers/modifiers.expected b/java/ql/test-kotlin2/library-tests/modifiers/modifiers.expected index 329e9e103999..6bc77b34a0ad 100644 --- a/java/ql/test-kotlin2/library-tests/modifiers/modifiers.expected +++ b/java/ql/test-kotlin2/library-tests/modifiers/modifiers.expected @@ -1,33 +1,33 @@ | modifiers.kt:1:1:29:1 | X | Class | public | | modifiers.kt:1:1:29:1 | X | Constructor | public | +| modifiers.kt:2:5:2:17 | getA$private | Method | final | +| modifiers.kt:2:5:2:17 | getA$private | Method | private | | modifiers.kt:2:5:2:21 | a | Field | final | | modifiers.kt:2:5:2:21 | a | Field | private | | modifiers.kt:2:5:2:21 | a | Property | private | -| modifiers.kt:2:5:2:21 | getA$private | Method | final | -| modifiers.kt:2:5:2:21 | getA$private | Method | private | +| modifiers.kt:3:5:3:19 | getB | Method | final | +| modifiers.kt:3:5:3:19 | getB | Method | protected | | modifiers.kt:3:5:3:23 | b | Field | final | | modifiers.kt:3:5:3:23 | b | Field | private | | modifiers.kt:3:5:3:23 | b | Property | protected | -| modifiers.kt:3:5:3:23 | getB | Method | final | -| modifiers.kt:3:5:3:23 | getB | Method | protected | +| modifiers.kt:4:5:4:18 | getC$main | Method | final | +| modifiers.kt:4:5:4:18 | getC$main | Method | internal | | modifiers.kt:4:5:4:22 | c | Field | final | | modifiers.kt:4:5:4:22 | c | Field | private | | modifiers.kt:4:5:4:22 | c | Property | internal | -| modifiers.kt:4:5:4:22 | getC$main | Method | final | -| modifiers.kt:4:5:4:22 | getC$main | Method | internal | +| modifiers.kt:5:5:5:9 | getD | Method | final | +| modifiers.kt:5:5:5:9 | getD | Method | public | | modifiers.kt:5:5:5:34 | d | Field | final | | modifiers.kt:5:5:5:34 | d | Field | private | | modifiers.kt:5:5:5:34 | d | Property | public | -| modifiers.kt:5:5:5:34 | getD | Method | final | -| modifiers.kt:5:5:5:34 | getD | Method | public | | modifiers.kt:7:5:9:5 | Nested | Class | final | | modifiers.kt:7:5:9:5 | Nested | Class | protected | | modifiers.kt:7:5:9:5 | Nested | Constructor | public | +| modifiers.kt:8:9:8:25 | getE | Method | final | +| modifiers.kt:8:9:8:25 | getE | Method | public | | modifiers.kt:8:9:8:29 | e | Field | final | | modifiers.kt:8:9:8:29 | e | Field | private | | modifiers.kt:8:9:8:29 | e | Property | public | -| modifiers.kt:8:9:8:29 | getE | Method | final | -| modifiers.kt:8:9:8:29 | getE | Method | public | | modifiers.kt:11:5:15:5 | fn1 | Method | final | | modifiers.kt:11:5:15:5 | fn1 | Method | public | | modifiers.kt:12:16:14:9 | | Constructor | public | diff --git a/java/ql/test-kotlin2/library-tests/private-anonymous-types/test.expected b/java/ql/test-kotlin2/library-tests/private-anonymous-types/test.expected index 6eff637457ed..fa622bab6ff8 100644 --- a/java/ql/test-kotlin2/library-tests/private-anonymous-types/test.expected +++ b/java/ql/test-kotlin2/library-tests/private-anonymous-types/test.expected @@ -17,16 +17,16 @@ | test.kt:0:0:0:0 | TestKt | test.kt:24:1:24:38 | user | | test.kt:1:1:5:1 | If | test.kt:3:3:3:11 | getX | | test.kt:7:1:22:1 | A | test.kt:7:16:7:21 | A | +| test.kt:7:1:22:1 | A | test.kt:9:3:9:14 | getAnonType | | test.kt:7:1:22:1 | A | test.kt:9:3:11:3 | anonType | -| test.kt:7:1:22:1 | A | test.kt:9:3:11:3 | getAnonType | -| test.kt:7:1:22:1 | A | test.kt:13:3:15:3 | getPrivateAnonType$private | +| test.kt:7:1:22:1 | A | test.kt:13:3:13:29 | getPrivateAnonType$private | | test.kt:7:1:22:1 | A | test.kt:13:3:15:3 | privateAnonType | | test.kt:7:1:22:1 | A | test.kt:17:3:20:3 | privateUser | | test.kt:9:18:11:3 | new If(...) { ... } | test.kt:9:18:11:3 | | -| test.kt:9:18:11:3 | new If(...) { ... } | test.kt:10:5:10:22 | getX | +| test.kt:9:18:11:3 | new If(...) { ... } | test.kt:10:5:10:18 | getX | | test.kt:9:18:11:3 | new If(...) { ... } | test.kt:10:5:10:22 | x | | test.kt:13:33:15:3 | new If(...) { ... } | test.kt:13:33:15:3 | | -| test.kt:13:33:15:3 | new If(...) { ... } | test.kt:14:5:14:22 | getX | +| test.kt:13:33:15:3 | new If(...) { ... } | test.kt:14:5:14:18 | getX | | test.kt:13:33:15:3 | new If(...) { ... } | test.kt:14:5:14:22 | x | enclosingTypes | file:///!unknown-binary-location/A$.class:0:0:0:0 | new If(...) { ... }<> | file:///!unknown-binary-location/A.class:0:0:0:0 | A | diff --git a/java/ql/test-kotlin2/library-tests/properties/properties.expected b/java/ql/test-kotlin2/library-tests/properties/properties.expected index 3f11ff28185f..6e2d867153ce 100644 --- a/java/ql/test-kotlin2/library-tests/properties/properties.expected +++ b/java/ql/test-kotlin2/library-tests/properties/properties.expected @@ -1,33 +1,33 @@ #select | properties.kt:2:27:2:50 | constructorProp | properties.kt:2:27:2:50 | getConstructorProp | file://:0:0:0:0 | | properties.kt:2:27:2:50 | constructorProp | public | | properties.kt:2:53:2:83 | mutableConstructorProp | properties.kt:2:53:2:83 | getMutableConstructorProp | properties.kt:2:53:2:83 | setMutableConstructorProp | properties.kt:2:53:2:83 | mutableConstructorProp | public | -| properties.kt:3:5:3:25 | modifiableInt | properties.kt:3:5:3:25 | getModifiableInt | properties.kt:3:5:3:25 | setModifiableInt | properties.kt:3:5:3:25 | modifiableInt | public | -| properties.kt:4:5:4:24 | immutableInt | properties.kt:4:5:4:24 | getImmutableInt | file://:0:0:0:0 | | properties.kt:4:5:4:24 | immutableInt | public | -| properties.kt:5:5:5:26 | typedProp | properties.kt:5:5:5:26 | getTypedProp | file://:0:0:0:0 | | properties.kt:5:5:5:26 | typedProp | public | +| properties.kt:3:5:3:25 | modifiableInt | properties.kt:3:5:3:21 | getModifiableInt | properties.kt:3:5:3:21 | setModifiableInt | properties.kt:3:5:3:25 | modifiableInt | public | +| properties.kt:4:5:4:24 | immutableInt | properties.kt:4:5:4:20 | getImmutableInt | file://:0:0:0:0 | | properties.kt:4:5:4:24 | immutableInt | public | +| properties.kt:5:5:5:26 | typedProp | properties.kt:5:5:5:22 | getTypedProp | file://:0:0:0:0 | | properties.kt:5:5:5:26 | typedProp | public | | properties.kt:6:5:6:38 | abstractTypeProp | properties.kt:6:5:6:38 | getAbstractTypeProp | file://:0:0:0:0 | | file://:0:0:0:0 | | public | | properties.kt:7:5:7:30 | initialisedInInit | properties.kt:7:5:7:30 | getInitialisedInInit | file://:0:0:0:0 | | properties.kt:7:5:7:30 | initialisedInInit | public | -| properties.kt:11:5:11:40 | useConstructorArg | properties.kt:11:5:11:40 | getUseConstructorArg | file://:0:0:0:0 | | properties.kt:11:5:11:40 | useConstructorArg | public | +| properties.kt:11:5:11:40 | useConstructorArg | properties.kt:11:5:11:25 | getUseConstructorArg | file://:0:0:0:0 | | properties.kt:11:5:11:40 | useConstructorArg | public | | properties.kt:12:5:13:21 | five | properties.kt:13:13:13:21 | getFive | file://:0:0:0:0 | | file://:0:0:0:0 | | public | | properties.kt:14:5:15:21 | six | properties.kt:15:13:15:21 | getSix | file://:0:0:0:0 | | file://:0:0:0:0 | | public | | properties.kt:16:5:18:40 | getSet | properties.kt:17:13:17:33 | getGetSet | properties.kt:18:13:18:40 | setGetSet | file://:0:0:0:0 | | public | | properties.kt:19:5:20:15 | defaultGetter | properties.kt:20:13:20:15 | getDefaultGetter | file://:0:0:0:0 | | properties.kt:19:5:20:15 | defaultGetter | public | -| properties.kt:21:5:22:15 | varDefaultGetter | properties.kt:22:13:22:15 | getVarDefaultGetter | properties.kt:21:5:22:15 | setVarDefaultGetter | properties.kt:21:5:22:15 | varDefaultGetter | public | -| properties.kt:23:5:24:15 | varDefaultSetter | properties.kt:23:5:24:15 | getVarDefaultSetter | properties.kt:24:13:24:15 | setVarDefaultSetter | properties.kt:23:5:24:15 | varDefaultSetter | public | +| properties.kt:21:5:22:15 | varDefaultGetter | properties.kt:22:13:22:15 | getVarDefaultGetter | properties.kt:21:5:21:24 | setVarDefaultGetter | properties.kt:21:5:22:15 | varDefaultGetter | public | +| properties.kt:23:5:24:15 | varDefaultSetter | properties.kt:23:5:23:24 | getVarDefaultSetter | properties.kt:24:13:24:15 | setVarDefaultSetter | properties.kt:23:5:24:15 | varDefaultSetter | public | | properties.kt:25:5:27:15 | varDefaultGetterSetter | properties.kt:26:13:26:15 | getVarDefaultGetterSetter | properties.kt:27:13:27:15 | setVarDefaultGetterSetter | properties.kt:25:5:27:15 | varDefaultGetterSetter | public | -| properties.kt:28:5:29:22 | overrideGetter | properties.kt:29:13:29:22 | getOverrideGetter | properties.kt:28:5:29:22 | setOverrideGetter | properties.kt:28:5:29:22 | overrideGetter | public | -| properties.kt:30:5:31:29 | overrideGetterUseField | properties.kt:31:13:31:29 | getOverrideGetterUseField | properties.kt:30:5:31:29 | setOverrideGetterUseField | properties.kt:30:5:31:29 | overrideGetterUseField | public | +| properties.kt:28:5:29:22 | overrideGetter | properties.kt:29:13:29:22 | getOverrideGetter | properties.kt:28:5:28:22 | setOverrideGetter | properties.kt:28:5:29:22 | overrideGetter | public | +| properties.kt:30:5:31:29 | overrideGetterUseField | properties.kt:31:13:31:29 | getOverrideGetterUseField | properties.kt:30:5:30:30 | setOverrideGetterUseField | properties.kt:30:5:31:29 | overrideGetterUseField | public | | properties.kt:32:5:33:29 | useField | properties.kt:33:13:33:29 | getUseField | file://:0:0:0:0 | | properties.kt:32:5:33:29 | useField | public | | properties.kt:34:5:34:36 | lateInitVar | properties.kt:34:5:34:36 | getLateInitVar | properties.kt:34:5:34:36 | setLateInitVar | properties.kt:34:5:34:36 | lateInitVar | lateinit, public | -| properties.kt:35:5:35:32 | privateProp | properties.kt:35:5:35:32 | getPrivateProp$private | file://:0:0:0:0 | | properties.kt:35:5:35:32 | privateProp | private | -| properties.kt:36:5:36:36 | protectedProp | properties.kt:36:5:36:36 | getProtectedProp | file://:0:0:0:0 | | properties.kt:36:5:36:36 | protectedProp | protected | -| properties.kt:37:5:37:30 | publicProp | properties.kt:37:5:37:30 | getPublicProp | file://:0:0:0:0 | | properties.kt:37:5:37:30 | publicProp | public | -| properties.kt:38:5:38:34 | internalProp | properties.kt:38:5:38:34 | getInternalProp$main | file://:0:0:0:0 | | properties.kt:38:5:38:34 | internalProp | internal | -| properties.kt:67:1:67:23 | constVal | properties.kt:67:1:67:23 | getConstVal | file://:0:0:0:0 | | properties.kt:67:1:67:23 | constVal | public | -| properties.kt:70:5:70:16 | prop | properties.kt:70:5:70:16 | getProp | file://:0:0:0:0 | | properties.kt:70:5:70:16 | prop | public | +| properties.kt:35:5:35:32 | privateProp | properties.kt:35:5:35:27 | getPrivateProp$private | file://:0:0:0:0 | | properties.kt:35:5:35:32 | privateProp | private | +| properties.kt:36:5:36:36 | protectedProp | properties.kt:36:5:36:31 | getProtectedProp | file://:0:0:0:0 | | properties.kt:36:5:36:36 | protectedProp | protected | +| properties.kt:37:5:37:30 | publicProp | properties.kt:37:5:37:25 | getPublicProp | file://:0:0:0:0 | | properties.kt:37:5:37:30 | publicProp | public | +| properties.kt:38:5:38:34 | internalProp | properties.kt:38:5:38:29 | getInternalProp$main | file://:0:0:0:0 | | properties.kt:38:5:38:34 | internalProp | internal | +| properties.kt:67:1:67:23 | constVal | properties.kt:67:1:67:18 | getConstVal | file://:0:0:0:0 | | properties.kt:67:1:67:23 | constVal | public | +| properties.kt:70:5:70:16 | prop | properties.kt:70:5:70:12 | getProp | file://:0:0:0:0 | | properties.kt:70:5:70:16 | prop | public | | properties.kt:78:1:79:13 | x | properties.kt:79:5:79:13 | getX | file://:0:0:0:0 | | file://:0:0:0:0 | | public | | properties.kt:80:1:81:13 | x | properties.kt:81:5:81:13 | getX | file://:0:0:0:0 | | file://:0:0:0:0 | | public | -| properties.kt:84:5:84:29 | data | properties.kt:84:5:84:29 | getData$private | properties.kt:84:5:84:29 | setData$private | properties.kt:84:5:84:29 | data | private | -| properties.kt:92:5:93:18 | data | properties.kt:93:9:93:18 | getData | properties.kt:92:5:93:18 | setData$private | properties.kt:92:5:93:18 | data | private | +| properties.kt:84:5:84:29 | data | properties.kt:84:5:84:25 | getData$private | properties.kt:84:5:84:25 | setData$private | properties.kt:84:5:84:29 | data | private | +| properties.kt:92:5:93:18 | data | properties.kt:93:9:93:18 | getData | properties.kt:92:5:92:25 | setData$private | properties.kt:92:5:93:18 | data | private | fieldDeclarations | properties.kt:2:27:2:50 | int constructorProp; | properties.kt:2:27:2:50 | constructorProp | 0 | | properties.kt:2:53:2:83 | int mutableConstructorProp; | properties.kt:2:53:2:83 | mutableConstructorProp | 0 | diff --git a/java/ql/test-kotlin2/library-tests/reflection/reflection.expected b/java/ql/test-kotlin2/library-tests/reflection/reflection.expected index 92b20bcae778..4074866da65f 100644 --- a/java/ql/test-kotlin2/library-tests/reflection/reflection.expected +++ b/java/ql/test-kotlin2/library-tests/reflection/reflection.expected @@ -59,10 +59,10 @@ functionReferences | reflection.kt:154:33:154:61 | ...::... | reflection.kt:154:33:154:61 | invoke | reflection.kt:154:33:154:61 | extTakesOptionalParam | | reflection.kt:162:25:162:45 | ...::... | reflection.kt:162:25:162:45 | invoke | reflection.kt:162:25:162:45 | | propertyGetReferences -| reflection.kt:10:38:10:42 | ...::... | reflection.kt:10:38:10:42 | get | reflection.kt:33:9:33:23 | getP0 | -| reflection.kt:15:35:15:41 | ...::... | reflection.kt:15:35:15:41 | get | reflection.kt:33:9:33:23 | getP0 | -| reflection.kt:17:45:17:49 | ...::... | reflection.kt:17:45:17:49 | get | reflection.kt:34:9:34:23 | getP1 | -| reflection.kt:22:42:22:48 | ...::... | reflection.kt:22:42:22:48 | get | reflection.kt:34:9:34:23 | getP1 | +| reflection.kt:10:38:10:42 | ...::... | reflection.kt:10:38:10:42 | get | reflection.kt:33:9:33:19 | getP0 | +| reflection.kt:15:35:15:41 | ...::... | reflection.kt:15:35:15:41 | get | reflection.kt:33:9:33:19 | getP0 | +| reflection.kt:17:45:17:49 | ...::... | reflection.kt:17:45:17:49 | get | reflection.kt:34:9:34:19 | getP1 | +| reflection.kt:22:42:22:48 | ...::... | reflection.kt:22:42:22:48 | get | reflection.kt:34:9:34:19 | getP1 | | reflection.kt:50:13:50:28 | ...::... | reflection.kt:50:13:50:28 | get | reflection.kt:47:5:47:28 | getLastChar | | reflection.kt:51:13:51:28 | ...::... | reflection.kt:51:13:51:28 | get | reflection.kt:47:5:47:28 | getLastChar | | reflection.kt:67:17:67:32 | ...::... | reflection.kt:67:17:67:32 | get | file:///Class1$Generic.class:0:0:0:0 | getP2 | @@ -73,8 +73,8 @@ propertyFieldReferences | reflection.kt:71:17:71:34 | ...::... | reflection.kt:71:17:71:34 | get | file:///modules/java.base/java/lang/Integer.class:0:0:0:0 | MAX_VALUE | | reflection.kt:72:17:72:35 | ...::... | reflection.kt:72:17:72:35 | get | file:///modules/java.desktop/java/awt/Rectangle.class:0:0:0:0 | height | propertySetReferences -| reflection.kt:17:45:17:49 | ...::... | reflection.kt:17:45:17:49 | set | reflection.kt:34:9:34:23 | setP1 | -| reflection.kt:22:42:22:48 | ...::... | reflection.kt:22:42:22:48 | set | reflection.kt:34:9:34:23 | setP1 | +| reflection.kt:17:45:17:49 | ...::... | reflection.kt:17:45:17:49 | set | reflection.kt:34:9:34:19 | setP1 | +| reflection.kt:22:42:22:48 | ...::... | reflection.kt:22:42:22:48 | set | reflection.kt:34:9:34:19 | setP1 | | reflection.kt:67:17:67:32 | ...::... | reflection.kt:67:17:67:32 | set | file:///Class1$Generic.class:0:0:0:0 | setP2 | | reflection.kt:68:17:68:34 | ...::... | reflection.kt:68:17:68:34 | set | file:///Class1$Generic.class:0:0:0:0 | setP2 | | reflection.kt:109:17:109:27 | ...::... | reflection.kt:109:17:109:27 | set | reflection.kt:105:18:105:31 | setProp1 | @@ -346,9 +346,9 @@ compGenerated | reflection.kt:21:44:21:50 | new Function2(...) { ... } | The class around a local function, a lambda, or a function reference | | reflection.kt:22:42:22:48 | new KMutableProperty0(...) { ... } | The class around a local function, a lambda, or a function reference | | reflection.kt:24:46:24:64 | new Function1,Boolean>(...) { ... } | The class around a local function, a lambda, or a function reference | -| reflection.kt:33:9:33:23 | getP0 | Default property accessor | -| reflection.kt:34:9:34:23 | getP1 | Default property accessor | -| reflection.kt:34:9:34:23 | setP1 | Default property accessor | +| reflection.kt:33:9:33:19 | getP0 | Default property accessor | +| reflection.kt:34:9:34:19 | getP1 | Default property accessor | +| reflection.kt:34:9:34:19 | setP1 | Default property accessor | | reflection.kt:50:13:50:28 | new KProperty1(...) { ... } | The class around a local function, a lambda, or a function reference | | reflection.kt:51:13:51:28 | new KProperty0(...) { ... } | The class around a local function, a lambda, or a function reference | | reflection.kt:60:17:60:32 | new Function2,Integer,String>(...) { ... } | The class around a local function, a lambda, or a function reference | diff --git a/java/ql/test-kotlin2/library-tests/variables/variableAccesses.expected b/java/ql/test-kotlin2/library-tests/variables/variableAccesses.expected index 5c3960f19b3e..360be0d0fe51 100644 --- a/java/ql/test-kotlin2/library-tests/variables/variableAccesses.expected +++ b/java/ql/test-kotlin2/library-tests/variables/variableAccesses.expected @@ -1,11 +1,11 @@ varAcc +| variables.kt:3:5:3:17 | this.prop | | variables.kt:3:5:3:21 | prop | -| variables.kt:3:5:3:21 | this.prop | | variables.kt:7:17:7:22 | local1 | | variables.kt:9:17:9:22 | local2 | | variables.kt:10:22:10:26 | param | | variables.kt:11:17:11:22 | local3 | -| variables.kt:15:1:15:21 | VariablesKt.topLevel | +| variables.kt:15:1:15:17 | VariablesKt.topLevel | | variables.kt:15:1:15:21 | VariablesKt.topLevel | | variables.kt:21:11:21:18 | o | | variables.kt:21:11:21:18 | o | @@ -20,7 +20,7 @@ extensionReceiverAcc | variables.kt:32:9:32:12 | this | | variables.kt:33:9:33:12 | this | instAcc -| variables.kt:3:5:3:21 | this | +| variables.kt:3:5:3:17 | this | | variables.kt:21:11:21:18 | this | | variables.kt:26:9:26:9 | this | | variables.kt:26:9:26:15 | this | diff --git a/java/ql/test-kotlin2/library-tests/variables/variables.expected b/java/ql/test-kotlin2/library-tests/variables/variables.expected index 0022c22ed8b1..1f562ccceac9 100644 --- a/java/ql/test-kotlin2/library-tests/variables/variables.expected +++ b/java/ql/test-kotlin2/library-tests/variables/variables.expected @@ -13,8 +13,8 @@ isFinal | variables.kt:8:9:8:26 | int local2 | non-final | | variables.kt:10:9:10:26 | int local3 | final | compileTimeConstant +| variables.kt:3:5:3:17 | this.prop | | variables.kt:3:5:3:21 | prop | -| variables.kt:3:5:3:21 | this.prop | | variables.kt:7:17:7:22 | local1 | -| variables.kt:15:1:15:21 | VariablesKt.topLevel | +| variables.kt:15:1:15:17 | VariablesKt.topLevel | | variables.kt:15:1:15:21 | VariablesKt.topLevel | From 0d34837eaffcbc8606efcaf6ad41dd5390d9ac3c Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 29 Apr 2025 13:59:57 +0100 Subject: [PATCH 330/336] Bump unit tests to use latest stable Kotlin --- java/kotlin-extractor/dev/wrapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/kotlin-extractor/dev/wrapper.py b/java/kotlin-extractor/dev/wrapper.py index f95a89352fc3..08969528c926 100755 --- a/java/kotlin-extractor/dev/wrapper.py +++ b/java/kotlin-extractor/dev/wrapper.py @@ -27,7 +27,7 @@ import io import os -DEFAULT_VERSION = "2.2.0-Beta1" +DEFAULT_VERSION = "2.1.20" def options(): From fc1fd263dfedd3376bd3afaabcb9066908eae2d9 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 29 Apr 2025 16:04:47 +0100 Subject: [PATCH 331/336] Fix plugin test to work with Kotlin 2.1.20 --- .../kotlin/linux/custom_plugin/plugin/Plugin.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/java/ql/integration-tests/kotlin/linux/custom_plugin/plugin/Plugin.kt b/java/ql/integration-tests/kotlin/linux/custom_plugin/plugin/Plugin.kt index f45b48043930..422d84deedb0 100644 --- a/java/ql/integration-tests/kotlin/linux/custom_plugin/plugin/Plugin.kt +++ b/java/ql/integration-tests/kotlin/linux/custom_plugin/plugin/Plugin.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.fromSymbolOwner import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.symbols.IrClassSymbol From 27222499d41f2f7ef3799ddad34e0735c2351cd0 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 29 Apr 2025 16:19:53 +0100 Subject: [PATCH 332/336] Update test expectation --- .../test-kotlin2/library-tests/numlines/callable.expected | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/test-kotlin2/library-tests/numlines/callable.expected b/java/ql/test-kotlin2/library-tests/numlines/callable.expected index 52f3a4f2cbe8..ca6371ce23e0 100644 --- a/java/ql/test-kotlin2/library-tests/numlines/callable.expected +++ b/java/ql/test-kotlin2/library-tests/numlines/callable.expected @@ -1,6 +1,6 @@ | test.kt:2:1:4:1 | foo | 3 | 3 | 0 | -| test.kt:8:1:8:9 | getX | 1 | 1 | 0 | -| test.kt:18:1:18:17 | getY | 5 | 1 | 4 | +| test.kt:8:1:8:5 | getX | 1 | 1 | 0 | +| test.kt:18:1:18:5 | getY | 5 | 1 | 4 | | test.kt:20:1:26:1 | Foo | 7 | 6 | 1 | | test.kt:21:5:24:5 | bar | 4 | 3 | 1 | -| test.kt:25:5:25:21 | getSomeField | 1 | 1 | 0 | +| test.kt:25:5:25:17 | getSomeField | 1 | 1 | 0 | From a2836f5aabf764c6e6dde769f497d8686a82c11b Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 29 Apr 2025 16:21:45 +0100 Subject: [PATCH 333/336] Adjust integration test expectations --- .../all-platforms/private_property_accessors/test.expected | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/integration-tests/kotlin/all-platforms/private_property_accessors/test.expected b/java/ql/integration-tests/kotlin/all-platforms/private_property_accessors/test.expected index 903b49c91f67..5c22734fee52 100644 --- a/java/ql/integration-tests/kotlin/all-platforms/private_property_accessors/test.expected +++ b/java/ql/integration-tests/kotlin/all-platforms/private_property_accessors/test.expected @@ -1,6 +1,6 @@ -| hasprops.kt:3:3:3:25 | getAccessorsPublic | -| hasprops.kt:3:3:3:25 | setAccessorsPublic | -| hasprops.kt:5:3:6:15 | getSetterPrivate | +| hasprops.kt:3:3:3:21 | getAccessorsPublic | +| hasprops.kt:3:3:3:21 | setAccessorsPublic | +| hasprops.kt:5:3:5:19 | getSetterPrivate | | hasprops.kt:6:5:6:15 | setSetterPrivate$private | | usesprops.kt:1:1:9:1 | user | | usesprops.kt:3:3:3:58 | useGetters | From 3001d0bd1c36792f865632d034d10695644f5d0a Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Mon, 28 Apr 2025 10:22:11 +0200 Subject: [PATCH 334/336] Bazel: remove `2.0.0` `rules_kotlin` patching --- .../rules_kotlin/2.0.0-codeql.1/MODULE.bazel | 35 ------------------- .../codeql_add_language_version_option.patch | 34 ------------------ .../patches/codeql_do_not_emit_jdeps.patch | 16 --------- .../rules_kotlin/2.0.0-codeql.1/source.json | 9 ----- .../modules/rules_kotlin/metadata.json | 3 +- 5 files changed, 1 insertion(+), 96 deletions(-) delete mode 100644 misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/MODULE.bazel delete mode 100644 misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_add_language_version_option.patch delete mode 100644 misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_do_not_emit_jdeps.patch delete mode 100644 misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/source.json diff --git a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/MODULE.bazel b/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/MODULE.bazel deleted file mode 100644 index 6c11301e2340..000000000000 --- a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/MODULE.bazel +++ /dev/null @@ -1,35 +0,0 @@ -module( - name = "rules_kotlin", - version = "2.0.0-codeql.1", - compatibility_level = 1, - repo_name = "rules_kotlin", -) - -bazel_dep(name = "platforms", version = "0.0.10") -bazel_dep(name = "bazel_skylib", version = "1.7.1") -bazel_dep(name = "rules_java", version = "7.2.0") -bazel_dep(name = "rules_python", version = "0.23.1") -bazel_dep(name = "rules_cc", version = "0.0.8") -bazel_dep(name = "rules_android", version = "0.1.1") - -rules_kotlin_extensions = use_extension( - "//src/main/starlark/core/repositories:bzlmod_setup.bzl", - "rules_kotlin_extensions", -) -use_repo( - rules_kotlin_extensions, - "com_github_google_ksp", - "com_github_jetbrains_kotlin", - "com_github_pinterest_ktlint", - "kotlinx_serialization_core_jvm", - "kotlinx_serialization_json", - "kotlinx_serialization_json_jvm", -) - -register_toolchains("//kotlin/internal:default_toolchain") - -# TODO(bencodes) We should be able to remove this once rules_android has rolled out official Bzlmod support -remote_android_extensions = use_extension("@bazel_tools//tools/android:android_extensions.bzl", "remote_android_tools_extensions") -use_repo(remote_android_extensions, "android_gmaven_r8", "android_tools") - -bazel_dep(name = "rules_proto", version = "5.3.0-21.7") diff --git a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_add_language_version_option.patch b/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_add_language_version_option.patch deleted file mode 100644 index d5716daba07b..000000000000 --- a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_add_language_version_option.patch +++ /dev/null @@ -1,34 +0,0 @@ -We need to build different extractor variants with different -language-version options, which is not allowed -in current kotlin_rules -diff --git a/src/main/starlark/core/options/opts.kotlinc.bzl b/src/main/starlark/core/options/opts.kotlinc.bzl -index 5e1461b..b93e6aa 100644 ---- a/src/main/starlark/core/options/opts.kotlinc.bzl -+++ b/src/main/starlark/core/options/opts.kotlinc.bzl -@@ -33,6 +33,11 @@ def _map_jdk_release_to_flag(version): - return None - return ["-Xjdk-release=%s" % version] - -+def _map_language_version_to_flag(version): -+ if not version: -+ return None -+ return ["-language-version=%s" % version, "-api-version=%s" % version] -+ - _KOPTS_ALL = { - "warn": struct( - args = dict( -@@ -417,6 +422,15 @@ _KOPTS_ALL = { - value_to_flag = None, - map_value_to_flag = _map_jdk_release_to_flag, - ), -+ "language_version": struct( -+ args = dict( -+ default = "1.9", -+ doc = "-language-version", -+ ), -+ type = attr.string, -+ value_to_flag = None, -+ map_value_to_flag = _map_language_version_to_flag, -+ ), - } - - # Filters out options that are not available in current compiler release \ No newline at end of file diff --git a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_do_not_emit_jdeps.patch b/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_do_not_emit_jdeps.patch deleted file mode 100644 index 380c837d06a4..000000000000 --- a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/patches/codeql_do_not_emit_jdeps.patch +++ /dev/null @@ -1,16 +0,0 @@ -Emitting jdeps is broken for the 2.0.0 kotlin extractor, and we don't need those files. -Patching it here rather than passing `--@rules_kotlin//kotlin/settings:jvm_emit_jdeps=false` -allows us to not have to specify that option (and therefore pull in `rules_kotlin`) in `semmle-code`. -diff --git a/kotlin/settings/BUILD.bazel b/kotlin/settings/BUILD.bazel -index 2c93c11..f352b80 100644 ---- a/kotlin/settings/BUILD.bazel -+++ b/kotlin/settings/BUILD.bazel -@@ -25,7 +25,7 @@ release_archive( - # Flag that controls the emission of jdeps files during kotlin jvm compilation. - bool_flag( - name = "jvm_emit_jdeps", -- build_setting_default = True, # Upstream default behavior -+ build_setting_default = False, - visibility = ["//visibility:public"], - ) - diff --git a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/source.json b/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/source.json deleted file mode 100644 index 96d828e3455a..000000000000 --- a/misc/bazel/registry/modules/rules_kotlin/2.0.0-codeql.1/source.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "integrity": "sha256-2JcjzJ67t72y66yhr30jg+B0YVZDz5ejZrdYp2t9xEM=", - "url": "https://github.com/bazelbuild/rules_kotlin/releases/download/v2.0.0/rules_kotlin-v2.0.0.tar.gz", - "patches": { - "codeql_do_not_emit_jdeps.patch": "sha256-1ir4Aio1SICxnj1wafQ0GefT/m7bwn2n+SQwq19V3A8=", - "codeql_add_language_version_option.patch": "sha256-t8Fm0bYZ4Q4vTqcoXZjyK4WPEoAafjE4whJLNnrnRbg=" - }, - "patch_strip": 1 -} diff --git a/misc/bazel/registry/modules/rules_kotlin/metadata.json b/misc/bazel/registry/modules/rules_kotlin/metadata.json index 3e11b7df8202..dace87c72d1c 100644 --- a/misc/bazel/registry/modules/rules_kotlin/metadata.json +++ b/misc/bazel/registry/modules/rules_kotlin/metadata.json @@ -21,8 +21,7 @@ "github:bazelbuild/rules_kotlin" ], "versions": [ - "2.1.3-codeql.1", - "2.0.0-codeql.1" + "2.1.3-codeql.1" ], "yanked_versions": {} } From fecad025ded53cfb8be6cc92506549029ae64a12 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 13 May 2025 18:10:21 +0100 Subject: [PATCH 335/336] Fix handling of X/jvm-default intermediate modes such as 'compatibility', the new default as of 2.2.0 --- .../src/main/kotlin/KotlinFileExtractor.kt | 4 ++-- .../kotlin/utils/versions/v_1_5_0/JvmDefaultModeEnabled.kt | 7 ------- .../versions/v_1_5_0/JvmDefaultModeIsNoCompatibility.kt | 7 +++++++ .../utils/versions/v_2_0_0-RC1/JvmDefaultModeEnabled.kt | 7 ------- .../v_2_0_0-RC1/JvmDefaultModeIsNoCompatibility.kt | 7 +++++++ .../v_2_2_0-Beta1/JvmDefaultModeIsNoCompatibility.kt | 7 +++++++ 6 files changed, 23 insertions(+), 16 deletions(-) delete mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/JvmDefaultModeEnabled.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/JvmDefaultModeIsNoCompatibility.kt delete mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_0_0-RC1/JvmDefaultModeEnabled.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_0_0-RC1/JvmDefaultModeIsNoCompatibility.kt create mode 100644 java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/JvmDefaultModeIsNoCompatibility.kt diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index ab3d3f69e91c..690372d67f51 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1608,7 +1608,7 @@ open class KotlinFileExtractor( cls.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB private fun needsInterfaceForwarder(f: IrFunction) = - // jvmDefaultModeEnabledIsEnabled means that -Xjvm-default=all or all-compatibility was + // jvmDefaultModeIsNoCompatibility means that -Xjvm-default=all or =no-compatibility was // used, in which case real Java default interfaces are used, and we don't need to do // anything. // Otherwise, for a Kotlin-defined method inheriting a Kotlin-defined default, we need to @@ -1618,7 +1618,7 @@ open class KotlinFileExtractor( // (NB. kotlinc's actual implementation strategy is different -- it makes an inner class // called InterfaceWithDefault$DefaultImpls and stores the default methods // there to allow default method usage in Java < 8, but this is hopefully niche. - !jvmDefaultModeEnabledIsEnabled(getJvmDefaultMode(pluginContext.languageVersionSettings)) && + !jvmDefaultModeIsNoCompatibility(getJvmDefaultMode(pluginContext.languageVersionSettings)) && f.parentClassOrNull.let { it != null && it.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/JvmDefaultModeEnabled.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/JvmDefaultModeEnabled.kt deleted file mode 100644 index cd8496526137..000000000000 --- a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/JvmDefaultModeEnabled.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.github.codeql.utils.versions - -import org.jetbrains.kotlin.config.JvmDefaultMode - -fun jvmDefaultModeEnabledIsEnabled(jdm: JvmDefaultMode): Boolean { - return jdm.forAllMethodsWithBody -} diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/JvmDefaultModeIsNoCompatibility.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/JvmDefaultModeIsNoCompatibility.kt new file mode 100644 index 000000000000..feda11b0cc02 --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_1_5_0/JvmDefaultModeIsNoCompatibility.kt @@ -0,0 +1,7 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.config.JvmDefaultMode + +fun jvmDefaultModeIsNoCompatibility(jdm: JvmDefaultMode): Boolean { + return jdm == JvmDefaultMode.ALL_INCOMPATIBLE +} diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_0_0-RC1/JvmDefaultModeEnabled.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_0_0-RC1/JvmDefaultModeEnabled.kt deleted file mode 100644 index 10a936ed9096..000000000000 --- a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_0_0-RC1/JvmDefaultModeEnabled.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.github.codeql.utils.versions - -import org.jetbrains.kotlin.config.JvmDefaultMode - -fun jvmDefaultModeEnabledIsEnabled(jdm: JvmDefaultMode): Boolean { - return jdm.isEnabled -} diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_0_0-RC1/JvmDefaultModeIsNoCompatibility.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_0_0-RC1/JvmDefaultModeIsNoCompatibility.kt new file mode 100644 index 000000000000..7f66c341b01c --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_0_0-RC1/JvmDefaultModeIsNoCompatibility.kt @@ -0,0 +1,7 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.config.JvmDefaultMode + +fun jvmDefaultModeIsNoCompatibility(jdm: JvmDefaultMode): Boolean { + return jdm == JvmDefaultMode.ALL +} diff --git a/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/JvmDefaultModeIsNoCompatibility.kt b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/JvmDefaultModeIsNoCompatibility.kt new file mode 100644 index 000000000000..52eac237808b --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/versions/v_2_2_0-Beta1/JvmDefaultModeIsNoCompatibility.kt @@ -0,0 +1,7 @@ +package com.github.codeql.utils.versions + +import org.jetbrains.kotlin.config.JvmDefaultMode + +fun jvmDefaultModeIsNoCompatibility(jdm: JvmDefaultMode): Boolean { + return jdm == JvmDefaultMode.NO_COMPATIBILITY +} From 2de4a01c86e3fe1dcfc11287f0a99a21eb9087fd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 13 May 2025 21:14:27 +0000 Subject: [PATCH 336/336] Release preparation for version 2.21.3 --- actions/ql/lib/CHANGELOG.md | 4 ++++ actions/ql/lib/change-notes/released/0.4.9.md | 3 +++ actions/ql/lib/codeql-pack.release.yml | 2 +- actions/ql/lib/qlpack.yml | 2 +- actions/ql/src/CHANGELOG.md | 4 ++++ actions/ql/src/change-notes/released/0.6.1.md | 3 +++ actions/ql/src/codeql-pack.release.yml | 2 +- actions/ql/src/qlpack.yml | 2 +- cpp/ql/lib/CHANGELOG.md | 6 ++++++ .../4.3.1.md} | 9 +++++---- cpp/ql/lib/codeql-pack.release.yml | 2 +- cpp/ql/lib/qlpack.yml | 2 +- cpp/ql/src/CHANGELOG.md | 11 +++++++++++ .../1.4.0.md} | 7 ++++--- cpp/ql/src/codeql-pack.release.yml | 2 +- cpp/ql/src/qlpack.yml | 2 +- csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md | 4 ++++ .../lib/change-notes/released/1.7.40.md | 3 +++ .../Solorigate/lib/codeql-pack.release.yml | 2 +- csharp/ql/campaigns/Solorigate/lib/qlpack.yml | 2 +- csharp/ql/campaigns/Solorigate/src/CHANGELOG.md | 4 ++++ .../src/change-notes/released/1.7.40.md | 3 +++ .../Solorigate/src/codeql-pack.release.yml | 2 +- csharp/ql/campaigns/Solorigate/src/qlpack.yml | 2 +- csharp/ql/lib/CHANGELOG.md | 4 ++++ csharp/ql/lib/change-notes/released/5.1.6.md | 3 +++ csharp/ql/lib/codeql-pack.release.yml | 2 +- csharp/ql/lib/qlpack.yml | 2 +- csharp/ql/src/CHANGELOG.md | 17 +++++++++++++++++ .../2025-04-28-equality-on-floats-precision.md | 4 ---- .../1.2.0.md} | 10 +++++++--- csharp/ql/src/codeql-pack.release.yml | 2 +- csharp/ql/src/qlpack.yml | 2 +- go/ql/consistency-queries/CHANGELOG.md | 4 ++++ .../change-notes/released/1.0.23.md | 3 +++ .../consistency-queries/codeql-pack.release.yml | 2 +- go/ql/consistency-queries/qlpack.yml | 2 +- go/ql/lib/CHANGELOG.md | 4 ++++ go/ql/lib/change-notes/released/4.2.5.md | 3 +++ go/ql/lib/codeql-pack.release.yml | 2 +- go/ql/lib/qlpack.yml | 2 +- go/ql/src/CHANGELOG.md | 15 +++++++++++++++ .../1.2.0.md} | 6 +++--- go/ql/src/codeql-pack.release.yml | 2 +- go/ql/src/qlpack.yml | 2 +- java/ql/lib/CHANGELOG.md | 6 ++++++ .../7.2.0.md} | 7 ++++--- java/ql/lib/codeql-pack.release.yml | 2 +- java/ql/lib/qlpack.yml | 2 +- java/ql/src/CHANGELOG.md | 8 ++++++++ .../1.5.0.md} | 6 +++--- java/ql/src/codeql-pack.release.yml | 2 +- java/ql/src/qlpack.yml | 2 +- javascript/ql/lib/CHANGELOG.md | 8 ++++++++ .../change-notes/2025-04-14-fastify-addhook.md | 4 ---- .../lib/change-notes/2025-04-30-fastify-all.md | 4 ---- .../ql/lib/change-notes/2025-04-30-shelljs.md | 4 ---- .../ql/lib/change-notes/released/2.6.3.md | 7 +++++++ javascript/ql/lib/codeql-pack.release.yml | 2 +- javascript/ql/lib/qlpack.yml | 2 +- javascript/ql/src/CHANGELOG.md | 14 ++++++++++++++ .../src/change-notes/2025-04-30-promise-all.md | 5 ----- .../1.6.0.md} | 11 ++++++++--- javascript/ql/src/codeql-pack.release.yml | 2 +- javascript/ql/src/qlpack.yml | 2 +- misc/suite-helpers/CHANGELOG.md | 4 ++++ .../change-notes/released/1.0.23.md | 3 +++ misc/suite-helpers/codeql-pack.release.yml | 2 +- misc/suite-helpers/qlpack.yml | 2 +- python/ql/lib/CHANGELOG.md | 7 +++++++ .../2025-04-30-model-send-header.md | 4 ---- python/ql/lib/change-notes/2025-05-01-hdbcli.md | 4 ---- python/ql/lib/change-notes/released/4.0.7.md | 6 ++++++ python/ql/lib/codeql-pack.release.yml | 2 +- python/ql/lib/qlpack.yml | 2 +- python/ql/src/CHANGELOG.md | 11 +++++++++++ .../1.5.0.md} | 6 +++--- python/ql/src/codeql-pack.release.yml | 2 +- python/ql/src/qlpack.yml | 2 +- ruby/ql/lib/CHANGELOG.md | 4 ++++ ruby/ql/lib/change-notes/released/4.1.6.md | 3 +++ ruby/ql/lib/codeql-pack.release.yml | 2 +- ruby/ql/lib/qlpack.yml | 2 +- ruby/ql/src/CHANGELOG.md | 7 +++++++ ...seless-assignment-to-local-precision-high.md | 5 ----- .../1.3.0.md} | 7 ++++--- ruby/ql/src/codeql-pack.release.yml | 2 +- ruby/ql/src/qlpack.yml | 2 +- rust/ql/lib/CHANGELOG.md | 4 ++++ rust/ql/lib/change-notes/released/0.1.8.md | 3 +++ rust/ql/lib/codeql-pack.release.yml | 2 +- rust/ql/lib/qlpack.yml | 2 +- rust/ql/src/CHANGELOG.md | 4 ++++ rust/ql/src/change-notes/released/0.1.8.md | 3 +++ rust/ql/src/codeql-pack.release.yml | 2 +- rust/ql/src/qlpack.yml | 2 +- shared/controlflow/CHANGELOG.md | 4 ++++ .../controlflow/change-notes/released/2.0.7.md | 3 +++ shared/controlflow/codeql-pack.release.yml | 2 +- shared/controlflow/qlpack.yml | 2 +- shared/dataflow/CHANGELOG.md | 4 ++++ shared/dataflow/change-notes/released/2.0.7.md | 3 +++ shared/dataflow/codeql-pack.release.yml | 2 +- shared/dataflow/qlpack.yml | 2 +- shared/mad/CHANGELOG.md | 4 ++++ shared/mad/change-notes/released/1.0.23.md | 3 +++ shared/mad/codeql-pack.release.yml | 2 +- shared/mad/qlpack.yml | 2 +- shared/quantum/CHANGELOG.md | 3 +++ shared/quantum/change-notes/released/0.0.1.md | 3 +++ shared/quantum/codeql-pack.release.yml | 2 ++ shared/quantum/qlpack.yml | 2 +- shared/rangeanalysis/CHANGELOG.md | 4 ++++ .../change-notes/released/1.0.23.md | 3 +++ shared/rangeanalysis/codeql-pack.release.yml | 2 +- shared/rangeanalysis/qlpack.yml | 2 +- shared/regex/CHANGELOG.md | 4 ++++ shared/regex/change-notes/released/1.0.23.md | 3 +++ shared/regex/codeql-pack.release.yml | 2 +- shared/regex/qlpack.yml | 2 +- shared/ssa/CHANGELOG.md | 4 ++++ shared/ssa/change-notes/released/1.1.2.md | 3 +++ shared/ssa/codeql-pack.release.yml | 2 +- shared/ssa/qlpack.yml | 2 +- shared/threat-models/CHANGELOG.md | 4 ++++ .../change-notes/released/1.0.23.md | 3 +++ shared/threat-models/codeql-pack.release.yml | 2 +- shared/threat-models/qlpack.yml | 2 +- shared/tutorial/CHANGELOG.md | 4 ++++ shared/tutorial/change-notes/released/1.0.23.md | 3 +++ shared/tutorial/codeql-pack.release.yml | 2 +- shared/tutorial/qlpack.yml | 2 +- shared/typeflow/CHANGELOG.md | 4 ++++ shared/typeflow/change-notes/released/1.0.23.md | 3 +++ shared/typeflow/codeql-pack.release.yml | 2 +- shared/typeflow/qlpack.yml | 2 +- shared/typeinference/CHANGELOG.md | 4 ++++ .../change-notes/released/0.0.4.md | 3 +++ shared/typeinference/codeql-pack.release.yml | 2 +- shared/typeinference/qlpack.yml | 2 +- shared/typetracking/CHANGELOG.md | 4 ++++ .../typetracking/change-notes/released/2.0.7.md | 3 +++ shared/typetracking/codeql-pack.release.yml | 2 +- shared/typetracking/qlpack.yml | 2 +- shared/typos/CHANGELOG.md | 4 ++++ shared/typos/change-notes/released/1.0.23.md | 3 +++ shared/typos/codeql-pack.release.yml | 2 +- shared/typos/qlpack.yml | 2 +- shared/util/CHANGELOG.md | 4 ++++ shared/util/change-notes/released/2.0.10.md | 3 +++ shared/util/codeql-pack.release.yml | 2 +- shared/util/qlpack.yml | 2 +- shared/xml/CHANGELOG.md | 4 ++++ shared/xml/change-notes/released/1.0.23.md | 3 +++ shared/xml/codeql-pack.release.yml | 2 +- shared/xml/qlpack.yml | 2 +- shared/yaml/CHANGELOG.md | 4 ++++ shared/yaml/change-notes/released/1.0.23.md | 3 +++ shared/yaml/codeql-pack.release.yml | 2 +- shared/yaml/qlpack.yml | 2 +- swift/ql/lib/CHANGELOG.md | 6 ++++++ .../4.3.0.md} | 7 ++++--- swift/ql/lib/codeql-pack.release.yml | 2 +- swift/ql/lib/qlpack.yml | 2 +- swift/ql/src/CHANGELOG.md | 4 ++++ swift/ql/src/change-notes/released/1.1.3.md | 3 +++ swift/ql/src/codeql-pack.release.yml | 2 +- swift/ql/src/qlpack.yml | 2 +- 168 files changed, 450 insertions(+), 144 deletions(-) create mode 100644 actions/ql/lib/change-notes/released/0.4.9.md create mode 100644 actions/ql/src/change-notes/released/0.6.1.md rename cpp/ql/lib/change-notes/{2025-05-13-range-analysis-infinite-loop.md => released/4.3.1.md} (76%) rename cpp/ql/src/change-notes/{2025-05-01-cwe-tag-changed.md => released/1.4.0.md} (95%) create mode 100644 csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.7.40.md create mode 100644 csharp/ql/campaigns/Solorigate/src/change-notes/released/1.7.40.md create mode 100644 csharp/ql/lib/change-notes/released/5.1.6.md delete mode 100644 csharp/ql/src/change-notes/2025-04-28-equality-on-floats-precision.md rename csharp/ql/src/change-notes/{2025-05-01-cwe-tag-changed.md => released/1.2.0.md} (87%) create mode 100644 go/ql/consistency-queries/change-notes/released/1.0.23.md create mode 100644 go/ql/lib/change-notes/released/4.2.5.md rename go/ql/src/change-notes/{2025-05-01-cwe-tag-changed.md => released/1.2.0.md} (97%) rename java/ql/lib/change-notes/{2025-04-28-kotlin-220.md => released/7.2.0.md} (84%) rename java/ql/src/change-notes/{2025-05-01-cwe-tag-changed.md => released/1.5.0.md} (92%) delete mode 100644 javascript/ql/lib/change-notes/2025-04-14-fastify-addhook.md delete mode 100644 javascript/ql/lib/change-notes/2025-04-30-fastify-all.md delete mode 100644 javascript/ql/lib/change-notes/2025-04-30-shelljs.md create mode 100644 javascript/ql/lib/change-notes/released/2.6.3.md delete mode 100644 javascript/ql/src/change-notes/2025-04-30-promise-all.md rename javascript/ql/src/change-notes/{2025-05-01-cwe-tag-changed.md => released/1.6.0.md} (71%) create mode 100644 misc/suite-helpers/change-notes/released/1.0.23.md delete mode 100644 python/ql/lib/change-notes/2025-04-30-model-send-header.md delete mode 100644 python/ql/lib/change-notes/2025-05-01-hdbcli.md create mode 100644 python/ql/lib/change-notes/released/4.0.7.md rename python/ql/src/change-notes/{2025-05-01-cwe-tag-changed.md => released/1.5.0.md} (95%) create mode 100644 ruby/ql/lib/change-notes/released/4.1.6.md delete mode 100644 ruby/ql/src/change-notes/2025-05-12-rb-useless-assignment-to-local-precision-high.md rename ruby/ql/src/change-notes/{2025-05-01-cwe-tag-changed.md => released/1.3.0.md} (51%) create mode 100644 rust/ql/lib/change-notes/released/0.1.8.md create mode 100644 rust/ql/src/change-notes/released/0.1.8.md create mode 100644 shared/controlflow/change-notes/released/2.0.7.md create mode 100644 shared/dataflow/change-notes/released/2.0.7.md create mode 100644 shared/mad/change-notes/released/1.0.23.md create mode 100644 shared/quantum/CHANGELOG.md create mode 100644 shared/quantum/change-notes/released/0.0.1.md create mode 100644 shared/quantum/codeql-pack.release.yml create mode 100644 shared/rangeanalysis/change-notes/released/1.0.23.md create mode 100644 shared/regex/change-notes/released/1.0.23.md create mode 100644 shared/ssa/change-notes/released/1.1.2.md create mode 100644 shared/threat-models/change-notes/released/1.0.23.md create mode 100644 shared/tutorial/change-notes/released/1.0.23.md create mode 100644 shared/typeflow/change-notes/released/1.0.23.md create mode 100644 shared/typeinference/change-notes/released/0.0.4.md create mode 100644 shared/typetracking/change-notes/released/2.0.7.md create mode 100644 shared/typos/change-notes/released/1.0.23.md create mode 100644 shared/util/change-notes/released/2.0.10.md create mode 100644 shared/xml/change-notes/released/1.0.23.md create mode 100644 shared/yaml/change-notes/released/1.0.23.md rename swift/ql/lib/change-notes/{2025-05-02-new-entities.md => released/4.3.0.md} (83%) create mode 100644 swift/ql/src/change-notes/released/1.1.3.md diff --git a/actions/ql/lib/CHANGELOG.md b/actions/ql/lib/CHANGELOG.md index e16567daffd3..16262bfaa849 100644 --- a/actions/ql/lib/CHANGELOG.md +++ b/actions/ql/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.9 + +No user-facing changes. + ## 0.4.8 No user-facing changes. diff --git a/actions/ql/lib/change-notes/released/0.4.9.md b/actions/ql/lib/change-notes/released/0.4.9.md new file mode 100644 index 000000000000..4666ef266e50 --- /dev/null +++ b/actions/ql/lib/change-notes/released/0.4.9.md @@ -0,0 +1,3 @@ +## 0.4.9 + +No user-facing changes. diff --git a/actions/ql/lib/codeql-pack.release.yml b/actions/ql/lib/codeql-pack.release.yml index 3c75bfd1a471..c898a5bfdcdf 100644 --- a/actions/ql/lib/codeql-pack.release.yml +++ b/actions/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.8 +lastReleaseVersion: 0.4.9 diff --git a/actions/ql/lib/qlpack.yml b/actions/ql/lib/qlpack.yml index 81973859a2bc..78262551e5b1 100644 --- a/actions/ql/lib/qlpack.yml +++ b/actions/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/actions-all -version: 0.4.9-dev +version: 0.4.9 library: true warnOnImplicitThis: true dependencies: diff --git a/actions/ql/src/CHANGELOG.md b/actions/ql/src/CHANGELOG.md index 73cc65ebe217..5779691947e4 100644 --- a/actions/ql/src/CHANGELOG.md +++ b/actions/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.1 + +No user-facing changes. + ## 0.6.0 ### Breaking Changes diff --git a/actions/ql/src/change-notes/released/0.6.1.md b/actions/ql/src/change-notes/released/0.6.1.md new file mode 100644 index 000000000000..6008e49b8e74 --- /dev/null +++ b/actions/ql/src/change-notes/released/0.6.1.md @@ -0,0 +1,3 @@ +## 0.6.1 + +No user-facing changes. diff --git a/actions/ql/src/codeql-pack.release.yml b/actions/ql/src/codeql-pack.release.yml index a3f820f884d3..80fb0899f645 100644 --- a/actions/ql/src/codeql-pack.release.yml +++ b/actions/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.6.0 +lastReleaseVersion: 0.6.1 diff --git a/actions/ql/src/qlpack.yml b/actions/ql/src/qlpack.yml index 942c10d3bcfa..a8bdbd232a2a 100644 --- a/actions/ql/src/qlpack.yml +++ b/actions/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/actions-queries -version: 0.6.1-dev +version: 0.6.1 library: false warnOnImplicitThis: true groups: [actions, queries] diff --git a/cpp/ql/lib/CHANGELOG.md b/cpp/ql/lib/CHANGELOG.md index c66e7d7cd550..4ad53d108e26 100644 --- a/cpp/ql/lib/CHANGELOG.md +++ b/cpp/ql/lib/CHANGELOG.md @@ -1,3 +1,9 @@ +## 4.3.1 + +### Bug Fixes + +* Fixed an infinite loop in `semmle.code.cpp.rangeanalysis.new.RangeAnalysis` when computing ranges in very large and complex function bodies. + ## 4.3.0 ### New Features diff --git a/cpp/ql/lib/change-notes/2025-05-13-range-analysis-infinite-loop.md b/cpp/ql/lib/change-notes/released/4.3.1.md similarity index 76% rename from cpp/ql/lib/change-notes/2025-05-13-range-analysis-infinite-loop.md rename to cpp/ql/lib/change-notes/released/4.3.1.md index 7452e024d53f..641abc97e454 100644 --- a/cpp/ql/lib/change-notes/2025-05-13-range-analysis-infinite-loop.md +++ b/cpp/ql/lib/change-notes/released/4.3.1.md @@ -1,4 +1,5 @@ ---- -category: fix ---- -* Fixed an infinite loop in `semmle.code.cpp.rangeanalysis.new.RangeAnalysis` when computing ranges in very large and complex function bodies. \ No newline at end of file +## 4.3.1 + +### Bug Fixes + +* Fixed an infinite loop in `semmle.code.cpp.rangeanalysis.new.RangeAnalysis` when computing ranges in very large and complex function bodies. diff --git a/cpp/ql/lib/codeql-pack.release.yml b/cpp/ql/lib/codeql-pack.release.yml index c46c103a0bd7..70ac3707fcda 100644 --- a/cpp/ql/lib/codeql-pack.release.yml +++ b/cpp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 4.3.0 +lastReleaseVersion: 4.3.1 diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index b7bf768c3f2e..ebc158065aa6 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-all -version: 4.3.1-dev +version: 4.3.1 groups: cpp dbscheme: semmlecode.cpp.dbscheme extractor: cpp diff --git a/cpp/ql/src/CHANGELOG.md b/cpp/ql/src/CHANGELOG.md index daad17e01685..f9880ce57641 100644 --- a/cpp/ql/src/CHANGELOG.md +++ b/cpp/ql/src/CHANGELOG.md @@ -1,3 +1,14 @@ +## 1.4.0 + +### Query Metadata Changes + +* The tag `external/cwe/cwe-14` has been removed from `cpp/memset-may-be-deleted` and the tag `external/cwe/cwe-014` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cpp/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cpp/count-untrusted-data-external-api-ir` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cpp/untrusted-data-to-external-api-ir` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cpp/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cpp/late-check-of-function-argument` and the tag `external/cwe/cwe-020` has been added. + ## 1.3.9 No user-facing changes. diff --git a/cpp/ql/src/change-notes/2025-05-01-cwe-tag-changed.md b/cpp/ql/src/change-notes/released/1.4.0.md similarity index 95% rename from cpp/ql/src/change-notes/2025-05-01-cwe-tag-changed.md rename to cpp/ql/src/change-notes/released/1.4.0.md index daefff65c31e..59eee09b2611 100644 --- a/cpp/ql/src/change-notes/2025-05-01-cwe-tag-changed.md +++ b/cpp/ql/src/change-notes/released/1.4.0.md @@ -1,6 +1,7 @@ ---- -category: queryMetadata ---- +## 1.4.0 + +### Query Metadata Changes + * The tag `external/cwe/cwe-14` has been removed from `cpp/memset-may-be-deleted` and the tag `external/cwe/cwe-014` has been added. * The tag `external/cwe/cwe-20` has been removed from `cpp/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. * The tag `external/cwe/cwe-20` has been removed from `cpp/count-untrusted-data-external-api-ir` and the tag `external/cwe/cwe-020` has been added. diff --git a/cpp/ql/src/codeql-pack.release.yml b/cpp/ql/src/codeql-pack.release.yml index 5ce113f4464d..b8b2e97d5086 100644 --- a/cpp/ql/src/codeql-pack.release.yml +++ b/cpp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.3.9 +lastReleaseVersion: 1.4.0 diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml index b911fdb21934..4a85abdeb488 100644 --- a/cpp/ql/src/qlpack.yml +++ b/cpp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-queries -version: 1.3.10-dev +version: 1.4.0 groups: - cpp - queries diff --git a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md index d4414a3f145f..f177ccf403e3 100644 --- a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.7.40 + +No user-facing changes. + ## 1.7.39 No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.7.40.md b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.7.40.md new file mode 100644 index 000000000000..e7dc874b123a --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.7.40.md @@ -0,0 +1,3 @@ +## 1.7.40 + +No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml index aba298841840..47c67a0a4d32 100644 --- a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml +++ b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.7.39 +lastReleaseVersion: 1.7.40 diff --git a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml index e39ac3a9763b..cce389c29633 100644 --- a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-all -version: 1.7.40-dev +version: 1.7.40 groups: - csharp - solorigate diff --git a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md index d4414a3f145f..f177ccf403e3 100644 --- a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.7.40 + +No user-facing changes. + ## 1.7.39 No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.7.40.md b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.7.40.md new file mode 100644 index 000000000000..e7dc874b123a --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.7.40.md @@ -0,0 +1,3 @@ +## 1.7.40 + +No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml index aba298841840..47c67a0a4d32 100644 --- a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml +++ b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.7.39 +lastReleaseVersion: 1.7.40 diff --git a/csharp/ql/campaigns/Solorigate/src/qlpack.yml b/csharp/ql/campaigns/Solorigate/src/qlpack.yml index bc910490374b..978778f73a57 100644 --- a/csharp/ql/campaigns/Solorigate/src/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-queries -version: 1.7.40-dev +version: 1.7.40 groups: - csharp - solorigate diff --git a/csharp/ql/lib/CHANGELOG.md b/csharp/ql/lib/CHANGELOG.md index 11a9350f81ae..47503fa222ed 100644 --- a/csharp/ql/lib/CHANGELOG.md +++ b/csharp/ql/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.1.6 + +No user-facing changes. + ## 5.1.5 ### Minor Analysis Improvements diff --git a/csharp/ql/lib/change-notes/released/5.1.6.md b/csharp/ql/lib/change-notes/released/5.1.6.md new file mode 100644 index 000000000000..74ba63bd37a6 --- /dev/null +++ b/csharp/ql/lib/change-notes/released/5.1.6.md @@ -0,0 +1,3 @@ +## 5.1.6 + +No user-facing changes. diff --git a/csharp/ql/lib/codeql-pack.release.yml b/csharp/ql/lib/codeql-pack.release.yml index fee027332511..5ddeeed69fc2 100644 --- a/csharp/ql/lib/codeql-pack.release.yml +++ b/csharp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 5.1.5 +lastReleaseVersion: 5.1.6 diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml index 632931bcd7e3..312ef102b8f1 100644 --- a/csharp/ql/lib/qlpack.yml +++ b/csharp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-all -version: 5.1.6-dev +version: 5.1.6 groups: csharp dbscheme: semmlecode.csharp.dbscheme extractor: csharp diff --git a/csharp/ql/src/CHANGELOG.md b/csharp/ql/src/CHANGELOG.md index cc2b6173a25d..a73c77f224f7 100644 --- a/csharp/ql/src/CHANGELOG.md +++ b/csharp/ql/src/CHANGELOG.md @@ -1,3 +1,20 @@ +## 1.2.0 + +### Query Metadata Changes + +* The tag `external/cwe/cwe-13` has been removed from `cs/password-in-configuration` and the tag `external/cwe/cwe-013` has been added. +* The tag `external/cwe/cwe-11` has been removed from `cs/web/debug-binary` and the tag `external/cwe/cwe-011` has been added. +* The tag `external/cwe/cwe-16` has been removed from `cs/web/large-max-request-length` and the tag `external/cwe/cwe-016` has been added. +* The tag `external/cwe/cwe-16` has been removed from `cs/web/request-validation-disabled` and the tag `external/cwe/cwe-016` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cs/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cs/serialization-check-bypass` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `cs/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-12` has been removed from `cs/web/missing-global-error-handler` and the tag `external/cwe/cwe-012` has been added. + +### Minor Analysis Improvements + +* Changed the precision of the `cs/equality-on-floats` query from medium to high. + ## 1.1.2 ### Minor Analysis Improvements diff --git a/csharp/ql/src/change-notes/2025-04-28-equality-on-floats-precision.md b/csharp/ql/src/change-notes/2025-04-28-equality-on-floats-precision.md deleted file mode 100644 index a990d236eecb..000000000000 --- a/csharp/ql/src/change-notes/2025-04-28-equality-on-floats-precision.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Changed the precision of the `cs/equality-on-floats` query from medium to high. diff --git a/csharp/ql/src/change-notes/2025-05-01-cwe-tag-changed.md b/csharp/ql/src/change-notes/released/1.2.0.md similarity index 87% rename from csharp/ql/src/change-notes/2025-05-01-cwe-tag-changed.md rename to csharp/ql/src/change-notes/released/1.2.0.md index 8b84ae3f0774..71c430a766a9 100644 --- a/csharp/ql/src/change-notes/2025-05-01-cwe-tag-changed.md +++ b/csharp/ql/src/change-notes/released/1.2.0.md @@ -1,6 +1,6 @@ ---- -category: queryMetadata ---- +## 1.2.0 + +### Query Metadata Changes * The tag `external/cwe/cwe-13` has been removed from `cs/password-in-configuration` and the tag `external/cwe/cwe-013` has been added. * The tag `external/cwe/cwe-11` has been removed from `cs/web/debug-binary` and the tag `external/cwe/cwe-011` has been added. @@ -10,3 +10,7 @@ category: queryMetadata * The tag `external/cwe/cwe-20` has been removed from `cs/serialization-check-bypass` and the tag `external/cwe/cwe-020` has been added. * The tag `external/cwe/cwe-20` has been removed from `cs/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added. * The tag `external/cwe/cwe-12` has been removed from `cs/web/missing-global-error-handler` and the tag `external/cwe/cwe-012` has been added. + +### Minor Analysis Improvements + +* Changed the precision of the `cs/equality-on-floats` query from medium to high. diff --git a/csharp/ql/src/codeql-pack.release.yml b/csharp/ql/src/codeql-pack.release.yml index 53ab127707fc..75430e73d1c4 100644 --- a/csharp/ql/src/codeql-pack.release.yml +++ b/csharp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.1.2 +lastReleaseVersion: 1.2.0 diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index 664f83f6980c..74065d9e9d3f 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-queries -version: 1.1.3-dev +version: 1.2.0 groups: - csharp - queries diff --git a/go/ql/consistency-queries/CHANGELOG.md b/go/ql/consistency-queries/CHANGELOG.md index b09bc81cffe9..c3254e1caad7 100644 --- a/go/ql/consistency-queries/CHANGELOG.md +++ b/go/ql/consistency-queries/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.23 + +No user-facing changes. + ## 1.0.22 No user-facing changes. diff --git a/go/ql/consistency-queries/change-notes/released/1.0.23.md b/go/ql/consistency-queries/change-notes/released/1.0.23.md new file mode 100644 index 000000000000..8480f179393b --- /dev/null +++ b/go/ql/consistency-queries/change-notes/released/1.0.23.md @@ -0,0 +1,3 @@ +## 1.0.23 + +No user-facing changes. diff --git a/go/ql/consistency-queries/codeql-pack.release.yml b/go/ql/consistency-queries/codeql-pack.release.yml index 27d922b5ea6d..0f96ba41d168 100644 --- a/go/ql/consistency-queries/codeql-pack.release.yml +++ b/go/ql/consistency-queries/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.22 +lastReleaseVersion: 1.0.23 diff --git a/go/ql/consistency-queries/qlpack.yml b/go/ql/consistency-queries/qlpack.yml index e09a33e17f57..029a8ee5a217 100644 --- a/go/ql/consistency-queries/qlpack.yml +++ b/go/ql/consistency-queries/qlpack.yml @@ -1,5 +1,5 @@ name: codeql-go-consistency-queries -version: 1.0.23-dev +version: 1.0.23 groups: - go - queries diff --git a/go/ql/lib/CHANGELOG.md b/go/ql/lib/CHANGELOG.md index 0bf8614edd60..9eb5ef69ebcd 100644 --- a/go/ql/lib/CHANGELOG.md +++ b/go/ql/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.2.5 + +No user-facing changes. + ## 4.2.4 No user-facing changes. diff --git a/go/ql/lib/change-notes/released/4.2.5.md b/go/ql/lib/change-notes/released/4.2.5.md new file mode 100644 index 000000000000..a6a2063506a6 --- /dev/null +++ b/go/ql/lib/change-notes/released/4.2.5.md @@ -0,0 +1,3 @@ +## 4.2.5 + +No user-facing changes. diff --git a/go/ql/lib/codeql-pack.release.yml b/go/ql/lib/codeql-pack.release.yml index e0c6f96cfe84..1821397188ee 100644 --- a/go/ql/lib/codeql-pack.release.yml +++ b/go/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 4.2.4 +lastReleaseVersion: 4.2.5 diff --git a/go/ql/lib/qlpack.yml b/go/ql/lib/qlpack.yml index 8367d8c5dee6..6effb4ee5899 100644 --- a/go/ql/lib/qlpack.yml +++ b/go/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-all -version: 4.2.5-dev +version: 4.2.5 groups: go dbscheme: go.dbscheme extractor: go diff --git a/go/ql/src/CHANGELOG.md b/go/ql/src/CHANGELOG.md index b871d911dd12..a90fa7b70345 100644 --- a/go/ql/src/CHANGELOG.md +++ b/go/ql/src/CHANGELOG.md @@ -1,3 +1,18 @@ +## 1.2.0 + +### Query Metadata Changes + +* The tag `external/cwe/cwe-20` has been removed from `go/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `go/incomplete-hostname-regexp` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `go/regex/missing-regexp-anchor` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `go/suspicious-character-in-regex` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `go/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `go/untrusted-data-to-unknown-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-90` has been removed from `go/ldap-injection` and the tag `external/cwe/cwe-090` has been added. +* The tag `external/cwe/cwe-74` has been removed from `go/dsn-injection` and the tag `external/cwe/cwe-074` has been added. +* The tag `external/cwe/cwe-74` has been removed from `go/dsn-injection-local` and the tag `external/cwe/cwe-074` has been added. +* The tag `external/cwe/cwe-79` has been removed from `go/html-template-escaping-passthrough` and the tag `external/cwe/cwe-079` has been added. + ## 1.1.13 No user-facing changes. diff --git a/go/ql/src/change-notes/2025-05-01-cwe-tag-changed.md b/go/ql/src/change-notes/released/1.2.0.md similarity index 97% rename from go/ql/src/change-notes/2025-05-01-cwe-tag-changed.md rename to go/ql/src/change-notes/released/1.2.0.md index d084aeeaf48a..288536c1b830 100644 --- a/go/ql/src/change-notes/2025-05-01-cwe-tag-changed.md +++ b/go/ql/src/change-notes/released/1.2.0.md @@ -1,6 +1,6 @@ ---- -category: queryMetadata ---- +## 1.2.0 + +### Query Metadata Changes * The tag `external/cwe/cwe-20` has been removed from `go/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. * The tag `external/cwe/cwe-20` has been removed from `go/incomplete-hostname-regexp` and the tag `external/cwe/cwe-020` has been added. diff --git a/go/ql/src/codeql-pack.release.yml b/go/ql/src/codeql-pack.release.yml index 09a80be68d17..75430e73d1c4 100644 --- a/go/ql/src/codeql-pack.release.yml +++ b/go/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.1.13 +lastReleaseVersion: 1.2.0 diff --git a/go/ql/src/qlpack.yml b/go/ql/src/qlpack.yml index 2cd2db243850..69f168f17eea 100644 --- a/go/ql/src/qlpack.yml +++ b/go/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-queries -version: 1.1.14-dev +version: 1.2.0 groups: - go - queries diff --git a/java/ql/lib/CHANGELOG.md b/java/ql/lib/CHANGELOG.md index b9c10d311fde..01832478c5b4 100644 --- a/java/ql/lib/CHANGELOG.md +++ b/java/ql/lib/CHANGELOG.md @@ -1,3 +1,9 @@ +## 7.2.0 + +### New Features + +* 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). + ## 7.1.4 No user-facing changes. diff --git a/java/ql/lib/change-notes/2025-04-28-kotlin-220.md b/java/ql/lib/change-notes/released/7.2.0.md similarity index 84% rename from java/ql/lib/change-notes/2025-04-28-kotlin-220.md rename to java/ql/lib/change-notes/released/7.2.0.md index c0c257a2f076..7714e3eeb326 100644 --- a/java/ql/lib/change-notes/2025-04-28-kotlin-220.md +++ b/java/ql/lib/change-notes/released/7.2.0.md @@ -1,4 +1,5 @@ ---- -category: feature ---- +## 7.2.0 + +### New Features + * 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). diff --git a/java/ql/lib/codeql-pack.release.yml b/java/ql/lib/codeql-pack.release.yml index de842046cc34..fda9ea165fc5 100644 --- a/java/ql/lib/codeql-pack.release.yml +++ b/java/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 7.1.4 +lastReleaseVersion: 7.2.0 diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index eeaa063e4738..345cd2806ea5 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-all -version: 7.1.5-dev +version: 7.2.0 groups: java dbscheme: config/semmlecode.dbscheme extractor: java diff --git a/java/ql/src/CHANGELOG.md b/java/ql/src/CHANGELOG.md index 8b8ac750e689..286ed1123af3 100644 --- a/java/ql/src/CHANGELOG.md +++ b/java/ql/src/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.5.0 + +### Query Metadata Changes + +* The tag `external/cwe/cwe-20` has been removed from `java/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `java/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-93` has been removed from `java/netty-http-request-or-response-splitting` and the tag `external/cwe/cwe-093` has been added. + ## 1.4.2 ### Minor Analysis Improvements diff --git a/java/ql/src/change-notes/2025-05-01-cwe-tag-changed.md b/java/ql/src/change-notes/released/1.5.0.md similarity index 92% rename from java/ql/src/change-notes/2025-05-01-cwe-tag-changed.md rename to java/ql/src/change-notes/released/1.5.0.md index 2bbc6a6d7764..d2c14f76e866 100644 --- a/java/ql/src/change-notes/2025-05-01-cwe-tag-changed.md +++ b/java/ql/src/change-notes/released/1.5.0.md @@ -1,6 +1,6 @@ ---- -category: queryMetadata ---- +## 1.5.0 + +### Query Metadata Changes * The tag `external/cwe/cwe-20` has been removed from `java/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. * The tag `external/cwe/cwe-20` has been removed from `java/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added. diff --git a/java/ql/src/codeql-pack.release.yml b/java/ql/src/codeql-pack.release.yml index a76cacdf7997..639f80c43417 100644 --- a/java/ql/src/codeql-pack.release.yml +++ b/java/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.4.2 +lastReleaseVersion: 1.5.0 diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index d077b42e4433..eb187075e823 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-queries -version: 1.4.3-dev +version: 1.5.0 groups: - java - queries diff --git a/javascript/ql/lib/CHANGELOG.md b/javascript/ql/lib/CHANGELOG.md index 48488450afab..2d7716b8393d 100644 --- a/javascript/ql/lib/CHANGELOG.md +++ b/javascript/ql/lib/CHANGELOG.md @@ -1,3 +1,11 @@ +## 2.6.3 + +### Minor Analysis Improvements + +* Enhanced modeling of the [fastify](https://www.npmjs.com/package/fastify) framework to support the `all` route handler method. +* Improved modeling of the [`shelljs`](https://www.npmjs.com/package/shelljs) and [`async-shelljs`](https://www.npmjs.com/package/async-shelljs) libraries by adding support for the `which`, `cmd`, `asyncExec` and `env`. +* Added support for the `fastify` `addHook` method. + ## 2.6.2 No user-facing changes. diff --git a/javascript/ql/lib/change-notes/2025-04-14-fastify-addhook.md b/javascript/ql/lib/change-notes/2025-04-14-fastify-addhook.md deleted file mode 100644 index a9e754bd56ea..000000000000 --- a/javascript/ql/lib/change-notes/2025-04-14-fastify-addhook.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Added support for the `fastify` `addHook` method. diff --git a/javascript/ql/lib/change-notes/2025-04-30-fastify-all.md b/javascript/ql/lib/change-notes/2025-04-30-fastify-all.md deleted file mode 100644 index a49092f6ba41..000000000000 --- a/javascript/ql/lib/change-notes/2025-04-30-fastify-all.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Enhanced modeling of the [fastify](https://www.npmjs.com/package/fastify) framework to support the `all` route handler method. diff --git a/javascript/ql/lib/change-notes/2025-04-30-shelljs.md b/javascript/ql/lib/change-notes/2025-04-30-shelljs.md deleted file mode 100644 index 90a5f5a2a308..000000000000 --- a/javascript/ql/lib/change-notes/2025-04-30-shelljs.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Improved modeling of the [`shelljs`](https://www.npmjs.com/package/shelljs) and [`async-shelljs`](https://www.npmjs.com/package/async-shelljs) libraries by adding support for the `which`, `cmd`, `asyncExec` and `env`. diff --git a/javascript/ql/lib/change-notes/released/2.6.3.md b/javascript/ql/lib/change-notes/released/2.6.3.md new file mode 100644 index 000000000000..19185b6f9c65 --- /dev/null +++ b/javascript/ql/lib/change-notes/released/2.6.3.md @@ -0,0 +1,7 @@ +## 2.6.3 + +### Minor Analysis Improvements + +* Enhanced modeling of the [fastify](https://www.npmjs.com/package/fastify) framework to support the `all` route handler method. +* Improved modeling of the [`shelljs`](https://www.npmjs.com/package/shelljs) and [`async-shelljs`](https://www.npmjs.com/package/async-shelljs) libraries by adding support for the `which`, `cmd`, `asyncExec` and `env`. +* Added support for the `fastify` `addHook` method. diff --git a/javascript/ql/lib/codeql-pack.release.yml b/javascript/ql/lib/codeql-pack.release.yml index cca069203ce7..e2457adb03c7 100644 --- a/javascript/ql/lib/codeql-pack.release.yml +++ b/javascript/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 2.6.2 +lastReleaseVersion: 2.6.3 diff --git a/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml index 36814d319281..9a212edfbd47 100644 --- a/javascript/ql/lib/qlpack.yml +++ b/javascript/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-all -version: 2.6.3-dev +version: 2.6.3 groups: javascript dbscheme: semmlecode.javascript.dbscheme extractor: javascript diff --git a/javascript/ql/src/CHANGELOG.md b/javascript/ql/src/CHANGELOG.md index dc7c6ebc2f89..bd5cb345793e 100644 --- a/javascript/ql/src/CHANGELOG.md +++ b/javascript/ql/src/CHANGELOG.md @@ -1,3 +1,17 @@ +## 1.6.0 + +### Query Metadata Changes + +* The tag `external/cwe/cwe-79` has been removed from `js/disabling-electron-websecurity` and the tag `external/cwe/cwe-079` has been added. +* The tag `external/cwe/cwe-20` has been removed from `js/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `js/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `js/untrusted-data-to-external-api-more-sources` and the tag `external/cwe/cwe-020` has been added. + +### Minor Analysis Improvements + +* Type information is now propagated more precisely through `Promise.all()` calls, + leading to more resolved calls and more sources and sinks being detected. + ## 1.5.4 No user-facing changes. diff --git a/javascript/ql/src/change-notes/2025-04-30-promise-all.md b/javascript/ql/src/change-notes/2025-04-30-promise-all.md deleted file mode 100644 index a50e31ea01d0..000000000000 --- a/javascript/ql/src/change-notes/2025-04-30-promise-all.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -category: minorAnalysis ---- -* Type information is now propagated more precisely through `Promise.all()` calls, - leading to more resolved calls and more sources and sinks being detected. diff --git a/javascript/ql/src/change-notes/2025-05-01-cwe-tag-changed.md b/javascript/ql/src/change-notes/released/1.6.0.md similarity index 71% rename from javascript/ql/src/change-notes/2025-05-01-cwe-tag-changed.md rename to javascript/ql/src/change-notes/released/1.6.0.md index 01e53adf5f5e..b24554c85c97 100644 --- a/javascript/ql/src/change-notes/2025-05-01-cwe-tag-changed.md +++ b/javascript/ql/src/change-notes/released/1.6.0.md @@ -1,8 +1,13 @@ ---- -category: queryMetadata ---- +## 1.6.0 + +### Query Metadata Changes * The tag `external/cwe/cwe-79` has been removed from `js/disabling-electron-websecurity` and the tag `external/cwe/cwe-079` has been added. * The tag `external/cwe/cwe-20` has been removed from `js/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. * The tag `external/cwe/cwe-20` has been removed from `js/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added. * The tag `external/cwe/cwe-20` has been removed from `js/untrusted-data-to-external-api-more-sources` and the tag `external/cwe/cwe-020` has been added. + +### Minor Analysis Improvements + +* Type information is now propagated more precisely through `Promise.all()` calls, + leading to more resolved calls and more sources and sinks being detected. diff --git a/javascript/ql/src/codeql-pack.release.yml b/javascript/ql/src/codeql-pack.release.yml index c216828ee1c3..c4f0b07d5336 100644 --- a/javascript/ql/src/codeql-pack.release.yml +++ b/javascript/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.5.4 +lastReleaseVersion: 1.6.0 diff --git a/javascript/ql/src/qlpack.yml b/javascript/ql/src/qlpack.yml index 288baf974d3c..24a0a1ab109b 100644 --- a/javascript/ql/src/qlpack.yml +++ b/javascript/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-queries -version: 1.5.5-dev +version: 1.6.0 groups: - javascript - queries diff --git a/misc/suite-helpers/CHANGELOG.md b/misc/suite-helpers/CHANGELOG.md index b7891e5bb95b..d65ced8b4c71 100644 --- a/misc/suite-helpers/CHANGELOG.md +++ b/misc/suite-helpers/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.23 + +No user-facing changes. + ## 1.0.22 No user-facing changes. diff --git a/misc/suite-helpers/change-notes/released/1.0.23.md b/misc/suite-helpers/change-notes/released/1.0.23.md new file mode 100644 index 000000000000..8480f179393b --- /dev/null +++ b/misc/suite-helpers/change-notes/released/1.0.23.md @@ -0,0 +1,3 @@ +## 1.0.23 + +No user-facing changes. diff --git a/misc/suite-helpers/codeql-pack.release.yml b/misc/suite-helpers/codeql-pack.release.yml index 27d922b5ea6d..0f96ba41d168 100644 --- a/misc/suite-helpers/codeql-pack.release.yml +++ b/misc/suite-helpers/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.22 +lastReleaseVersion: 1.0.23 diff --git a/misc/suite-helpers/qlpack.yml b/misc/suite-helpers/qlpack.yml index 06c89edc7723..93018dd3c94f 100644 --- a/misc/suite-helpers/qlpack.yml +++ b/misc/suite-helpers/qlpack.yml @@ -1,4 +1,4 @@ name: codeql/suite-helpers -version: 1.0.23-dev +version: 1.0.23 groups: shared warnOnImplicitThis: true diff --git a/python/ql/lib/CHANGELOG.md b/python/ql/lib/CHANGELOG.md index 3d8ab0011caf..33813cf94e46 100644 --- a/python/ql/lib/CHANGELOG.md +++ b/python/ql/lib/CHANGELOG.md @@ -1,3 +1,10 @@ +## 4.0.7 + +### Minor Analysis Improvements + +* Added modeling for the `hdbcli` PyPI package as a database library implementing PEP 249. +* Added header write model for `send_header` in `http.server`. + ## 4.0.6 No user-facing changes. diff --git a/python/ql/lib/change-notes/2025-04-30-model-send-header.md b/python/ql/lib/change-notes/2025-04-30-model-send-header.md deleted file mode 100644 index 032e984bdf3a..000000000000 --- a/python/ql/lib/change-notes/2025-04-30-model-send-header.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Added header write model for `send_header` in `http.server`. \ No newline at end of file diff --git a/python/ql/lib/change-notes/2025-05-01-hdbcli.md b/python/ql/lib/change-notes/2025-05-01-hdbcli.md deleted file mode 100644 index 5b9afe4618b0..000000000000 --- a/python/ql/lib/change-notes/2025-05-01-hdbcli.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Added modeling for the `hdbcli` PyPI package as a database library implementing PEP 249. diff --git a/python/ql/lib/change-notes/released/4.0.7.md b/python/ql/lib/change-notes/released/4.0.7.md new file mode 100644 index 000000000000..5f5120e027e4 --- /dev/null +++ b/python/ql/lib/change-notes/released/4.0.7.md @@ -0,0 +1,6 @@ +## 4.0.7 + +### Minor Analysis Improvements + +* Added modeling for the `hdbcli` PyPI package as a database library implementing PEP 249. +* Added header write model for `send_header` in `http.server`. diff --git a/python/ql/lib/codeql-pack.release.yml b/python/ql/lib/codeql-pack.release.yml index 3b3376d94e43..bf65f0dc10b1 100644 --- a/python/ql/lib/codeql-pack.release.yml +++ b/python/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 4.0.6 +lastReleaseVersion: 4.0.7 diff --git a/python/ql/lib/qlpack.yml b/python/ql/lib/qlpack.yml index 78eec8158e86..85ce51edc48e 100644 --- a/python/ql/lib/qlpack.yml +++ b/python/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-all -version: 4.0.7-dev +version: 4.0.7 groups: python dbscheme: semmlecode.python.dbscheme extractor: python diff --git a/python/ql/src/CHANGELOG.md b/python/ql/src/CHANGELOG.md index aa0908119da3..c449304f0da1 100644 --- a/python/ql/src/CHANGELOG.md +++ b/python/ql/src/CHANGELOG.md @@ -1,3 +1,14 @@ +## 1.5.0 + +### Query Metadata Changes + +* The tags `security/cwe/cwe-94` and `security/cwe/cwe-95` have been removed from `py/use-of-input` and the tags `external/cwe/cwe-094` and `external/cwe/cwe-095` have been added. +* The tag `external/cwe/cwe-20` has been removed from `py/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `py/untrusted-data-to-external-api` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `py/cookie-injection` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-20` has been removed from `py/incomplete-url-substring-sanitization` and the tag `external/cwe/cwe-020` has been added. +* The tag `external/cwe/cwe-94` has been removed from `py/js2py-rce` and the tag `external/cwe/cwe-094` has been added. + ## 1.4.8 No user-facing changes. diff --git a/python/ql/src/change-notes/2025-05-01-cwe-tag-changed.md b/python/ql/src/change-notes/released/1.5.0.md similarity index 95% rename from python/ql/src/change-notes/2025-05-01-cwe-tag-changed.md rename to python/ql/src/change-notes/released/1.5.0.md index 0267e9a3fbb8..e9fa8ad818d1 100644 --- a/python/ql/src/change-notes/2025-05-01-cwe-tag-changed.md +++ b/python/ql/src/change-notes/released/1.5.0.md @@ -1,6 +1,6 @@ ---- -category: queryMetadata ---- +## 1.5.0 + +### Query Metadata Changes * The tags `security/cwe/cwe-94` and `security/cwe/cwe-95` have been removed from `py/use-of-input` and the tags `external/cwe/cwe-094` and `external/cwe/cwe-095` have been added. * The tag `external/cwe/cwe-20` has been removed from `py/count-untrusted-data-external-api` and the tag `external/cwe/cwe-020` has been added. diff --git a/python/ql/src/codeql-pack.release.yml b/python/ql/src/codeql-pack.release.yml index 16e6425ae7e4..639f80c43417 100644 --- a/python/ql/src/codeql-pack.release.yml +++ b/python/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.4.8 +lastReleaseVersion: 1.5.0 diff --git a/python/ql/src/qlpack.yml b/python/ql/src/qlpack.yml index a1c976dfdfae..24b80a87e2ed 100644 --- a/python/ql/src/qlpack.yml +++ b/python/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-queries -version: 1.4.9-dev +version: 1.5.0 groups: - python - queries diff --git a/ruby/ql/lib/CHANGELOG.md b/ruby/ql/lib/CHANGELOG.md index 43ab8e8fdac4..f9858668d937 100644 --- a/ruby/ql/lib/CHANGELOG.md +++ b/ruby/ql/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.1.6 + +No user-facing changes. + ## 4.1.5 No user-facing changes. diff --git a/ruby/ql/lib/change-notes/released/4.1.6.md b/ruby/ql/lib/change-notes/released/4.1.6.md new file mode 100644 index 000000000000..142f6a39b077 --- /dev/null +++ b/ruby/ql/lib/change-notes/released/4.1.6.md @@ -0,0 +1,3 @@ +## 4.1.6 + +No user-facing changes. diff --git a/ruby/ql/lib/codeql-pack.release.yml b/ruby/ql/lib/codeql-pack.release.yml index 3b4af49b03c4..8b32e3bae01c 100644 --- a/ruby/ql/lib/codeql-pack.release.yml +++ b/ruby/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 4.1.5 +lastReleaseVersion: 4.1.6 diff --git a/ruby/ql/lib/qlpack.yml b/ruby/ql/lib/qlpack.yml index bb7cfb00c9b4..571ca22b15f8 100644 --- a/ruby/ql/lib/qlpack.yml +++ b/ruby/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-all -version: 4.1.6-dev +version: 4.1.6 groups: ruby extractor: ruby dbscheme: ruby.dbscheme diff --git a/ruby/ql/src/CHANGELOG.md b/ruby/ql/src/CHANGELOG.md index a44233266fb9..0a3ce10b979c 100644 --- a/ruby/ql/src/CHANGELOG.md +++ b/ruby/ql/src/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.3.0 + +### Query Metadata Changes + +* The precision of `rb/useless-assignment-to-local` has been adjusted from `medium` to `high`. +* The tag `external/cwe/cwe-94` has been removed from `rb/server-side-template-injection` and the tag `external/cwe/cwe-094` has been added. + ## 1.2.1 No user-facing changes. diff --git a/ruby/ql/src/change-notes/2025-05-12-rb-useless-assignment-to-local-precision-high.md b/ruby/ql/src/change-notes/2025-05-12-rb-useless-assignment-to-local-precision-high.md deleted file mode 100644 index c62510ba5ba4..000000000000 --- a/ruby/ql/src/change-notes/2025-05-12-rb-useless-assignment-to-local-precision-high.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -category: queryMetadata ---- - -* The precision of `rb/useless-assignment-to-local` has been adjusted from `medium` to `high`. diff --git a/ruby/ql/src/change-notes/2025-05-01-cwe-tag-changed.md b/ruby/ql/src/change-notes/released/1.3.0.md similarity index 51% rename from ruby/ql/src/change-notes/2025-05-01-cwe-tag-changed.md rename to ruby/ql/src/change-notes/released/1.3.0.md index c8fd8d626866..5b2538735d09 100644 --- a/ruby/ql/src/change-notes/2025-05-01-cwe-tag-changed.md +++ b/ruby/ql/src/change-notes/released/1.3.0.md @@ -1,5 +1,6 @@ ---- -category: queryMetadata ---- +## 1.3.0 +### Query Metadata Changes + +* The precision of `rb/useless-assignment-to-local` has been adjusted from `medium` to `high`. * The tag `external/cwe/cwe-94` has been removed from `rb/server-side-template-injection` and the tag `external/cwe/cwe-094` has been added. diff --git a/ruby/ql/src/codeql-pack.release.yml b/ruby/ql/src/codeql-pack.release.yml index 73dd403938c9..ec16350ed6fd 100644 --- a/ruby/ql/src/codeql-pack.release.yml +++ b/ruby/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.2.1 +lastReleaseVersion: 1.3.0 diff --git a/ruby/ql/src/qlpack.yml b/ruby/ql/src/qlpack.yml index b2f8b36fc8a8..c7a150408638 100644 --- a/ruby/ql/src/qlpack.yml +++ b/ruby/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-queries -version: 1.2.2-dev +version: 1.3.0 groups: - ruby - queries diff --git a/rust/ql/lib/CHANGELOG.md b/rust/ql/lib/CHANGELOG.md index 6c0dda8457ac..3000a1098cc4 100644 --- a/rust/ql/lib/CHANGELOG.md +++ b/rust/ql/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.8 + +No user-facing changes. + ## 0.1.7 No user-facing changes. diff --git a/rust/ql/lib/change-notes/released/0.1.8.md b/rust/ql/lib/change-notes/released/0.1.8.md new file mode 100644 index 000000000000..5b20b52baf19 --- /dev/null +++ b/rust/ql/lib/change-notes/released/0.1.8.md @@ -0,0 +1,3 @@ +## 0.1.8 + +No user-facing changes. diff --git a/rust/ql/lib/codeql-pack.release.yml b/rust/ql/lib/codeql-pack.release.yml index 949d4c64c66f..3136ea4a1cc9 100644 --- a/rust/ql/lib/codeql-pack.release.yml +++ b/rust/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.1.7 +lastReleaseVersion: 0.1.8 diff --git a/rust/ql/lib/qlpack.yml b/rust/ql/lib/qlpack.yml index 9b7b15b43faf..7660d75b460b 100644 --- a/rust/ql/lib/qlpack.yml +++ b/rust/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/rust-all -version: 0.1.8-dev +version: 0.1.8 groups: rust extractor: rust dbscheme: rust.dbscheme diff --git a/rust/ql/src/CHANGELOG.md b/rust/ql/src/CHANGELOG.md index cc9fb2bcf682..a7c23fbfd30a 100644 --- a/rust/ql/src/CHANGELOG.md +++ b/rust/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.8 + +No user-facing changes. + ## 0.1.7 ### Minor Analysis Improvements diff --git a/rust/ql/src/change-notes/released/0.1.8.md b/rust/ql/src/change-notes/released/0.1.8.md new file mode 100644 index 000000000000..5b20b52baf19 --- /dev/null +++ b/rust/ql/src/change-notes/released/0.1.8.md @@ -0,0 +1,3 @@ +## 0.1.8 + +No user-facing changes. diff --git a/rust/ql/src/codeql-pack.release.yml b/rust/ql/src/codeql-pack.release.yml index 949d4c64c66f..3136ea4a1cc9 100644 --- a/rust/ql/src/codeql-pack.release.yml +++ b/rust/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.1.7 +lastReleaseVersion: 0.1.8 diff --git a/rust/ql/src/qlpack.yml b/rust/ql/src/qlpack.yml index b1a919d02eb6..75845fd10e1d 100644 --- a/rust/ql/src/qlpack.yml +++ b/rust/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/rust-queries -version: 0.1.8-dev +version: 0.1.8 groups: - rust - queries diff --git a/shared/controlflow/CHANGELOG.md b/shared/controlflow/CHANGELOG.md index d69921efe23b..1aab9a2eebaf 100644 --- a/shared/controlflow/CHANGELOG.md +++ b/shared/controlflow/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.7 + +No user-facing changes. + ## 2.0.6 No user-facing changes. diff --git a/shared/controlflow/change-notes/released/2.0.7.md b/shared/controlflow/change-notes/released/2.0.7.md new file mode 100644 index 000000000000..4eb1353458c2 --- /dev/null +++ b/shared/controlflow/change-notes/released/2.0.7.md @@ -0,0 +1,3 @@ +## 2.0.7 + +No user-facing changes. diff --git a/shared/controlflow/codeql-pack.release.yml b/shared/controlflow/codeql-pack.release.yml index fbbc03c76427..08d5e9594498 100644 --- a/shared/controlflow/codeql-pack.release.yml +++ b/shared/controlflow/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 2.0.6 +lastReleaseVersion: 2.0.7 diff --git a/shared/controlflow/qlpack.yml b/shared/controlflow/qlpack.yml index 70edae6befd5..7a8528bcf06f 100644 --- a/shared/controlflow/qlpack.yml +++ b/shared/controlflow/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/controlflow -version: 2.0.7-dev +version: 2.0.7 groups: shared library: true dependencies: diff --git a/shared/dataflow/CHANGELOG.md b/shared/dataflow/CHANGELOG.md index e07fdc75a97d..36d289f7f049 100644 --- a/shared/dataflow/CHANGELOG.md +++ b/shared/dataflow/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.7 + +No user-facing changes. + ## 2.0.6 No user-facing changes. diff --git a/shared/dataflow/change-notes/released/2.0.7.md b/shared/dataflow/change-notes/released/2.0.7.md new file mode 100644 index 000000000000..4eb1353458c2 --- /dev/null +++ b/shared/dataflow/change-notes/released/2.0.7.md @@ -0,0 +1,3 @@ +## 2.0.7 + +No user-facing changes. diff --git a/shared/dataflow/codeql-pack.release.yml b/shared/dataflow/codeql-pack.release.yml index fbbc03c76427..08d5e9594498 100644 --- a/shared/dataflow/codeql-pack.release.yml +++ b/shared/dataflow/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 2.0.6 +lastReleaseVersion: 2.0.7 diff --git a/shared/dataflow/qlpack.yml b/shared/dataflow/qlpack.yml index de4dfb3dfe0e..30e12f194562 100644 --- a/shared/dataflow/qlpack.yml +++ b/shared/dataflow/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/dataflow -version: 2.0.7-dev +version: 2.0.7 groups: shared library: true dependencies: diff --git a/shared/mad/CHANGELOG.md b/shared/mad/CHANGELOG.md index cb5108afd2c7..5efa3ce9aec8 100644 --- a/shared/mad/CHANGELOG.md +++ b/shared/mad/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.23 + +No user-facing changes. + ## 1.0.22 No user-facing changes. diff --git a/shared/mad/change-notes/released/1.0.23.md b/shared/mad/change-notes/released/1.0.23.md new file mode 100644 index 000000000000..8480f179393b --- /dev/null +++ b/shared/mad/change-notes/released/1.0.23.md @@ -0,0 +1,3 @@ +## 1.0.23 + +No user-facing changes. diff --git a/shared/mad/codeql-pack.release.yml b/shared/mad/codeql-pack.release.yml index 27d922b5ea6d..0f96ba41d168 100644 --- a/shared/mad/codeql-pack.release.yml +++ b/shared/mad/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.22 +lastReleaseVersion: 1.0.23 diff --git a/shared/mad/qlpack.yml b/shared/mad/qlpack.yml index d1e4d3fd45e6..96556fa674b5 100644 --- a/shared/mad/qlpack.yml +++ b/shared/mad/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/mad -version: 1.0.23-dev +version: 1.0.23 groups: shared library: true dependencies: diff --git a/shared/quantum/CHANGELOG.md b/shared/quantum/CHANGELOG.md new file mode 100644 index 000000000000..59b60bad0f37 --- /dev/null +++ b/shared/quantum/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +No user-facing changes. diff --git a/shared/quantum/change-notes/released/0.0.1.md b/shared/quantum/change-notes/released/0.0.1.md new file mode 100644 index 000000000000..59b60bad0f37 --- /dev/null +++ b/shared/quantum/change-notes/released/0.0.1.md @@ -0,0 +1,3 @@ +## 0.0.1 + +No user-facing changes. diff --git a/shared/quantum/codeql-pack.release.yml b/shared/quantum/codeql-pack.release.yml new file mode 100644 index 000000000000..c6933410b71c --- /dev/null +++ b/shared/quantum/codeql-pack.release.yml @@ -0,0 +1,2 @@ +--- +lastReleaseVersion: 0.0.1 diff --git a/shared/quantum/qlpack.yml b/shared/quantum/qlpack.yml index 8e34c19c1121..87daa7dc97d5 100644 --- a/shared/quantum/qlpack.yml +++ b/shared/quantum/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/quantum -version: 0.0.0-dev +version: 0.0.1 groups: shared library: true dependencies: diff --git a/shared/rangeanalysis/CHANGELOG.md b/shared/rangeanalysis/CHANGELOG.md index ed8f8e1eab3d..75bb80c6db72 100644 --- a/shared/rangeanalysis/CHANGELOG.md +++ b/shared/rangeanalysis/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.23 + +No user-facing changes. + ## 1.0.22 No user-facing changes. diff --git a/shared/rangeanalysis/change-notes/released/1.0.23.md b/shared/rangeanalysis/change-notes/released/1.0.23.md new file mode 100644 index 000000000000..8480f179393b --- /dev/null +++ b/shared/rangeanalysis/change-notes/released/1.0.23.md @@ -0,0 +1,3 @@ +## 1.0.23 + +No user-facing changes. diff --git a/shared/rangeanalysis/codeql-pack.release.yml b/shared/rangeanalysis/codeql-pack.release.yml index 27d922b5ea6d..0f96ba41d168 100644 --- a/shared/rangeanalysis/codeql-pack.release.yml +++ b/shared/rangeanalysis/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.22 +lastReleaseVersion: 1.0.23 diff --git a/shared/rangeanalysis/qlpack.yml b/shared/rangeanalysis/qlpack.yml index ccb83d389295..e3025d785223 100644 --- a/shared/rangeanalysis/qlpack.yml +++ b/shared/rangeanalysis/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/rangeanalysis -version: 1.0.23-dev +version: 1.0.23 groups: shared library: true dependencies: diff --git a/shared/regex/CHANGELOG.md b/shared/regex/CHANGELOG.md index 49ac9b18d4b1..59bbd8cf93b5 100644 --- a/shared/regex/CHANGELOG.md +++ b/shared/regex/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.23 + +No user-facing changes. + ## 1.0.22 No user-facing changes. diff --git a/shared/regex/change-notes/released/1.0.23.md b/shared/regex/change-notes/released/1.0.23.md new file mode 100644 index 000000000000..8480f179393b --- /dev/null +++ b/shared/regex/change-notes/released/1.0.23.md @@ -0,0 +1,3 @@ +## 1.0.23 + +No user-facing changes. diff --git a/shared/regex/codeql-pack.release.yml b/shared/regex/codeql-pack.release.yml index 27d922b5ea6d..0f96ba41d168 100644 --- a/shared/regex/codeql-pack.release.yml +++ b/shared/regex/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.22 +lastReleaseVersion: 1.0.23 diff --git a/shared/regex/qlpack.yml b/shared/regex/qlpack.yml index 763f7edc7433..02983bb3ce54 100644 --- a/shared/regex/qlpack.yml +++ b/shared/regex/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/regex -version: 1.0.23-dev +version: 1.0.23 groups: shared library: true dependencies: diff --git a/shared/ssa/CHANGELOG.md b/shared/ssa/CHANGELOG.md index 58ac1a04d04b..509445eb6b13 100644 --- a/shared/ssa/CHANGELOG.md +++ b/shared/ssa/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.2 + +No user-facing changes. + ## 1.1.1 No user-facing changes. diff --git a/shared/ssa/change-notes/released/1.1.2.md b/shared/ssa/change-notes/released/1.1.2.md new file mode 100644 index 000000000000..ce8d2c1a4f37 --- /dev/null +++ b/shared/ssa/change-notes/released/1.1.2.md @@ -0,0 +1,3 @@ +## 1.1.2 + +No user-facing changes. diff --git a/shared/ssa/codeql-pack.release.yml b/shared/ssa/codeql-pack.release.yml index 1a19084be3f7..53ab127707fc 100644 --- a/shared/ssa/codeql-pack.release.yml +++ b/shared/ssa/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.1.1 +lastReleaseVersion: 1.1.2 diff --git a/shared/ssa/qlpack.yml b/shared/ssa/qlpack.yml index 2010bbe1e12e..f6a6ce660752 100644 --- a/shared/ssa/qlpack.yml +++ b/shared/ssa/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ssa -version: 1.1.2-dev +version: 1.1.2 groups: shared library: true dependencies: diff --git a/shared/threat-models/CHANGELOG.md b/shared/threat-models/CHANGELOG.md index b09bc81cffe9..c3254e1caad7 100644 --- a/shared/threat-models/CHANGELOG.md +++ b/shared/threat-models/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.23 + +No user-facing changes. + ## 1.0.22 No user-facing changes. diff --git a/shared/threat-models/change-notes/released/1.0.23.md b/shared/threat-models/change-notes/released/1.0.23.md new file mode 100644 index 000000000000..8480f179393b --- /dev/null +++ b/shared/threat-models/change-notes/released/1.0.23.md @@ -0,0 +1,3 @@ +## 1.0.23 + +No user-facing changes. diff --git a/shared/threat-models/codeql-pack.release.yml b/shared/threat-models/codeql-pack.release.yml index 27d922b5ea6d..0f96ba41d168 100644 --- a/shared/threat-models/codeql-pack.release.yml +++ b/shared/threat-models/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.22 +lastReleaseVersion: 1.0.23 diff --git a/shared/threat-models/qlpack.yml b/shared/threat-models/qlpack.yml index 7b0cad6d5f99..3231707ef499 100644 --- a/shared/threat-models/qlpack.yml +++ b/shared/threat-models/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/threat-models -version: 1.0.23-dev +version: 1.0.23 library: true groups: shared dataExtensions: diff --git a/shared/tutorial/CHANGELOG.md b/shared/tutorial/CHANGELOG.md index 1da44a270de6..247d9be86a5e 100644 --- a/shared/tutorial/CHANGELOG.md +++ b/shared/tutorial/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.23 + +No user-facing changes. + ## 1.0.22 No user-facing changes. diff --git a/shared/tutorial/change-notes/released/1.0.23.md b/shared/tutorial/change-notes/released/1.0.23.md new file mode 100644 index 000000000000..8480f179393b --- /dev/null +++ b/shared/tutorial/change-notes/released/1.0.23.md @@ -0,0 +1,3 @@ +## 1.0.23 + +No user-facing changes. diff --git a/shared/tutorial/codeql-pack.release.yml b/shared/tutorial/codeql-pack.release.yml index 27d922b5ea6d..0f96ba41d168 100644 --- a/shared/tutorial/codeql-pack.release.yml +++ b/shared/tutorial/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.22 +lastReleaseVersion: 1.0.23 diff --git a/shared/tutorial/qlpack.yml b/shared/tutorial/qlpack.yml index 3ae10d7b4a1b..4102bfeb2f1e 100644 --- a/shared/tutorial/qlpack.yml +++ b/shared/tutorial/qlpack.yml @@ -1,7 +1,7 @@ name: codeql/tutorial description: Library for the CodeQL detective tutorials, helping new users learn to write CodeQL queries. -version: 1.0.23-dev +version: 1.0.23 groups: shared library: true warnOnImplicitThis: true diff --git a/shared/typeflow/CHANGELOG.md b/shared/typeflow/CHANGELOG.md index 3b08c24e221e..cad6ded5224f 100644 --- a/shared/typeflow/CHANGELOG.md +++ b/shared/typeflow/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.23 + +No user-facing changes. + ## 1.0.22 No user-facing changes. diff --git a/shared/typeflow/change-notes/released/1.0.23.md b/shared/typeflow/change-notes/released/1.0.23.md new file mode 100644 index 000000000000..8480f179393b --- /dev/null +++ b/shared/typeflow/change-notes/released/1.0.23.md @@ -0,0 +1,3 @@ +## 1.0.23 + +No user-facing changes. diff --git a/shared/typeflow/codeql-pack.release.yml b/shared/typeflow/codeql-pack.release.yml index 27d922b5ea6d..0f96ba41d168 100644 --- a/shared/typeflow/codeql-pack.release.yml +++ b/shared/typeflow/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.22 +lastReleaseVersion: 1.0.23 diff --git a/shared/typeflow/qlpack.yml b/shared/typeflow/qlpack.yml index 85f2c86741d2..485648dde5b6 100644 --- a/shared/typeflow/qlpack.yml +++ b/shared/typeflow/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/typeflow -version: 1.0.23-dev +version: 1.0.23 groups: shared library: true dependencies: diff --git a/shared/typeinference/CHANGELOG.md b/shared/typeinference/CHANGELOG.md index d7831747b120..4ffbff1e0c4e 100644 --- a/shared/typeinference/CHANGELOG.md +++ b/shared/typeinference/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.4 + +No user-facing changes. + ## 0.0.3 No user-facing changes. diff --git a/shared/typeinference/change-notes/released/0.0.4.md b/shared/typeinference/change-notes/released/0.0.4.md new file mode 100644 index 000000000000..eefe286a4d88 --- /dev/null +++ b/shared/typeinference/change-notes/released/0.0.4.md @@ -0,0 +1,3 @@ +## 0.0.4 + +No user-facing changes. diff --git a/shared/typeinference/codeql-pack.release.yml b/shared/typeinference/codeql-pack.release.yml index a24b693d1e7a..ec411a674bcd 100644 --- a/shared/typeinference/codeql-pack.release.yml +++ b/shared/typeinference/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.0.3 +lastReleaseVersion: 0.0.4 diff --git a/shared/typeinference/qlpack.yml b/shared/typeinference/qlpack.yml index d949e23fe0fa..4c3dc975ca23 100644 --- a/shared/typeinference/qlpack.yml +++ b/shared/typeinference/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/typeinference -version: 0.0.4-dev +version: 0.0.4 groups: shared library: true dependencies: diff --git a/shared/typetracking/CHANGELOG.md b/shared/typetracking/CHANGELOG.md index 507a195aff80..16294923597f 100644 --- a/shared/typetracking/CHANGELOG.md +++ b/shared/typetracking/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.7 + +No user-facing changes. + ## 2.0.6 No user-facing changes. diff --git a/shared/typetracking/change-notes/released/2.0.7.md b/shared/typetracking/change-notes/released/2.0.7.md new file mode 100644 index 000000000000..4eb1353458c2 --- /dev/null +++ b/shared/typetracking/change-notes/released/2.0.7.md @@ -0,0 +1,3 @@ +## 2.0.7 + +No user-facing changes. diff --git a/shared/typetracking/codeql-pack.release.yml b/shared/typetracking/codeql-pack.release.yml index fbbc03c76427..08d5e9594498 100644 --- a/shared/typetracking/codeql-pack.release.yml +++ b/shared/typetracking/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 2.0.6 +lastReleaseVersion: 2.0.7 diff --git a/shared/typetracking/qlpack.yml b/shared/typetracking/qlpack.yml index 924fd143829d..afcebca713b6 100644 --- a/shared/typetracking/qlpack.yml +++ b/shared/typetracking/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/typetracking -version: 2.0.7-dev +version: 2.0.7 groups: shared library: true dependencies: diff --git a/shared/typos/CHANGELOG.md b/shared/typos/CHANGELOG.md index 9500437aa07e..c7ff1a773da2 100644 --- a/shared/typos/CHANGELOG.md +++ b/shared/typos/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.23 + +No user-facing changes. + ## 1.0.22 No user-facing changes. diff --git a/shared/typos/change-notes/released/1.0.23.md b/shared/typos/change-notes/released/1.0.23.md new file mode 100644 index 000000000000..8480f179393b --- /dev/null +++ b/shared/typos/change-notes/released/1.0.23.md @@ -0,0 +1,3 @@ +## 1.0.23 + +No user-facing changes. diff --git a/shared/typos/codeql-pack.release.yml b/shared/typos/codeql-pack.release.yml index 27d922b5ea6d..0f96ba41d168 100644 --- a/shared/typos/codeql-pack.release.yml +++ b/shared/typos/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.22 +lastReleaseVersion: 1.0.23 diff --git a/shared/typos/qlpack.yml b/shared/typos/qlpack.yml index 21912e1efdfa..15579110177e 100644 --- a/shared/typos/qlpack.yml +++ b/shared/typos/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/typos -version: 1.0.23-dev +version: 1.0.23 groups: shared library: true warnOnImplicitThis: true diff --git a/shared/util/CHANGELOG.md b/shared/util/CHANGELOG.md index 8a71bf4f263b..f6f7838bc2ee 100644 --- a/shared/util/CHANGELOG.md +++ b/shared/util/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.10 + +No user-facing changes. + ## 2.0.9 No user-facing changes. diff --git a/shared/util/change-notes/released/2.0.10.md b/shared/util/change-notes/released/2.0.10.md new file mode 100644 index 000000000000..37310f107aa0 --- /dev/null +++ b/shared/util/change-notes/released/2.0.10.md @@ -0,0 +1,3 @@ +## 2.0.10 + +No user-facing changes. diff --git a/shared/util/codeql-pack.release.yml b/shared/util/codeql-pack.release.yml index ce305265e337..96ea0220a690 100644 --- a/shared/util/codeql-pack.release.yml +++ b/shared/util/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 2.0.9 +lastReleaseVersion: 2.0.10 diff --git a/shared/util/qlpack.yml b/shared/util/qlpack.yml index e14572c562a8..6187f53a9c52 100644 --- a/shared/util/qlpack.yml +++ b/shared/util/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/util -version: 2.0.10-dev +version: 2.0.10 groups: shared library: true dependencies: null diff --git a/shared/xml/CHANGELOG.md b/shared/xml/CHANGELOG.md index 95a60e498bff..bdb83dc88300 100644 --- a/shared/xml/CHANGELOG.md +++ b/shared/xml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.23 + +No user-facing changes. + ## 1.0.22 No user-facing changes. diff --git a/shared/xml/change-notes/released/1.0.23.md b/shared/xml/change-notes/released/1.0.23.md new file mode 100644 index 000000000000..8480f179393b --- /dev/null +++ b/shared/xml/change-notes/released/1.0.23.md @@ -0,0 +1,3 @@ +## 1.0.23 + +No user-facing changes. diff --git a/shared/xml/codeql-pack.release.yml b/shared/xml/codeql-pack.release.yml index 27d922b5ea6d..0f96ba41d168 100644 --- a/shared/xml/codeql-pack.release.yml +++ b/shared/xml/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.22 +lastReleaseVersion: 1.0.23 diff --git a/shared/xml/qlpack.yml b/shared/xml/qlpack.yml index bfac4d918413..2555d030028a 100644 --- a/shared/xml/qlpack.yml +++ b/shared/xml/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/xml -version: 1.0.23-dev +version: 1.0.23 groups: shared library: true dependencies: diff --git a/shared/yaml/CHANGELOG.md b/shared/yaml/CHANGELOG.md index edddaed1fdd7..28ca258e0d54 100644 --- a/shared/yaml/CHANGELOG.md +++ b/shared/yaml/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.23 + +No user-facing changes. + ## 1.0.22 No user-facing changes. diff --git a/shared/yaml/change-notes/released/1.0.23.md b/shared/yaml/change-notes/released/1.0.23.md new file mode 100644 index 000000000000..8480f179393b --- /dev/null +++ b/shared/yaml/change-notes/released/1.0.23.md @@ -0,0 +1,3 @@ +## 1.0.23 + +No user-facing changes. diff --git a/shared/yaml/codeql-pack.release.yml b/shared/yaml/codeql-pack.release.yml index 27d922b5ea6d..0f96ba41d168 100644 --- a/shared/yaml/codeql-pack.release.yml +++ b/shared/yaml/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.0.22 +lastReleaseVersion: 1.0.23 diff --git a/shared/yaml/qlpack.yml b/shared/yaml/qlpack.yml index 7aed9bae5e95..f1cb000d7401 100644 --- a/shared/yaml/qlpack.yml +++ b/shared/yaml/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/yaml -version: 1.0.23-dev +version: 1.0.23 groups: shared library: true warnOnImplicitThis: true diff --git a/swift/ql/lib/CHANGELOG.md b/swift/ql/lib/CHANGELOG.md index 7409680a2e19..36f0bc8e5fd5 100644 --- a/swift/ql/lib/CHANGELOG.md +++ b/swift/ql/lib/CHANGELOG.md @@ -1,3 +1,9 @@ +## 4.3.0 + +### New Features + +* Added AST nodes `UnsafeCastExpr`, `TypeValueExpr`, `IntegerType`, and `BuiltinFixedArrayType` that correspond to new nodes added by Swift 6.1. + ## 4.2.0 ### Major Analysis Improvements diff --git a/swift/ql/lib/change-notes/2025-05-02-new-entities.md b/swift/ql/lib/change-notes/released/4.3.0.md similarity index 83% rename from swift/ql/lib/change-notes/2025-05-02-new-entities.md rename to swift/ql/lib/change-notes/released/4.3.0.md index 55472b08ff8f..499b7c8e9a35 100644 --- a/swift/ql/lib/change-notes/2025-05-02-new-entities.md +++ b/swift/ql/lib/change-notes/released/4.3.0.md @@ -1,4 +1,5 @@ ---- -category: feature ---- +## 4.3.0 + +### New Features + * Added AST nodes `UnsafeCastExpr`, `TypeValueExpr`, `IntegerType`, and `BuiltinFixedArrayType` that correspond to new nodes added by Swift 6.1. diff --git a/swift/ql/lib/codeql-pack.release.yml b/swift/ql/lib/codeql-pack.release.yml index 9fc6933b429f..c46c103a0bd7 100644 --- a/swift/ql/lib/codeql-pack.release.yml +++ b/swift/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 4.2.0 +lastReleaseVersion: 4.3.0 diff --git a/swift/ql/lib/qlpack.yml b/swift/ql/lib/qlpack.yml index 667ce5588c8e..baa74b0a388d 100644 --- a/swift/ql/lib/qlpack.yml +++ b/swift/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/swift-all -version: 4.2.1-dev +version: 4.3.0 groups: swift extractor: swift dbscheme: swift.dbscheme diff --git a/swift/ql/src/CHANGELOG.md b/swift/ql/src/CHANGELOG.md index 993a2252ae4d..7910cf095ce7 100644 --- a/swift/ql/src/CHANGELOG.md +++ b/swift/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.3 + +No user-facing changes. + ## 1.1.2 No user-facing changes. diff --git a/swift/ql/src/change-notes/released/1.1.3.md b/swift/ql/src/change-notes/released/1.1.3.md new file mode 100644 index 000000000000..e8f1701bd624 --- /dev/null +++ b/swift/ql/src/change-notes/released/1.1.3.md @@ -0,0 +1,3 @@ +## 1.1.3 + +No user-facing changes. diff --git a/swift/ql/src/codeql-pack.release.yml b/swift/ql/src/codeql-pack.release.yml index 53ab127707fc..35e710ab1bf0 100644 --- a/swift/ql/src/codeql-pack.release.yml +++ b/swift/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.1.2 +lastReleaseVersion: 1.1.3 diff --git a/swift/ql/src/qlpack.yml b/swift/ql/src/qlpack.yml index 482affb8e16d..513b7054ed13 100644 --- a/swift/ql/src/qlpack.yml +++ b/swift/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/swift-queries -version: 1.1.3-dev +version: 1.1.3 groups: - swift - queries