From 395d54bf867803acddc8012c4c44bf8b56531165 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Thu, 23 Jan 2025 12:46:09 +0100 Subject: [PATCH 001/189] 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 00000000000..bfdd509174e --- /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 002/189] WIP --- cpp/ql/lib/experimental/Quantum/Base.qll | 84 +++++------- .../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, 290 insertions(+), 54 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 bfdd509174e..8a910eb4414 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(); - /** - * digest:HashAlgorithm - */ override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) or - edgeName = "digest" and result = this.getHashAlgorithmOrUnknown() + edgeName = "digest" and result = this.getHashAlgorithm() + } + } + + 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() } } } diff --git a/cpp/ql/lib/experimental/Quantum/BaseBackup.qll b/cpp/ql/lib/experimental/Quantum/BaseBackup.qll new file mode 100644 index 00000000000..821c89eb8f5 --- /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 00000000000..108993fb134 --- /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 00000000000..b489a6630a0 --- /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 00000000000..a9ad5021a29 --- /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 00000000000..f5971da9644 --- /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 003/189] 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 8a910eb4414..22e810f4aff 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 b489a6630a0..17de5ddab60 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 004/189] 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 22e810f4aff..b3f4d619f4d 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() + } - override string getAlgorithmName() { hashTypeToNameMapping(this.getHashType(), result) } + 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" } + 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 108993fb134..c9398c9e324 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 17de5ddab60..852fedf646a 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 a9ad5021a29..87341a6b612 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 f5971da9644..3f48f156a43 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 005/189] 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 b3f4d619f4d..9be24ca6efa 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 00000000000..9be24ca6efa --- /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 00000000000..9abf3e7fa7e --- /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 00000000000..802ad23cf9d --- /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 2da0dd61f88..67f21ad0b24 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 006/189] 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 b3f4d619f4d..cb0f53f468e 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 821c89eb8f5..00000000000 --- 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 852fedf646a..18feda6c8c6 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 00000000000..1df6611aab9 --- /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 87341a6b612..00000000000 --- 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 00000000000..df1c58b1efb --- /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 00000000000..10ec895dc62 --- /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 007/189] 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 1df6611aab9..edcc40aca6a 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 008/189] 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 00000000000..bbcd60ee891 --- /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 00000000000..bef648d290a --- /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 00000000000..246f2b86367 --- /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 00000000000..672ad14e5df --- /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 009/189] 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 bef648d290a..fae5c4f806e 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 672ad14e5df..f35336a846f 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 010/189] 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 fae5c4f806e..8a613b66d02 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 00000000000..020ac1b8925 --- /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 011/189] 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 c9398c9e324..8f400858f07 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 18feda6c8c6..bf38e5c0ab5 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 6ffc77714d4..489de9f6cef 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 df1c58b1efb..9cbef951bbf 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 68b3bc08cf7..eba25db60d2 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 00000000000..768c64a0704 --- /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 012/189] 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 bbcd60ee891..a14f3b6836a 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 8a613b66d02..389235964b5 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 013/189] 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 389235964b5..f75cfe7fd08 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 014/189] 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 a14f3b6836a..00000000000 --- 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 246f2b86367..485b3e716e6 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 18b74a919dd..ae7f13ad7ab 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 eba25db60d2..aa626066684 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 015/189] 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 f75cfe7fd08..4443ce85159 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 aa626066684..2b2919b6d3f 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 016/189] 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 edcc40aca6a..00000000000 --- 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 00000000000..d9658105aeb --- /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 4443ce85159..44a753bb7db 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 00000000000..063cda564b6 --- /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 2b2919b6d3f..ad117674dff 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 017/189] Modify model to use newtypes, expand modeling --- cpp/ql/lib/experimental/Quantum/OpenSSL.qll | 208 ++++++-- java/ql/lib/experimental/Quantum/JCA.qll | 161 +++--- java/ql/src/experimental/Quantum/Test.ql | 7 +- .../codeql/cryptography/Model.qll | 467 ++++++++++++++++-- 4 files changed, 676 insertions(+), 167 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL.qll index bf38e5c0ab5..cb19092f3fd 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 } - class SHA1Algo extends Crypto::HashAlgorithm instanceof MacroAccess { - SHA1Algo() { this.getMacro().getName() = "SN_sha1" } - - override string getRawAlgorithmName() { result = "SN_sha1" } - - override Crypto::THashType getHashType() { result instanceof Crypto::SHA1 } + 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() + ) + } + + 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() 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 EVP_KDF_fetch_AlgorithmArg extends Expr { + EVP_KDF_fetch_AlgorithmArg() { exists(EVP_KDF_fetch_Call call | this = call.getAlgorithmArg()) } + } - class KDFAlgorithmStringLiteral extends Crypto::NodeBase instanceof StringLiteral { + predicate kdf_names(string algo) { algo = ["HKDF", "PKCS12KDF", "PBKDF2"] } + + class KDFAlgorithmStringLiteral extends 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()) - } + 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 Crypto::NodeBase getOrigin(string name) { + 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/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 44a753bb7db..807dec96ba4 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 } - class ModeOfOperationStringLiteral extends StringLiteral { - ModeOfOperationStringLiteral() { cipher_modes(this.(StringLiteral).getValue().splitAt("/")) } - - string getRawAlgorithmName() { result = this.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 - } - - override Crypto::TModeOperation getModeType() { - this.modeToNameMapping(result, this.getRawAlgorithmName()) - } - - override Crypto::LocatableElement getOrigin(string name) { - result = mode and name = mode.toString() + predicate isSink(DataFlow::Node sink) { + exists(CipherGetInstanceCall call | sink.asExpr() = call.getAlgorithmArg()) } } - abstract class CipherAlgorithmPadding extends Crypto::NodeBase { - string getValue() { result = "" } + module AlgorithmStringToFetchFlow = DataFlow::Global; + + class CipherGetInstanceAlgorithmArg extends Expr { + CipherGetInstanceAlgorithmArg() { + exists(CipherGetInstanceCall call | this = call.getArgument(0)) + } + + StringLiteral getOrigin() { + AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(result), DataFlow::exprNode(this)) + } + } + + class ModeStringLiteral extends Crypto::ModeOfOperation { + CipherStringLiteral instance; + + ModeStringLiteral() { + this = Crypto::TModeOfOperationAlgorithm(instance) and + exists(instance.getMode()) and + instance = any(CipherGetInstanceAlgorithmArg call).getOrigin() + } + + override Location getLocation() { result = instance.getLocation() } + + override string getRawAlgorithmName() { result = instance.getMode() } + + predicate modeToNameMapping(Crypto::TModeOperationType type, string name) { + super.modeToNameMapping(type, name) + } + + override Crypto::TModeOperationType getModeType() { + this.modeToNameMapping(result, instance.getMode().toUpperCase()) + } + + 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; - AESAlgo() { algorithmStringToCipherInstanceArgFlow("AES", alg, this) } + CipherAlgorithm() { + this = Crypto::TSymmetricAlgorithm(instance) and + instance.getOrigin() = origin + } + + 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 = origin.getValue() } - override string getRawAlgorithmName() { result = alg.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 f35336a846f..f3ae23a2cca 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 ad117674dff..dd570a89ef6 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 SHA256 and name = "SHA-256" + type instanceof SHA2 and name = "SHA2" or - type instanceof SHA512 and name = "SHA-512" + 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 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() } + } + + /** + * 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 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 HKDF extends KeyDerivationAlgorithm { + 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 + ) + ) } } /** - * PKCS #12 key derivation function + * PKCS12KDF key derivation function */ - abstract class PKCS12KDF extends KeyDerivationAlgorithm { - final override string getAlgorithmName() { result = "PKCS12KDF" } + abstract class PKCS12KDF extends KeyDerivationWithDigestParameter { + override string getAlgorithmName() { result = "PKCS12KDF" } - abstract HashAlgorithm getHashAlgorithm(); + /** + * Gets the iteration count of this key derivation algorithm. + */ + abstract string getIterationCount(Location location); - override NodeBase getChild(string edgeName) { - result = super.getChild(edgeName) + /** + * 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 - 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 = "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 018/189] 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 cb19092f3fd..821fc0aec8f 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) } + } + + 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) } - Expr getAlgorithmArg() { result = instance.getArgument(3) } - - 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 807dec96ba4..299d9558ee1 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 f3ae23a2cca..5496e5a70cf 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 dd570a89ef6..38ea6e475c0 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 019/189] Expand model and JCA modeling --- java/ql/lib/experimental/Quantum/JCA.qll | 151 ++++++++++++++++-- java/ql/src/experimental/Quantum/Test.ql | 6 +- .../codeql/cryptography/Model.qll | 124 +++++++++++--- 3 files changed, 238 insertions(+), 43 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 299d9558ee1..5a30e96b13c 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 - } - - bindingset[name] - predicate cipherNameMapping(Crypto::TCipherType type, string name) { - this.cipherNameMappingKnown(type, name) or - not this.cipherNameMappingKnown(_, name) and - type instanceof Crypto::OtherSymmetricCipherType + name = "RC5" and + type instanceof Crypto::RC5 + or + name = "RSA" and + type instanceof Crypto::RSA } } + + /** + * 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 5496e5a70cf..ba76213132c 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 38ea6e475c0..9814f151995 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 020/189] Continue Artifact data-flow WIP --- java/ql/lib/experimental/Quantum/JCA.qll | 37 ++++++--- java/ql/lib/experimental/Quantum/Language.qll | 80 ++++++++++++++++--- .../codeql/cryptography/Model.qll | 62 +++++++++++--- 3 files changed, 143 insertions(+), 36 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 5a30e96b13c..e961310334f 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 485b3e716e6..5801815109b 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() = "" } -} - -/** - * 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 { +private class UnknownDefaultLocation extends UnknownLocation { UnknownDefaultLocation() { locations_default(this, _, 0, 0, 0, 0) } } -module CryptoInput implements InputSig { - class LocatableElement = Lang::Element; +module CryptoInput implements InputSig { + class DataFlowNode = DataFlow::Node; + + class LocatableElement = Language::Element; class UnknownLocation = UnknownDefaultLocation; + + predicate rngToIvFlow(DataFlowNode rng, DataFlowNode iv) { none() } } -module Crypto = CryptographyBase; +/** + * Instantiate the model + */ +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() } +} + +class SecureRandomnessInstance extends RandomnessInstance { + SecureRandomnessInstance() { + exists(RandomDataSource s | this = s.getOutput() | + 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 import JCA diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 9814f151995..205400e8a3c 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 021/189] 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 e961310334f..5b55090bd9e 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 205400e8a3c..8a5011489a6 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 022/189] 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 5b55090bd9e..0f505e400a0 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 8a5011489a6..24e3d4f48eb 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; - abstract override EncryptionAlgorithm getAlgorithm(); + CipherOperation() { this = TCipherOperation(instance) } + + override Location getLocation() { result = instance.getLocation() } + + final TCipherOperationMode getCipherOperationMode() { + result = instance.getCipherOperationMode() + } + + final override EncryptionAlgorithm getAlgorithm() { result = instance.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 023/189] 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 24e3d4f48eb..17834343e6d 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 024/189] 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 0f505e400a0..0a7903aa272 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 025/189] 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 0a7903aa272..3c37d1d717e 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 026/189] 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 3c37d1d717e..acbe6c67888 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 17834343e6d..a0f22d0229b 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 027/189] 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 | 237 ++++++++++-------- 8 files changed, 299 insertions(+), 210 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 acbe6c67888..9892b445312 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 5801815109b..e88bce6d995 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 00000000000..cb0d6ff9d61 --- /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 ba76213132c..00000000000 --- 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 00000000000..6be308c2560 --- /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 9cbef951bbf..ef558ccf432 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 10ec895dc62..07400d6cd6a 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 a0f22d0229b..e5b91e198ea 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 CipherOperationMode getCipherOperationMode(); + abstract CipherOperationSubtype getCipherOperationSubtype(); + + 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) } + + final override string getInternalType() { result = "Nonce" } + + override Location getLocation() { result = instance.getLocation() } + + override DataFlowNode asOutputData() { result = instance.asOutputData() } + + override DataFlowNode getInputData() { result = instance.getInput() } } - 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() + 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() } - abstract TRNGSeedSecurity getSeedSecurity(Location location); + override DataFlowNode asOutputData() { result = instance.asOutputData() } + + 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 028/189] 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 e88bce6d995..f8b7bf7a914 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 e5b91e198ea..4e8dae8aa02 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 029/189] 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 9892b445312..df96a4460e2 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 f8b7bf7a914..5abac9e9462 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 6be308c2560..14041cd3b22 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 4e8dae8aa02..713c503ea65 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 class GenericDataSourceInstance extends ArtifactLocatableElement { } + 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 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 030/189] 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 | 1146 ++++++++++------- 5 files changed, 864 insertions(+), 718 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index df96a4460e2..f1e1ce9ccdc 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 Crypto::ArtifactConsumer getMessageConsumer() { + result = doFinalize.getMessageArg().asExpr() } - 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::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 5abac9e9462..228f21bd69b 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 predicate flowsTo(Crypto::ArtifactLocatableElement other) { - RNGToArtifactFlow::flow(this.asOutputData(), other.getInput()) + override DataFlow::Node getInputNode() { none() } // TODO: add seed + + 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 cb0d6ff9d61..7847781e0be 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 14041cd3b22..fa04770d854 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 713c503ea65..5889e9eb5e2 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); } - // 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 asset. + */ + abstract class KnownElement extends LocatableElement { + final ConsumerElement getAConsumer() { result.getAKnownSource() = this } + } - abstract string getLabel(); + /** + * 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(); + } + + /** + * 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(); + + 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? } - abstract class DigestArtifactInstance extends ArtifactLocatableElement { } + /** + * 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() } - abstract class KeyArtifactInstance extends ArtifactLocatableElement { } + override DataFlowNode getOutputNode() { none() } - abstract class NonceArtifactInstance extends ArtifactLocatableElement { - // no implicit outbound data-flow (only modelled in cipher operations) - override predicate flowsTo(ArtifactLocatableElement other) { 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() } } - abstract class RandomNumberGenerationInstance extends ArtifactLocatableElement { - final override DataFlowNode getInput() { none() } + /** + * 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 ArtifactConsumer extends ConsumerElement { + final override KnownElement getAKnownSource() { result = this.getAKnownArtifactSource() } + + 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 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 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(); } - class Asset = NodeBase; + /** + * 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 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,15 +522,367 @@ module CryptographyBase Input> { } } + newtype TCipherOperationSubtype = + TEncryptionMode() or + TDecryptionMode() or + TWrapMode() or + TUnwrapMode() or + TUnknownCipherOperationMode() + + abstract class CipherOperationSubtype extends TCipherOperationSubtype { + abstract string toString(); + } + + 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" } + } + + /** + * 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). + */ + final class CipherOperationNode extends OperationNode, TCipherOperation { + CipherOperationInstance instance; + + 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 + // [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.getANonceOrUnknown()) + then result = this.getANonceOrUnknown() + else result = this + or + // [KNOWN_OR_UNKNOWN] + key = "Message" and + if exists(this.getAMessageOrUnknown()) + then result = this.getAMessageOrUnknown() + 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.getCipherOperationSubtype().toString() and + location = this.getLocation() + } + } + + /** + * 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 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`. + */ + TBlockCipherModeOperationType getModeType() { result = instance.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() + + 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] + 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) } + + override string getRawAlgorithmName() { result = instance.getRawPaddingAlgorithmName() } + } + + /** + * 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() + + final class CipherAlgorithmNode extends AlgorithmNode, TCipherAlgorithm { + CipherAlgorithmInstance instance; + + CipherAlgorithmNode() { this = TCipherAlgorithm(instance) } + + override LocatableElement asElement() { result = instance } + + override string getInternalType() { result = "CipherAlgorithm" } + + final TCipherStructureType getCipherStructure() { + this.cipherFamilyToNameAndStructure(this.getCipherFamily(), _, result) + } + + final override string getAlgorithmName() { + this.cipherFamilyToNameAndStructure(this.getCipherFamily(), result, _) + } + + final override string getRawAlgorithmName() { result = instance.getRawAlgorithmName() } + + /** + * Gets the key size of this cipher, e.g., "128" or "256". + */ + string getKeySize(Location location) { none() } // TODO + + /** + * Gets the type of this cipher, e.g., "AES" or "ChaCha20". + */ + TCipherType getCipherFamily() { result = instance.getCipherFamily() } + + /** + * Gets the mode of operation of this cipher, e.g., "GCM" or "CBC". + */ + ModeOfOperationAlgorithmNode getModeOfOperation() { + result.asElement() = instance.getModeOfOperationAlgorithm() + } + + /** + * Gets the padding scheme of this cipher, e.g., "PKCS7" or "NoPadding". + */ + PaddingAlgorithmNode getPaddingAlgorithm() { + result.asElement() = instance.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 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 + // [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 + ) + ) + } + } + /** * 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" } + abstract class HashOperationNode extends OperationNode, THashOperation { + abstract HashAlgorithmNode getAlgorithm(); } newtype THashType = @@ -450,8 +899,8 @@ module CryptographyBase Input> { /** * A hashing algorithm that transforms variable-length input into a fixed-size hash value. */ - abstract class HashAlgorithm extends Algorithm, THashAlgorithm { - override string getAlgorithmType() { result = "HashAlgorithm" } + abstract class HashAlgorithmNode extends AlgorithmNode, THashAlgorithm { + override string getInternalType() { result = "HashAlgorithm" } final predicate hashTypeToNameMapping(THashType type, string name) { type instanceof MD2 and name = "MD2" @@ -539,11 +988,12 @@ module CryptographyBase Input> { /** * An operation that derives one or more keys from an input value. */ - abstract class KeyDerivationOperation extends Operation, TKeyDerivationOperation { + abstract class KeyDerivationOperationNode extends OperationNode, TKeyDerivationOperation { final override Location getLocation() { exists(LocatableElement le | this = TKeyDerivationOperation(le) and result = le.getLocation()) } - //override string getOperationType() { result = "KeyDerivationOperation" } + + override string getInternalType() { result = "KeyDerivationOperation" } } /** @@ -553,12 +1003,12 @@ module CryptographyBase Input> { * * For known algorithms, use the specialized classes, e.g., `HKDF` and `PKCS12KDF`. */ - abstract class KeyDerivationAlgorithm extends Algorithm, TKeyDerivationAlgorithm { + abstract class KeyDerivationAlgorithmNode extends AlgorithmNode, TKeyDerivationAlgorithm { final override Location getLocation() { exists(LocatableElement le | this = TKeyDerivationAlgorithm(le) and result = le.getLocation()) } - override string getAlgorithmType() { result = "KeyDerivationAlgorithm" } + override string getInternalType() { result = "KeyDerivationAlgorithm" } override string getAlgorithmName() { result = this.getRawAlgorithmName() } } @@ -566,8 +1016,8 @@ module CryptographyBase Input> { /** * 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(); + abstract private class KeyDerivationWithDigestParameterNode extends KeyDerivationAlgorithmNode { + abstract HashAlgorithmNode getHashAlgorithm(); override NodeBase getChild(string edgeName) { result = super.getChild(edgeName) @@ -583,14 +1033,14 @@ module CryptographyBase Input> { /** * HKDF key derivation function */ - abstract class HKDF extends KeyDerivationWithDigestParameter { + abstract class HKDFNode extends KeyDerivationWithDigestParameterNode { final override string getAlgorithmName() { result = "HKDF" } } /** * PBKDF2 key derivation function */ - abstract class PBKDF2 extends KeyDerivationWithDigestParameter { + abstract class PBKDF2Node extends KeyDerivationWithDigestParameterNode { final override string getAlgorithmName() { result = "PBKDF2" } /** @@ -631,7 +1081,7 @@ module CryptographyBase Input> { /** * PKCS12KDF key derivation function */ - abstract class PKCS12KDF extends KeyDerivationWithDigestParameter { + abstract class PKCS12KDF extends KeyDerivationWithDigestParameterNode { override string getAlgorithmName() { result = "PKCS12KDF" } /** @@ -685,7 +1135,7 @@ module CryptographyBase Input> { /** * scrypt key derivation function */ - abstract class SCRYPT extends KeyDerivationAlgorithm { + abstract class SCRYPT extends KeyDerivationAlgorithmNode { final override string getAlgorithmName() { result = "scrypt" } /** @@ -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 031/189] 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 5889e9eb5e2..2006804952a 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 032/189] Make ArtifactConsumers instances of some Artifacts TODO: refactor the interfaces --- java/ql/lib/experimental/Quantum/JCA.qll | 52 ++++++++----------- java/ql/lib/experimental/Quantum/Language.qll | 39 +++++++++++++- .../codeql/cryptography/Model.qll | 19 +++---- 3 files changed, 69 insertions(+), 41 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index f1e1ce9ccdc..4370d34ca28 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 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.getInputNode() and - node2.asExpr() = n - ) - } + 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() + ) } - module NonceArtifactToCipherInitCallFlow = DataFlow::Global; + class NonceAdditionalFlowInputStep extends AdditionalFlowInputStep { + DataFlow::Node output; + + NonceAdditionalFlowInputStep() { additionalFlowSteps(this, output) } + + 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 228f21bd69b..a2945bb6dd3 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 2006804952a..8799bbef572 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 033/189] Add input and output nodes and fix cross product --- java/ql/lib/experimental/Quantum/JCA.qll | 42 +++-- java/ql/lib/experimental/Quantum/Language.qll | 72 ++++++--- .../codeql/cryptography/Model.qll | 147 ++++++++++++++---- 3 files changed, 196 insertions(+), 65 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 4370d34ca28..8d748772bff 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 a2945bb6dd3..03c35100538 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,29 +111,10 @@ 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() - } - - predicate isSink(DataFlow::Node sink) { - sink = any(Crypto::FlowAwareElement other).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; -class NonceArtifactInstance extends Crypto::NonceArtifactInstance { - NonceArtifactInstance() { this instanceof Crypto::NonceArtifactConsumer } - +class NonceArtifactConsumer extends Crypto::NonceArtifactInstance instanceof Crypto::NonceArtifactConsumer +{ override predicate flowsTo(Crypto::FlowAwareElement other) { ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) } @@ -149,6 +128,27 @@ class NonceArtifactInstance extends Crypto::NonceArtifactInstance { } } +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() } +} + /** * Generic data source to node input configuration */ @@ -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 8799bbef572..83111519a00 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 LocatableElement getAKnownOrUnknownSource() { - result = this.getAKnownSource() - or - result = this.getAnUnknownSource() + final GenericDataSourceInstance getAnUnknownSource() { + result.flowsTo(this) and not result = this.getAKnownSource() } - NodeBase getAKnownOrUnknownSourceNode() { result.asElement() = this.getAKnownOrUnknownSource() } + final GenericSourceNode getAnUnknownSourceNode() { + result.asElement() = this.getAnUnknownSource() + } + + 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 034/189] 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 8d748772bff..5cb7bcf23dc 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 03c35100538..0e875295bd8 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 83111519a00..243d52cd2e6 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,23 +241,24 @@ 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 ArtifactConsumerAndInstance extends ArtifactConsumer { + final override DataFlowNode getOutputNode() { none() } + + final override predicate flowsTo(FlowAwareElement other) { none() } } - abstract class CipherInputArtifactInstance extends ArtifactElement { } - - abstract class CipherInputConsumer extends ArtifactConsumer, CipherInputArtifactInstance { - CipherInputArtifactInstance asCipherInput() { result = this } + abstract class CipherOutputArtifactInstance extends ArtifactElement { + final override DataFlowNode getInputNode() { none() } } - 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. @@ -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 KeyArtifactInstance extends ArtifactElement { } + abstract class DigestArtifactInstance extends OutputArtifactElement { } - abstract class NonceArtifactInstance extends ArtifactElement { } + abstract class RandomNumberGenerationInstance extends OutputArtifactElement { } // TODO: is this an OutputArtifactElement if it takes a seed? - abstract class RandomNumberGenerationInstance 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 CipherInputConsumer extends ArtifactConsumerAndInstance { } + + // 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 035/189] 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 00000000000..ba43413d281 --- /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 036/189] 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 ba43413d281..cdeeebd5a7d 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 037/189] 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 00000000000..fde1ef12178 --- /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 038/189] 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 7847781e0be..00000000000 --- 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 039/189] Initial OpenSSL modeling work. --- cpp/ql/lib/experimental/Quantum/Language.qll | 125 +- 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, 3674 insertions(+), 247 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 8f400858f07..3f1d9aa9bdf 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 LocatableElement = Lang::Locatable; +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 821fc0aec8f..00000000000 --- 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 00000000000..f409578e98d --- /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 00000000000..54be40729b6 --- /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 00000000000..ceabae77374 --- /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 00000000000..12cbe4da650 --- /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 00000000000..4913d2763e9 --- /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 00000000000..f942f4687da --- /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 040/189] 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 | 64 +-- 8 files changed, 652 insertions(+), 150 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 3f1d9aa9bdf..5d4ff4bc686 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 54be40729b6..e1b08c9652d 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 00000000000..046abf3f43a --- /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 ceabae77374..8717a857385 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 00000000000..3cd359ce58b --- /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 00000000000..79491ca2a09 --- /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 f409578e98d..dcf24d01ace 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 243d52cd2e6..522ff3b2784 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 - DES() or - TripleDES() or - IDEA() or + ARIA() or + BLOWFISH() or + CAMELLIA() or CAST5() or - ChaCha20() 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 - 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 041/189] 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 046abf3f43a..c6810c0ab39 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 79491ca2a09..0b1f5546c4b 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 042/189] 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 5cb7bcf23dc..5d5184fdda2 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 043/189] 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 c6810c0ab39..8aa4f88a81b 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 00000000000..aa9c4008dd1 --- /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 00000000000..91b3f2ea62b --- /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 0b1f5546c4b..30ffd1e1f3e 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 5d5184fdda2..b2698cabee2 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 522ff3b2784..e3a1a6123ec 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 044/189] 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 e3a1a6123ec..5a6cd3288fe 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 045/189] 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 5a6cd3288fe..433c97a8387 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 046/189] Initial hash models for openssl. --- cpp/ql/lib/experimental/Quantum/Language.qll | 128 +++++++++--------- .../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, 312 insertions(+), 106 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 5d4ff4bc686..f0775df1b2e 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() - } - - 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 +// /** +// * Generic data source to node input configuration +// */ +// module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig { +// predicate isSource(DataFlow::Node source) { +// source = any(Crypto::GenericDataSourceInstance i).getOutputNode() // } -// override predicate flowsTo(Crypto::FlowAwareElement other) { -// // TODO: separate config to avoid blowing up data-flow analysis -// GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) +// predicate isSink(DataFlow::Node sink) { +// sink = any(Crypto::FlowAwareElement 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 +// predicate isBarrierOut(DataFlow::Node node) { +// node = any(Crypto::FlowAwareElement element).getInputNode() // } -// override DataFlow::Node getOutputNode() { result.asExpr() = this } - -// override predicate flowsTo(Crypto::FlowAwareElement other) { -// GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode()) +// predicate isBarrierIn(DataFlow::Node node) { +// node = any(Crypto::FlowAwareElement element).getOutputNode() // } -// 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()) +// predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { +// node1.(AdditionalFlowInputStep).getOutput() = node2 // } - -// override string getAdditionalDescription() { result = this.toString() } // } -module GenericDataSourceUniversalFlow = DataFlow::Global; + +// // // 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) { diff --git a/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPDigestAlgorithmSource.qll b/cpp/ql/lib/experimental/Quantum/OpenSSL/EVPDigestAlgorithmSource.qll index aa9c4008dd1..7d132b22a3a 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 00000000000..ad2af7e05be --- /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 00000000000..31bf00ef94a --- /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 00000000000..16a9234d68c --- /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 91b3f2ea62b..7db90c4eccc 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 dcf24d01ace..76c6c172bf6 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 5a6cd3288fe..bc763175589 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 047/189] 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 25165cf5bf3..bbe817e2110 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 048/189] 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 e1b08c9652d..c07902022d8 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 049/189] 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 76c6c172bf6..063a7084d3d 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 050/189] 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 30ffd1e1f3e..cee5937d551 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 051/189] 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 8aa4f88a81b..4523bd86035 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 052/189] 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 4523bd86035..2c1930698b1 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 8717a857385..4f8a5ccd354 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 7d132b22a3a..00000000000 --- 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 ad2af7e05be..5fc61c7b6c5 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 31bf00ef94a..2edca9d5763 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 cee5937d551..689f022b56d 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 bbe817e2110..298b270e6b6 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 053/189] 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 f942f4687da..6c30bec16cd 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 054/189] 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 298b270e6b6..0e8a3959675 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 055/189] 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 6c30bec16cd..9e48f8cbb93 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 00000000000..eceff874874 --- /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 056/189] 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 9e48f8cbb93..16b9e6485c9 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 689f022b56d..02d0d833918 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 057/189] Uncommenting out generic dataflow --- cpp/ql/lib/experimental/Quantum/Language.qll | 40 ++++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index f0775df1b2e..5ec4da8d19d 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() -// } +/** + * 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 + } +} From ae574f7cf2b67a981e7052851d23a85a601a421a Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 11 Mar 2025 13:35:02 -0400 Subject: [PATCH 058/189] 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 2c1930698b1..8718fb5b44d 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 5fc61c7b6c5..d89eee2590d 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 059/189] 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 063a7084d3d..0d328e287f6 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 060/189] 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 0e8a3959675..4ad83b12210 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 061/189] 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 d89eee2590d..d269658c8aa 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 4ad83b12210..74a9b5d02a7 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 062/189] 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 02d0d833918..364bb3ab0b8 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 063/189] 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 364bb3ab0b8..3e061eeff88 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 064/189] 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 4913d2763e9..fd95bb71805 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 065/189] 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 fd95bb71805..f426eb3f92d 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 066/189] 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 74a9b5d02a7..f5f57d245ba 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 067/189] 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 8718fb5b44d..65231e32cd0 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 068/189] 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 | 127 +++++- 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 | 401 +++++++++++++----- 10 files changed, 475 insertions(+), 167 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 5ec4da8d19d..dbcb2004b83 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 4f8a5ccd354..e2f5bc0e838 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 2edca9d5763..82bf331546f 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 b2698cabee2..336f7fe5cc5 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() } - - override DataFlow::Node getInputNode() { result.asExpr() = this } - } - 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 } } + + 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 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 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 0e875295bd8..5666a0c42bb 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 cdeeebd5a7d..7fea3515b7d 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 fde1ef12178..f9fc7a873db 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 fa04770d854..b98347a57ec 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 00000000000..96f99193cba --- /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 f5f57d245ba..cebbac2ff6b 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() } + + final LocatableElement getASource() { + result = this.getAnUnknownSource() or + result = this.getAKnownSource() + } + } + + abstract class AlgorithmValueConsumer extends ConsumerElement { + /** + * DO NOT USE. + * Model `getAKnownAlgorithmSource()` instead, which is equivalent but correctly typed. + */ + final override KnownElement getAKnownSource() { result = this.getAKnownAlgorithmSource() } + + /** + * Gets a known algorithm value that is equivalent to or consumed by this element. + */ + abstract AlgorithmInstance getAKnownAlgorithmSource(); } /** - * An element that consumes _known_ and _unknown_ values. - * - * A value consumer can consume multiple values and multiple value sources at once. + * An element that represents a _known_ cryptographic artifact. */ - 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 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() } - - final override predicate flowsTo(FlowAwareElement other) { 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() } } - abstract class CipherOutputArtifactInstance extends ArtifactElement { + 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; + + 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 CipherOperationInstance extends OperationElement { + abstract class RandomNumberGenerationInstance extends OutputArtifactInstance { + // TODO: input seed? + final override DataFlowNode getInputNode() { none() } + } + + abstract class CipherOutputArtifactInstance extends ArtifactInstance { + final override DataFlowNode getInputNode() { none() } + } + + // 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() } - abstract class KeyEncapsulationAlgorithmInstance extends LocatableElement { } + /** + * Gets the hash algorithm used in this padding scheme. + */ + abstract HashAlgorithmInstance getHashAlgorithm(); - abstract class EllipticCurveAlgorithmInstance extends LocatableElement { } - - abstract class HashOperationInstance extends OperationElement { - // TODO: need input and outputs, but this should be universal to all Operations + /** + * Gets the mask generation function used in this padding scheme. + */ + abstract HashAlgorithmInstance getMaskGenerationFunction(); } - abstract class HashAlgorithmInstance extends AlgorithmElement { + abstract class KeyEncapsulationOperationInstance extends OperationInstance { } + + abstract class KeyEncapsulationAlgorithmInstance extends AlgorithmInstance { } + + abstract class EllipticCurveAlgorithmInstance extends AlgorithmInstance { } + + abstract class HashOperationInstance extends OperationInstance { + abstract DigestArtifactInstance getDigestArtifact(); + } + + 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; + + module AlgorithmInstanceOrValueConsumer { + class Union extends LocatableElement { + Union() { + this instanceof Alg + or + this instanceof AlgorithmValueConsumer and + not exists(this.(AlgorithmValueConsumer).getASource()) + } + + Alg asAlg() { result = this } + + AlgorithmValueConsumer asAVC() { result = this } + } } - abstract class DigestArtifactInstance extends OutputArtifactElement { } + class CipherAlgorithmInstanceOrValueConsumer = + AlgorithmInstanceOrValueConsumer::Union; - abstract class RandomNumberGenerationInstance extends OutputArtifactElement { } // TODO: is this an OutputArtifactElement if it takes a seed? - - // 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 CipherInputConsumer extends ArtifactConsumerAndInstance { } - - // 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 069/189] . --- 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 | 1024 ++++++++--------- .../codeql/cryptography/Model.qll | 5 + 7 files changed, 555 insertions(+), 1122 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 dbcb2004b83..2dc17f5e267 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 65231e32cd0..00000000000 --- 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 12cbe4da650..00000000000 --- 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 f426eb3f92d..00000000000 --- 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 16b9e6485c9..1f9fb9a54ba 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 3e061eeff88..b436f3b412a 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(); +// } +// 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 -// 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) +// 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 = getSymmetricEncryptionType() } +// 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_MAC_fetch -// predicate macAlgorithmSink(string funcName, int argInd) { -// (funcName = "EVP_MAC_fetch" and argInd = 1) +// 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 MACAlgorithmSink extends AlgorithmSinkArgument { -// MACAlgorithmSink() { -// exists(Call c, string funcName, int argInd | -// funcName = c.getTarget().getName() and this = c.getArgument(argInd) -// | -// macAlgorithmSink(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 = "TBD" } +// 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_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) -// ) +// 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 = 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() } +// 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 cebbac2ff6b..2f5e2ca77fa 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 070/189] 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 336f7fe5cc5..e0e30f6d510 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 5666a0c42bb..e8bb052b620 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 b98347a57ec..8743ef3aa19 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 00000000000..1ae0cdfd89f --- /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 2f5e2ca77fa..2a006cd7f82 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() } + + override DataFlowNode getInputNode() { none() } } - abstract class DigestArtifactInstance extends OutputArtifactInstance { - final 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 071/189] 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 2f5e2ca77fa..577993e7f63 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 072/189] 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 e0e30f6d510..eac400183b8 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) + ) + } + + 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 Crypto::TBlockCipherModeOperationType getModeType() { - if this.modeToNameMappingKnown(_, super.getMode()) - then this.modeToNameMappingKnown(result, super.getMode()) - else result instanceof Crypto::OtherMode - } + override string getRawHashAlgorithmName() { result = super.getPadding() } - override string getRawModeAlgorithmName() { result = super.getMode() } + override Crypto::THashType getHashFamily() { result = hash_name_to_hash_type(hashName, _) } - override string getRawPaddingAlgorithmName() { result = super.getPadding() } + override int getDigestLength() { exists(hash_name_to_hash_type(hashName, result)) } + } - 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% - } + class OAEPPaddingAlgorithmInstance extends Crypto::OAEPPaddingAlgorithmInstance, + CipherStringLiteralPaddingAlgorithmInstance + { + override Crypto::HashAlgorithmInstance getOAEPEncodingHashAlgorithm() { result = this } - override Crypto::TPaddingType getPaddingType() { - if this.paddingToNameMappingKnown(_, super.getPadding()) - then this.paddingToNameMappingKnown(result, super.getPadding()) - else result instanceof Crypto::OtherPadding - } + 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 e8bb052b620..74edfec1d39 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 2a006cd7f82..0ed24452c0b 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 mask generation function used in this padding scheme. + * Gets the hash algorithm used by MGF1 (assumption: MGF1 is the only MGF used by OAEP) */ - abstract HashAlgorithmInstance getMaskGenerationFunction(); + 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 key used in this operation. + */ + 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()) + } - class HashAlgorithmInstanceOrValueConsumer = - AlgorithmInstanceOrValueConsumer::Union; + private predicate isCipherAVC(AlgorithmValueConsumer avc) { + exists(CipherOperationInstance op | op.getAnAlgorithmValueConsumer() = avc) + } - newtype TNode = + private predicate isMACAVC(AlgorithmValueConsumer avc) { + exists(MACOperationInstance op | op.getAnAlgorithmValueConsumer() = avc) + } + + final private class CipherAlgorithmInstanceOrValueConsumer = + AlgorithmInstanceOrValueConsumer::Union; + + final private class HashAlgorithmInstanceOrValueConsumer = + AlgorithmInstanceOrValueConsumer::Union; + + private class MACAlgorithmInstanceOrValueConsumer = + 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 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(); + THashType getHashFamily() { result = instance.asAlg().getHashFamily() } - override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashType(), result) } + override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashFamily(), 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" - } - - 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) - } + 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 073/189] 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 07400d6cd6a..fa4c2cb1d02 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 074/189] 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 | 1125 ++++++++++------- 3 files changed, 877 insertions(+), 507 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index eac400183b8..5cff0129b72 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 74edfec1d39..1621e9436c4 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 f2068192380..8252b513860 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" } } - abstract class GenericExternalCallSource extends GenericDataSourceInstance { + /** + * An element representing statically or dynamically allocated data. + */ + abstract class GenericAllocationSourceInstance extends GenericValueSourceInstance { + final override string getInternalType() { result = "Allocation" } + } + + /** + * 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,24 +1041,50 @@ 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" } override LocatableElement asElement() { result = instance } } + /** + * A message or plaintext/ciphertext input + */ + final class MessageArtifactNode extends ArtifactNode, TMessageInput { + MessageArtifactConsumer instance; + + MessageArtifactNode() { this = TMessageInput(instance) } + + final override string getInternalType() { result = "Message" } + + override LocatableElement asElement() { result = instance } + } + + /** + * 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 } + } + /** * Output text from a cipher operation */ @@ -836,19 +1100,6 @@ module CryptographyBase Input> { override string getSourceNodeRelationship() { none() } } - /** - * Input text to a cipher operation - */ - final class CipherInputNode extends ArtifactNode, TCipherInput { - CipherInputArtifactConsumer instance; - - CipherInputNode() { this = TCipherInput(instance) } - - final override string getInternalType() { result = "CipherInput" } - - override LocatableElement asElement() { result = instance } - } - /** * A source of random number generation */ @@ -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,60 +1287,13 @@ 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 LocatableElement asElement() { result = instance } - } - - /** - * A cryptographic operation, such as hashing or encryption. - */ - abstract class OperationNode extends AssetNode { } - - 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() - } - } - - final 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 predicate isCandidateKnownAlgorithmNode(AlgorithmNode node) { + node instanceof CipherAlgorithmNode } override NodeBase getChild(string key) { @@ -1099,6 +1305,236 @@ module CryptographyBase Input> { } } + class KeyDerivationOperationNode extends KeyCreationOperationNode { + KeyDerivationOperationInstance kdfInstance; + + KeyDerivationOperationNode() { kdfInstance = instance } + + 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 = "DefaultIterations" and + value = kdfInstance.getIterationCountFixed() and + location = this.getLocation() + or + // [ONLY_KNOWN] + 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) + } + } + + class KeyDerivationAlgorithmNode extends AlgorithmNode, TKeyDerivationAlgorithm { + KeyDerivationAlgorithmInstanceOrValueConsumer instance; + + KeyDerivationAlgorithmNode() { this = TKeyDerivationAlgorithm(instance) } + + final override string getInternalType() { result = "KeyDerivationAlgorithm" } + + override LocatableElement asElement() { result = instance } + + final override string getRawAlgorithmName() { + result = instance.asAlg().getRawKDFAlgorithmName() + } + + 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 + // [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 TDecryptionMode() 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() } + + MessageArtifactNode getAnInputArtifact() { + result.asElement() = instance.getInputConsumer().getConsumer() } - CipherInputNode getAnInputArtifact() { - result.asElement() = - Input::dfn_to_element(this.asElement().(CipherOperationInstance).getInputConsumer()) - } + CipherOutputNode getAnOutputArtifact() { result.asElement() = instance.getOutputArtifact() } - CipherOutputNode getAnOutputArtifact() { - result.asElement() = this.asElement().(CipherOperationInstance).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) + override NodeBase getChild(string key) { + result = super.getChild(key) 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 + 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 075/189] Misc. modifications to support elliptic curves and hooking them up to keygeneration. --- java/ql/lib/experimental/Quantum/JCA.qll | 241 ++++++++++++++---- java/ql/lib/experimental/Quantum/Language.qll | 8 + .../codeql/cryptography/Model.qll | 172 +++++++++++-- 3 files changed, 341 insertions(+), 80 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 5cff0129b72..bce4b117522 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; - CipherStringLiteralAlgorithmInstance() { - AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) + EllipticCurveStringLiteralAlgorithmInstance() { + // Trace a known elliptic curve algorithm string literal to a key gen consumer + EllipticCurveAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), + consumer.getInputNode()) } - Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } + 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() { + CipherAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) + } + + 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 1621e9436c4..55d4f497f8e 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 8252b513860..f202db6f8e6 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" + ) + } - abstract TEllipticCurveType getCurveFamily(); + 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) } + + 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 076/189] 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 5cff0129b72..4a9082bf91c 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 1621e9436c4..9e27fedf7fa 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 8252b513860..33c75c556ef 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 077/189] 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 1c2e655314c..09f67f156c2 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 078/189] 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 2bce7fa6843..7d4b36ebe27 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 09f67f156c2..fe397c6247f 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 079/189] 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 | 1208 +++++++++-------- 7 files changed, 986 insertions(+), 1016 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index 2dc17f5e267..0d0caf7f49b 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 7d4b36ebe27..b75c00c3549 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 key_agreement_names(string name) { Crypto::isKeyAgreementAlgorithmName(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) { + 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 + class CipherStringLiteralAlgorithmInstance extends Crypto::KeyOperationAlgorithmInstance instanceof CipherStringLiteral { 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 - { - 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 7fea3515b7d..a9eb70076a0 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 f9fc7a873db..2263f05d56e 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 8743ef3aa19..d56e1680440 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 1ae0cdfd89f..c489320528d 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 fe397c6247f..782c53e1043 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. - */ - abstract ConsumerInputDataFlowNode getInputConsumer(); - - /** - * Gets the consumer of a key. + * 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 getKeyConsumer(); /** - * Gets the output artifact of this cipher operation. + * 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 getNonceConsumer(); + + /** + * 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". - */ - abstract TCipherType getCipherFamily(); - - /** - * Gets the mode of operation of this cipher, e.g., "GCM" or "CBC". + * Gets the key operation algorithm type, e.g., `TSignature(Ed25519())` or `TSymmetricCipher(AES())`. * - * 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. + * 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 KeyOpAlg::Algorithm getAlgorithmType(); + + /** + * Gets the mode of operation, such as "CBC", "GCM", or "ECB". + * + * 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(); - - /** - * 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 string getRawEllipticCurveName(); abstract TEllipticCurveType getEllipticCurveFamily(); abstract string getKeySize(); + + /** + * 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. + */ + 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) - THashOperation(HashOperationInstance e) or - TCipherOperation(CipherOperationInstance e) or - TKeyEncapsulationOperation(KeyEncapsulationOperationInstance e) or - TMACOperation(MACOperationInstance e) or - // Key Creation Operations + // Key Creation Operation union type (e.g., key generation, key load) TKeyCreationOperation(KeyCreationOperationInstance e) or - // Algorithms (e.g., SHA-256, AES) - TCipherAlgorithm(CipherAlgorithmInstanceOrValueConsumer e) or - TEllipticCurveAlgorithm(EllipticCurveAlgorithmInstanceOrValueConsumer 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 + // 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 - // 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 + // All other operations + THashOperation(HashOperationInstance e) or + TMACOperation(MACOperationInstance 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 + // 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() + ScryptAlgorithmNode() { scryptInstance = instance.asAlg() } - abstract class CipherOperationSubtype extends TCipherOperationSubtype { - abstract string toString(); - } + /** + * Gets the iteration count (`N`) argument + */ + GenericSourceNode get_N() { none() } // TODO - class EncryptionSubtype extends CipherOperationSubtype, TEncryptionMode { - override string toString() { result = "Encrypt" } - } + /** + * Gets the block size (`r`) argument + */ + GenericSourceNode get_r() { none() } // TODO - 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 SignatureSubtype extends CipherOperationSubtype, TSignatureMode { - override string toString() { result = "Sign" } - } - - class UnknownCipherOperationSubtype extends CipherOperationSubtype, TUnknownCipherOperationMode { - override string toString() { result = "Unknown" } + /** + * Gets the parallelization factor (`p`) argument + */ + GenericSourceNode get_p() { none() } // TODO } /** - * 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 type defining the subtype type of a key operation. */ - final class CipherOperationNode extends OperationNode, TCipherOperation { - CipherOperationInstance instance; + newtype TKeyOperationSubtype = + TEncryptMode() or + TDecryptMode() or + TWrapMode() or + TUnwrapMode() or + TSignMode() or + TVerifyMode() or + TUnknownKeyOperationMode() - CipherOperationNode() { this = TCipherOperation(instance) } + /** + * 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() + } + } + + /** + * 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. + */ + class KeyOperationNode extends OperationNode, TKeyOperation { + KeyOperationInstance instance; + + KeyOperationNode() { this = TKeyOperation(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() + class KeyOperationAlgorithmNode extends AlgorithmNode, TKeyOperationAlgorithm { + KeyOperationAlgorithmInstanceOrValueConsumer instance; - 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 - 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) - } - - bindingset[curveName] - predicate isEllipticCurveAlgorithmName(string curveName) { - isEllipticCurveAlgorithm(curveName, _, _) + 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) { + ellipticCurveNameToKeySizeAndFamilyMapping(curveName, _, _) + } + + /** + * 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 1958c192ecdc1ed7cbb88038d1eaf72daaf22e2d Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Tue, 15 Apr 2025 23:00:12 -0400 Subject: [PATCH 080/189] Reimplement EC, MAC, key creation logic + consumer --- java/ql/lib/experimental/Quantum/JCA.qll | 1168 ++++++++++------- java/ql/lib/experimental/Quantum/Language.qll | 8 +- .../ql/src/experimental/Quantum/TestCipher.ql | 4 +- .../codeql/cryptography/Model.qll | 125 +- 4 files changed, 834 insertions(+), 471 deletions(-) diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index b75c00c3549..7507c9edbd5 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" - } - - abstract Crypto::KeyOperationSubtype getKeyOperationMode(); - } - - private class UninitializedCipherModeFlowState extends CipherModeFlowState, - TUninitializedCipherModeFlowState - { - override Crypto::KeyOperationSubtype getKeyOperationMode() { - result instanceof Crypto::TUnknownKeyOperationMode - } - } - - private class InitializedCipherModeFlowState extends CipherModeFlowState, - TInitializedCipherModeFlowState - { - CipherInitCall call; - DataFlow::Node node1; - DataFlow::Node node2; - Crypto::KeyOperationSubtype mode; - - 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() - } - - CipherInitCall getInitCall() { result = call } - - DataFlow::Node getFstNode() { result = node1 } + signature class InitCallSig instanceof MethodCall; + signature class UseCallSig instanceof MethodCall { /** - * Returns the node *to* which the state-changing step occurs + * Holds if the use is not a final use, such as an `update()` call before `doFinal()` */ - DataFlow::Node getSndNode() { result = node2 } - - override Crypto::KeyOperationSubtype getKeyOperationMode() { result = mode } + predicate isIntermediate(); } + module MethodCallOption = Option; + /** - * Trace from cipher initialization to a cryptographic operation, - * specifically `Cipher.doFinal()`, `Cipher.wrap()`, or `Cipher.unwrap()`. + * An generic analysis module for analyzing the `getInstance` to `initialize` to `doOperation` pattern in the JCA. * - * TODO: handle `Cipher.update()` + * For example: + * ``` + * kpg = KeyPairGenerator.getInstance(); + * kpg.initialize(...); + * kpg.generate(...); + * ``` */ - private module CipherGetInstanceToCipherOperationConfig implements DataFlow::StateConfigSig { - class FlowState = TCipherModeFlowState; + module GetInstanceInitUseFlowAnalysis< + GetInstanceCallSig GetInstance, InitCallSig Init, UseCallSig Use> + { + newtype TFlowState = + TUninitialized() or + TInitialized(Init call) or + TIntermediateUse(Use call) - predicate isSource(DataFlow::Node src, FlowState state) { - state instanceof UninitializedCipherModeFlowState and - src.asExpr() instanceof CipherGetInstanceCall - } - - 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()) - } - - predicate isAdditionalFlowStep( - DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 - ) { - state1 = state1 and - 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 + abstract class InitFlowState extends TFlowState { + string toString() { + this = TUninitialized() and result = "Uninitialized" or - state.(InitializedCipherModeFlowState).getInitCall() != call - ) + this = TInitialized(_) and result = "Initialized" + // TODO: add intermediate use + } + } + + class UninitializedFlowState extends InitFlowState, TUninitialized { } + + class InitializedFlowState extends InitFlowState, TInitialized { + Init call; + DataFlow::Node node1; + DataFlow::Node node2; + + InitializedFlowState() { + this = TInitialized(call) and + node2.asExpr() = call.(MethodCall).getQualifier() and + DataFlow::localFlowStep(node1, node2) and + node1 != node2 + } + + Init getInitCall() { result = call } + + DataFlow::Node getFstNode() { result = node1 } + + DataFlow::Node getSndNode() { result = node2 } + } + + 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 + } + + Use getUseCall() { result = call } + + DataFlow::Node getFstNode() { result = node1 } + + DataFlow::Node getSndNode() { result = node2 } + } + + module GetInstanceToInitToUseConfig implements DataFlow::StateConfigSig { + class FlowState = InitFlowState; + + 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) + } + + Init getInitFromUse( + Use use, GetInstanceToInitToUseFlow::PathNode src, GetInstanceToInitToUseFlow::PathNode sink + ) { + src.getNode().asExpr() = result.(MethodCall).getQualifier() and + sink.getNode().asExpr() = use.(MethodCall).getQualifier() and + GetInstanceToInitToUseFlow::flowPath(src, sink) + } + + 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() } - override Crypto::KeyOperationSubtype getKeyOperationSubtype() { result = mode } + CipherGetInstanceCall getInstantiationCall() { + result = CipherFlowAnalysisImpl::getInstantiationFromUse(this, _, _) + } + + 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,38 +885,141 @@ 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; + + module KeyGeneratorFlow = KeyGeneratorFlowAnalysisImpl::GetInstanceToInitToUseFlow; + + abstract class KeyGeneratorParameterSpecClassInstanceExpr extends ClassInstanceExpr { + KeyGeneratorInitCall getAnInitCallUse() { + exists(DataFlow::Node sink | + KeyGeneratorParameterSpecToInitializeFlow::flow(DataFlow::exprNode(this), sink) and + result.getAlgorithmParameterSpecArg() = sink.asExpr() + ) + } + } + + class DHGenParameterSpecInstance extends KeyGeneratorParameterSpecClassInstanceExpr { + DHGenParameterSpecInstance() { + this.(ClassInstanceExpr) + .getConstructedType() + .hasQualifiedName("javax.crypto.spec", "DHGenParameterSpec") + } + + Expr getPrimeSizeArg() { result = this.getArgument(0) } + + Expr getExponentSizeArg() { result = this.getArgument(1) } + } + + class DSAParameterSpecInstance extends KeyGeneratorParameterSpecClassInstanceExpr { + DSAParameterSpecInstance() { + this.(ClassInstanceExpr) + .getConstructedType() + .hasQualifiedName("java.security.spec", "DSAParameterSpec") + } + + Expr getPArg() { result = this.getArgument(0) } + + Expr getQArg() { result = this.getArgument(1) } + + Expr getSeedLenArg() { result = this.getArgument(2) } + } + + class ECGenParameterSpecInstance extends KeyGeneratorParameterSpecClassInstanceExpr { + ECGenParameterSpecInstance() { + this.(ClassInstanceExpr) + .getConstructedType() + .hasQualifiedName("java.security.spec", "ECGenParameterSpec") + } + + Expr getCurveNameArg() { result = this.getArgument(0) } + + Expr getRandomNumberGeneratorArg() { result = this.getArgument(1) } + } + + class RSAGenParameterSpecInstance extends KeyGeneratorParameterSpecClassInstanceExpr { + RSAGenParameterSpecInstance() { + this.(ClassInstanceExpr) + .getConstructedType() + .hasQualifiedName("java.security.spec", "RSAGenParameterSpec") + } + + Expr getKeySizeArg() { result = this.getArgument(0) } + } + + private module KeyGeneratorParameterSpecToInitializeConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + src.asExpr() instanceof KeyGeneratorParameterSpecClassInstanceExpr + } + + predicate isSink(DataFlow::Node sink) { + exists(KeyGeneratorInitCall c | + c.getKeyType() = Crypto::TAsymmetricKeyType() and + c.getArgument(0) = sink.asExpr() + ) + } + } + + module KeyGeneratorParameterSpecToInitializeFlow = + DataFlow::Global; + + class ECGenParameterSpecClassInstanceExpr extends KeyGeneratorParameterSpecClassInstanceExpr { + ECGenParameterSpecClassInstanceExpr() { + this.(ClassInstanceExpr) + .getConstructedType() + .hasQualifiedName("java.security.spec", "ECGenParameterSpec") + } + + Expr getAlgorithmArg() { result = this.getArgument(0) } + } + + class KeyGenerationAlgorithmValueConsumer extends CipherAlgorithmValueConsumer, + KeyAgreementAlgorithmValueConsumer, EllipticCurveAlgorithmValueConsumer instanceof Expr + { + KeyGeneratorGetInstanceCall instantiationCall; + + 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 + ) + } override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { - result.(CipherStringLiteralAlgorithmInstance).getConsumer() = this + result.(CipherStringLiteralAlgorithmInstance).getConsumer() = this or + result.(KeyAgreementStringLiteralAlgorithmInstance).getConsumer() = this or + result.(EllipticCurveStringLiteralInstance).getConsumer() = this } + + KeyGeneratorGetInstanceCall getInstantiationCall() { result = instantiationCall } } - // 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; - + // TODO: Link getAlgorithm from KeyPairGenerator to algorithm instances or AVCs? High priority. class KeyGeneratorGetInstanceCall extends MethodCall { KeyGeneratorGetInstanceCall() { this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "getInstance") @@ -834,10 +1028,36 @@ module JCAModel { } Expr getAlgorithmArg() { result = super.getArgument(0) } + } - predicate flowsToKeyGenerateCallQualifier(KeyGeneratorGenerateCall sink) { - KeyGeneratorGetInstanceToGenerateFlow::flow(DataFlow::exprNode(this), - DataFlow::exprNode(sink.(MethodCall).getQualifier())) + class KeyGeneratorInitCall extends MethodCall { + Crypto::TKeyArtifactType keyType; + + 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() + } + + Crypto::TKeyArtifactType getKeyType() { result = keyType } + + Expr getAlgorithmParameterSpecArg() { + result = this.getArgument(0) and + this.getMethod().getParameterType(0).hasName("AlgorithmParameterSpec") + } + + Expr getKeySizeArg() { + result = this.getArgument(0) and + this.getMethod().getParameterType(0) instanceof IntegralType + } + + Expr getRandomnessSourceArg() { + exists(int index | + this.getMethod().getParameterType(index).hasName("SecureRandom") and + result = this.getArgument(index) + ) } } @@ -849,29 +1069,344 @@ module JCAModel { this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "generateKey") and type instanceof Crypto::TSymmetricKeyType or - this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "generateKeyPair") and + this.getCallee() + .hasQualifiedName("java.security", "KeyPairGenerator", ["generateKeyPair", "genKeyPair"]) and type instanceof Crypto::TAsymmetricKeyType } + predicate isIntermediate() { none() } + override Crypto::ArtifactOutputDataFlowNode getOutputKeyArtifact() { result.asExpr() = this } override Crypto::KeyArtifactType getOutputKeyType() { result = type } override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { - exists(KeyGeneratorGetInstanceCall getInstance | - getInstance.flowsToKeyGenerateCallQualifier(this) and result = getInstance.getAlgorithmArg() - ) + KeyGeneratorFlowAnalysisImpl::getInstantiationFromUse(this, _, _) = + result.(KeyGenerationAlgorithmValueConsumer).getInstantiationCall() } Crypto::AlgorithmInstance getAKnownAlgorithm() { result = this.getAnAlgorithmValueConsumer().getAKnownAlgorithmSource() } - override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { none() } + override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { + KeyGeneratorFlowAnalysisImpl::getInitFromUse(this, _, _).getKeySizeArg() = result.asExpr() + } override string getKeySizeFixed() { none() } } + /* + * 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) } + } + + class PBEKeySpecInstantiation extends KeySpecInstantiation { + PBEKeySpecInstantiation() { this.getConstructedType().hasName("PBEKeySpec") } + + Expr getSaltArg() { result = this.getArgument(1) } + + Expr getIterationCountArg() { result = this.getArgument(2) } + + Expr getKeyLengthArg() { result = this.getArgument(3) } + } + + module KeySpecInstantiationToGenerateSecretFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + exists(KeySpecInstantiation 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 KeySpecInstantiationToGenerateSecretFlow = + DataFlow::Global; + + module KDFAlgorithmStringToGetInstanceFlow = + DataFlow::Global; + + class DUMMY_UNUSED_METHODCALL extends MethodCall { + DUMMY_UNUSED_METHODCALL() { none() } + } + + module SecretKeyFactoryFlowAnalysisImpl = + GetInstanceInitUseFlowAnalysis; + + module SecretKeyFactoryFlow = SecretKeyFactoryFlowAnalysisImpl::GetInstanceToInitToUseFlow; + + class SecretKeyFactoryGetInstanceCall extends MethodCall { + SecretKeyFactoryGetInstanceCall() { + this.getCallee().hasQualifiedName("javax.crypto", "SecretKeyFactory", "getInstance") + } + + Expr getAlgorithmArg() { result = this.getArgument(0) } + } + + 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 + { + 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_type_known(this.getRawHashAlgorithmName(), _) + } + + override int getDigestLength() { + exists(hash_name_to_type_known(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 KeyDerivationOperationCall extends Crypto::KeyDerivationOperationInstance instanceof SecretKeyFactoryGenerateSecretCall + { + KeyDerivationOperationCall() { not super.isIntermediate() } + + KeySpecInstantiation getKeySpecInstantiation() { + KeySpecInstantiationToGenerateSecretFlow::flow(DataFlow::exprNode(result), + DataFlow::exprNode(super.getKeySpecArg())) + } + + override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { + result.(SecretKeyFactoryKDFAlgorithmValueConsumer).getInstantiation() = + SecretKeyFactoryFlowAnalysisImpl::getInstantiationFromUse(this, _, _) + } + + override Crypto::ConsumerInputDataFlowNode getSaltConsumer() { + result.asExpr() = this.getKeySpecInstantiation().(PBEKeySpecInstantiation).getSaltArg() + } + + override Crypto::ConsumerInputDataFlowNode getInputConsumer() { + result.asExpr() = this.getKeySpecInstantiation().getPasswordArg() + } + + override Crypto::ConsumerInputDataFlowNode getIterationCountConsumer() { + result.asExpr() = + this.getKeySpecInstantiation().(PBEKeySpecInstantiation).getIterationCountArg() + } + + override Crypto::ArtifactOutputDataFlowNode getOutputKeyArtifact() { result.asExpr() = this } + + override Crypto::ConsumerInputDataFlowNode getOutputKeySizeConsumer() { + result.asExpr() = this.getKeySpecInstantiation().(PBEKeySpecInstantiation).getKeyLengthArg() + } + + override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { + result.asExpr() = this.getKeySpecInstantiation().(PBEKeySpecInstantiation).getKeyLengthArg() + } + + override string getKeySizeFixed() { none() } + + override string getOutputKeySizeFixed() { none() } + + 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 string literal to a key agreement algorithm consumer. + */ + private module KeyAgreementAlgorithmStringToConsumerConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof KeyAgreementStringLiteral } + + predicate isSink(DataFlow::Node sink) { + sink = any(KeyAgreementAlgorithmValueConsumer consumer).getInputNode() + } + } + + module KeyAgreementAlgorithmStringToConsumerFlow = + TaintTracking::Global; + + class KeyAgreementInitCall extends MethodCall { + KeyAgreementInitCall() { + this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "init") + } + + Expr getServerKeyArg() { result = this.getArgument(0) } + } + + class KeyAgreementGetInstanceCall extends MethodCall { + KeyAgreementGetInstanceCall() { + this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "getInstance") + } + + Expr getAlgorithmArg() { result = super.getArgument(0) } + } + + private class KeyAgreementGetInstanceAlgorithmArgValueConsumer extends KeyAgreementAlgorithmValueConsumer + { + KeyAgreementGetInstanceCall 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 + { + KeyAgreementAlgorithmValueConsumer consumer; + + KeyAgreementStringLiteralAlgorithmInstance() { + KeyAgreementAlgorithmStringToConsumerFlow::flow(DataFlow::exprNode(this), + consumer.getInputNode()) + } + + 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() + } + + 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 } + } + + /* + * MACs + */ + module MACKnownAlgorithmToConsumerConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { mac_names(src.asExpr().(StringLiteral).getValue()) } @@ -1001,317 +1536,50 @@ module JCAModel { } } - 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 Crypto::ArtifactOutputDataFlowNode 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() } - } - - 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. + /* + * Elliptic Curves (EC) */ - private module KeyAgreementAlgorithmStringToFetchConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node src) { src.asExpr() instanceof KeyAgreementStringLiteral } + + module EllipticCurveStringToConsumerConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof EllipticCurveStringLiteral } predicate isSink(DataFlow::Node sink) { - exists(Crypto::AlgorithmValueConsumer consumer | sink = consumer.getInputNode()) + exists(EllipticCurveAlgorithmValueConsumer consumer | sink = consumer.getInputNode()) } } - module KeyAgreementAlgorithmStringToFetchFlow = - TaintTracking::Global; + module EllipticCurveStringToConsumerFlow = DataFlow::Global; - class KeyAgreementInitCall extends MethodCall { - KeyAgreementInitCall() { - this.getCallee().hasQualifiedName("javax.crypto", "KeyAgreement", "init") - } - - Expr getServerKeyArg() { result = this.getArgument(0) } + class EllipticCurveStringLiteral extends StringLiteral { + EllipticCurveStringLiteral() { elliptic_curve_names(this.getValue()) } } - 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 + class EllipticCurveStringLiteralInstance extends Crypto::EllipticCurveInstance instanceof EllipticCurveStringLiteral { - Crypto::AlgorithmValueConsumer consumer; + EllipticCurveAlgorithmValueConsumer consumer; - KeyAgreementStringLiteralAlgorithmInstance() { - KeyAgreementAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) + EllipticCurveStringLiteralInstance() { + EllipticCurveStringToConsumerFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) } - Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } + override string getRawEllipticCurveName() { result = super.getValue() } - 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") + override Crypto::TEllipticCurveType getEllipticCurveType() { + if Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getRawEllipticCurveName(), _, _) + then + Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getRawEllipticCurveName(), _, result) + else result = Crypto::OtherEllipticCurveType() } - 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) + override string getKeySize() { + exists(int keySize | + Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getRawEllipticCurveName(), keySize, + _) + | + result = keySize.toString() + ) } - 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? - } + EllipticCurveAlgorithmValueConsumer getConsumer() { result = consumer } } } diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 8027ef33df7..1e12f6f1ac8 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 d56e1680440..6779a64f608 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 782c53e1043..510f334bc62 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 28ccc833464e64d3e5dbdc5fd34c7fb59bde3bbb Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 28 Apr 2025 11:33:37 -0400 Subject: [PATCH 081/189] 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 510f334bc62..1ea862b470d 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 082/189] 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 00000000000..de283f89775 --- /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 00000000000..d8adccace55 --- /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 2263f05d56e..00000000000 --- 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 083/189] 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 00000000000..1d451978400 --- /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 1fd7643ab3ad1f2b15817ca0839e67ae69129cec Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 28 Apr 2025 14:54:38 -0400 Subject: [PATCH 084/189] 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 00000000000..1e5a7c5bced --- /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 00000000000..0900401b80d --- /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 00000000000..0112e9d96df --- /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 00000000000..632872725e7 --- /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 00000000000..b3556393173 --- /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 00000000000..ce0f4d37d4d --- /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 00000000000..584ffef0bbf --- /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 00000000000..8c77b2aa984 --- /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 00000000000..cf9a4e96f4d --- /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 00000000000..0076c478dec --- /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 00000000000..61a27c75dac --- /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 085/189] 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 1d451978400..00000000000 --- 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 086/189] 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 1ea862b470d..704be38362b 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 087/189] 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 00000000000..439295f74e3 --- /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 00000000000..0c91e66d52b --- /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 088/189] 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 0112e9d96df..048bcd8182c 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 089/189] 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 00000000000..962a6b72015 --- /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 00000000000..4096fe16d29 --- /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 00000000000..e69de29bb2d diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 704be38362b..bfc527e108d 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 f6fae7ad60ad011e60ba072d9b7e68ac42fbcd42 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Wed, 30 Apr 2025 13:33:31 +0200 Subject: [PATCH 090/189] 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 003ae3f442f..de70e7a1d0a 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 9e7905c9847..2bbcd51f582 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 091/189] 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 9f3eeb6e0dc..91b18a1779d 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 de70e7a1d0a..4ca9f088bf4 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 092/189] Added support for `shelljs.cmd` and `async-shelljs.asyncExec` --- .../semmle/javascript/frameworks/ShellJS.qll | 21 ++++++++++++++----- .../frameworks/Shelljs/ShellJS.expected | 3 +++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll index 91b18a1779d..ae0ba17941c 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" } + ShellJSExec() { name = ["exec", "cmd", "asyncExec"] } - override DataFlow::Node getACommandArgument() { result = this.getArgument(0) } + 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 4ca9f088bf4..5c3c922a84f 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 7f24a2557dab63a2e1a241ef83c5e11a0622a28b Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Wed, 30 Apr 2025 16:28:31 +0200 Subject: [PATCH 093/189] 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 7507c9edbd5..6589cbbc9d5 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 1e12f6f1ac8..6f7dc88157b 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 00000000000..9c06884328b --- /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 00000000000..985527318ff --- /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 6779a64f608..503d6003922 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 96f99193cba..76ef6951a7e 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 fa4c2cb1d02..6bd0d19712c 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 510f334bc62..b3c104cbc5e 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 c80588cda15b873c2f5c4196726104feb7c72065 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Wed, 30 Apr 2025 11:41:28 -0400 Subject: [PATCH 094/189] 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 e69de29bb2d..21949f1c8c6 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 499d224c2b1c85d0fcf083625c23c2495d44c244 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Thu, 1 May 2025 10:11:10 +0200 Subject: [PATCH 095/189] 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 effb389aecc..8d177c4e856 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 7cd8a602f24..2b91ef42107 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 0bb74f5e412..734b13027cd 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 5ff016dcf3e..8f45f5773b4 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 4a1103eaa48..00d31391a4d 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 6c2a7c2ba85..85d42df2ca3 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 b5e19855cfa..df5c5d04a7e 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 40d176a7703fd01407179668f3921e1702e48da9 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Wed, 30 Apr 2025 13:45:50 +0200 Subject: [PATCH 096/189] 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 00000000000..8d2c8db645d --- /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 097/189] 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 00000000000..90a5f5a2a30 --- /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 098/189] 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 02171539521..a92b7713491 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 099/189] 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 5dca4cf1df2..dbb775f99b5 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 9dd6ab4b4a9..84c4600fbc0 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 d9f7267d425..b5e52d7c6c7 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 7c732184577..9fc6f6b1bc4 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 a92b7713491..8fb6994a597 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 53b2e9708cddc30c8f71134b772cce533493e3b3 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Wed, 30 Apr 2025 13:21:56 +0200 Subject: [PATCH 100/189] 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 9cdc89dd52f..6536a4b6fd9 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 0ec1769f1d1..b983a3217a3 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 00000000000..2c7da705dd2 --- /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 00000000000..91989b5262b --- /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 101/189] 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 856a61276a0..9f143a9713a 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 1f51af3efda..473dfe46527 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 102/189] 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 146d8514488..f45877f26d0 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 4deec0653da..ca256c4f856 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 17358a1c100..fe45fc4b6dc 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 fa790e6cd7f..165a770e1cb 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 1f343b197c0..15ee83de7ad 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 9429dada005..146d8514488 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 9429dada005..146d8514488 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 32a3b111024..03c81ea6fb7 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 17358a1c100..fe45fc4b6dc 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 e9a65e0c7be..0cf90cf71e0 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 5912f7d69ba..c845417a624 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 5912f7d69ba..c845417a624 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 4b0e6ed828b..0ee55e79623 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 17358a1c100..fe45fc4b6dc 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 103/189] 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 7fa38a327f1..9e6c4ff8b81 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 104/189] 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 0f25c694f61..31f5f16bbfb 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 9f143a9713a..0e19e84b666 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 07f186343ce..dd904cd78c3 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 105/189] 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 5bc45afecf1..d1878ce3dae 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 198f8ab9cd8..9ff1be3b3c5 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 648ffd0a307..3ce3e0ecae0 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 00000000000..03a2899da09 --- /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 106/189] 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 c4125774315..3d25ede3187 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 107/189] 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 75bd47e76dc..c2a1dcc747f 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 108/189] 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 368e5738c19..a3ca1722b57 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 fdbfb5d4613..ab9aa6ef0fd 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 109/189] 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 ce494ff5a60..dc75d109a33 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 5fa7b20e01b..76e48043d0d 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 ed21d9772fc..793ed90a482 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 110/189] 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 0bc1b6b6ee0..875b0189d61 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 5681ae99aa8..09874ecef10 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 111/189] 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 00000000000..e69de29bb2d 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 00000000000..7605aa9e719 --- /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 00000000000..84152bd7072 --- /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 c6d95ceeb011f3ba0b0cd6ec9ee5e3e0cc14f212 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Fri, 2 May 2025 13:21:10 +0200 Subject: [PATCH 112/189] 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 3d98e74f0fb..b0e4a20f2b8 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 38bbaad118b..00000000000 --- 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 00000000000..824b37180a1 --- /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 ebc7ea1be78..00000000000 --- 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 00000000000..0a2d9e797fc --- /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 44b40a4d34a..00000000000 --- 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 1f7df71776b..0c38f41c069 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 1d108015fa0..60674ed54ed 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 @@ If none of these flags are specified, all models are generated except for the ty --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 @@ Requirements: `codeql` should appear on your path. @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 @@ Requirements: `codeql` should appear on your path. 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 @@ extensions: 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 008b82501ff..00000000000 --- 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 871e93d9fe2309d757bc6d19484fb491c9b31b64 Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Fri, 2 May 2025 13:39:46 +0200 Subject: [PATCH 113/189] 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 ae0ba17941c..fc0e366df4b 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 114/189] 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 b95cec8d7d9..3bc1c511fa1 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 04ed47ffe92..11c2d5d450d 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 32c1865ff30..22fb1d0111b 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 53d630d9f19..a8d352e0ead 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 00000000000..162e5d08589 --- /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 00000000000..892f3400380 --- /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 00000000000..89a010f5752 --- /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 2925620f24f..30801ade8d5 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 c59c831a1ee..0ebc95d2084 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 ce6eca080af..83a94b96505 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 1da3dcbc013..474420586ca 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 00000000000..d21ba383f14 --- /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 4dd3d5ca8a8..3d88fb615e8 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 9baeaf41241..ac122e39f9f 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 e57454212df..8254ef3cc8a 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 6bd2b4b3fb1..24f0a6cff19 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 78750ae2baa..4e11bc7a33d 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 115/189] 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 3bc1c511fa1..285f48cc940 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 6357a58beca..7e1f1f0bfe8 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 0f7d5d0c915..30cca659a8c 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 ff3db137b3b..525f1fda6c1 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 3404bb7d95a..cd471449827 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 02eb24632f4..404f7214bea 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 11c2d5d450d..fcec2a9fbe2 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 22fb1d0111b..2d8114e910c 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 a8d352e0ead..f840aa9df51 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 00000000000..7f48b7a80b5 --- /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 00000000000..de997a791b4 --- /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 00000000000..4fd16c6693f --- /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 00000000000..8d1df2b4769 --- /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 00000000000..b9190352b5d --- /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 00000000000..9eeb9798fc6 --- /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 30801ade8d5..8ab3348f470 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 0ebc95d2084..88ba766fc86 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 83a94b96505..7eecd52e626 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 474420586ca..a9225a1b0ce 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 00000000000..602b0db2375 --- /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 00000000000..655d4b1fc19 --- /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 3d88fb615e8..4295ec72e82 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 9b5429f8ba9..3cc64e753b3 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 00000000000..fa57faafb19 --- /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 00000000000..d434781d152 --- /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 00000000000..43e48141790 --- /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 00000000000..3c08a5c76d4 --- /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 00000000000..d9ac932879c --- /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 00000000000..7fba23db8bd --- /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 00000000000..dea3771c7c5 --- /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 00000000000..ce2127e600d --- /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 4e11bc7a33d..917f5a3a30c 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 116/189] 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 285f48cc940..b204c06ff0b 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 fcec2a9fbe2..f693ce9e9fc 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 2d8114e910c..761b2efeb7c 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 f840aa9df51..2551a7ece9b 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 00000000000..bf523a0a785 --- /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 00000000000..51c78ebf215 --- /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 00000000000..ff157961c40 --- /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 8ab3348f470..49ffc37a473 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 88ba766fc86..a2779b148e9 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 7eecd52e626..09f52604bb9 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 a9225a1b0ce..8ffefd96281 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 00000000000..b61533168b7 --- /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 4295ec72e82..987ab0bc091 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 27e4e6f0868..1b64e9f4a22 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 00000000000..ab422992106 --- /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 917f5a3a30c..fc923d0c6a3 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 117/189] 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 00000000000..ee11b5a8654 --- /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 00000000000..987ab0bc091 --- /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 00000000000..4dd3d5ca8a8 --- /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 00000000000..5817523dc52 --- /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 00000000000..4dd3d5ca8a8 --- /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 00000000000..987ab0bc091 --- /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 00000000000..2beb5c2591d --- /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 118/189] 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 9567c4ea517..857bfe31380 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 7c3c1419474..e56e7e3ca36 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 f051cf49e08..3de58350f20 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 119/189] 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 82b6665615b..158f55acad5 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 caeeb7552a7..a79bfc7bd0a 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 0ff3e721e23..bc447c524e8 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 900580914e2..298d7e49438 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 12ef6847b82..34ccb8d2381 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 77416d93699..9ef0c12b35f 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 e80debcb27d..636e0d1ea09 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 4268ef3f840..57e18e373b8 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 3bd57ae9862..b1e26574de1 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 6d7c69fde13..abc696eb51e 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 e8707b675dc..48a13c5eec3 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 d5d978b9f52..2b87a4996b1 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 1705b88e3d7..0b79e26e95a 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 6c2a7c2ba85..a03453383b0 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 2f3d9927710..2c04ca30410 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 a5c3ff56651..f783e72e619 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 120/189] 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 b2950622440..f750fed0455 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 a03453383b0..123e8801649 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 e56e7e3ca36..176556b658c 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 121/189] 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 8b8d7f5c593..3f1613573df 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 158f55acad5..fdaed238b03 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 a79bfc7bd0a..91fe945df62 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 32b9c2367a6..8628b3e30f3 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 bc447c524e8..6983e823256 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 382565f3b86..dec3580d68c 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 298d7e49438..943e6ed020d 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 34ccb8d2381..f3cf52dab76 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,6 +3751,18 @@ module MakeCfgNodes Input> { cfgNode ) or + pred = "getTailExpr" and + parent = + any(Nodes::MacroBlockExprCfgNode cfgNode, MacroBlockExpr astNode | + astNode = cfgNode.getMacroBlockExpr() and + child = getDesugared(astNode.getTailExpr()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getTailExpr().getAstNode() + | + cfgNode + ) + or pred = "getMacroCall" and parent = any(Nodes::MacroExprCfgNode cfgNode, MacroExpr astNode | @@ -3775,18 +3787,6 @@ 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/dataflow/internal/DataFlowImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll index f750fed0455..8aa6c921eef 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 21c254b5d67..4456cb4b44a 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 9ef0c12b35f..8fcd2119a0a 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 6f588955125..0bb4936209a 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 8ec38e3c526..60030dd6f27 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 00000000000..3dd6411e20e --- /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 636e0d1ea09..00000000000 --- 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 57e18e373b8..6bea3762de1 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll @@ -2368,6 +2368,28 @@ private module Impl { ) } + 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 + 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.getTailExpr() and partialPredicateCall = "TailExpr()" + or + result = e.getStatement(index - nTailExpr) and + partialPredicateCall = "Statement(" + (index - nTailExpr).toString() + ")" + ) + ) + } + private Element getImmediateChildOfMacroExpr(MacroExpr e, int index, string partialPredicateCall) { exists(int b, int bExpr, int n, int nMacroCall | b = 0 and @@ -2400,26 +2422,6 @@ 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 ) { @@ -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 b1e26574de1..0869ec4de5a 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 abc696eb51e..04588e2861e 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 9be635b767e..e6ff3af4715 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 48a13c5eec3..58bc96172f5 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 56cb7ed62e1..13778503766 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 133c01c05cd..9452518fe36 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 00000000000..4bf0740b930 --- /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 00000000000..c003ca232f1 --- /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 0d0743de096..a5d58c0e32d 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 00000000000..ed7fbf364cf --- /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 f03854ddb14..4fdb10bc351 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 1b60df41f79..f4bb40db46b 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 e74a5e4e857..00000000000 --- 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 189e280605c..00000000000 --- 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 d1390595304..00000000000 --- 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 0b79e26e95a..b51f42537d1 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 123e8801649..0cd59e28115 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 2c04ca30410..f2a80077bfc 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 f783e72e619..6eb463746ec 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 dabe1be807a..17fb872bb8e 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 122/189] 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 00000000000..55472b08ff8 --- /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 123/189] 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 00000000000..58bc96172f5 --- /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 00000000000..e8707b675dc --- /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 00000000000..61d3e02cd8a --- /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 00000000000..e8707b675dc --- /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 00000000000..58bc96172f5 --- /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 00000000000..5e11ce73174 --- /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 124/189] 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 ab9aa6ef0fd..7638bea15fd 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 00000000000..a1915f837fd --- /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 6aac95fcace..bb7106cf6e9 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 bf77c7b88ea..2008be60660 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 ff97a37b5d1..f09f49b30bb 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 7605aa9e719..1609d4b5d22 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 84152bd7072..7ec3d8a3eef 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 125/189] 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 7638bea15fd..40a3c4a4e26 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 a1915f837fd..6564e912743 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 bb7106cf6e9..7793fc5808c 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 2008be60660..782f0addf64 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 1609d4b5d22..5829b5b360f 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 7ec3d8a3eef..1e8da17c2e4 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 126/189] 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 6564e912743..26486686cb2 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 7793fc5808c..42ac0521db3 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 782f0addf64..56cc43babd0 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 5829b5b360f..cbb81bdcb02 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 1e8da17c2e4..f82a9501fef 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 127/189] 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 40a3c4a4e26..72cc4ffdf57 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 128/189] 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 0e619031ed5..b3683f02d92 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 129/189] 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 aa49c30ce5a..15a45c6f4b5 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 1b0a498afe5..11e29d475e4 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 388c98d07b6..398551a84a7 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 130/189] 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 8b137891791..94c62ec81ae 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 131/189] Misc. cleanup --- cpp/ql/lib/experimental/Quantum/Language.qll | 112 ++++---- .../experimental/Quantum/OpenSSL/CtxFlow.qll | 8 +- .../experimental/Quantum/OpenSSL/OpenSSL.qll | 271 +----------------- 3 files changed, 65 insertions(+), 326 deletions(-) diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index 0d0caf7f49b..7e1857cc68a 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,25 +16,59 @@ 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; -/** - * 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 { +module ArtifactFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { - source = any(Crypto::GenericDataSourceInstance i).getOutputNode() + 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 + */ +abstract class AdditionalFlowInputStep extends DataFlow::Node { + abstract DataFlow::Node getOutput(); + + final DataFlow::Node getInput() { result = this } +} + +/** + * Generic data source to node input configuration + */ +module GenericDataSourceFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + 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 c07902022d8..88e4a1c378b 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 1f9fb9a54ba..6b28c4ee8e4 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 132/189] 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 7e1857cc68a..2d076a1323c 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 133/189] 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 a7938b1d1ce..8fcc304e9ef 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 134/189] 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 00000000000..25cdea6accf --- /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 00000000000..1e17c64f34c --- /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 00000000000..03f2643d46d --- /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 0d328e287f6..80bd6b422da 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 00000000000..6a206773bfb --- /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 00000000000..2a3f136f117 --- /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 00000000000..219289c7da0 --- /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 00000000000..19777bc06d1 --- /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 00000000000..cebe7a86a12 --- /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 00000000000..dddcf14c713 --- /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 00000000000..46021269d71 --- /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 00000000000..009b22cf1b8 --- /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 00000000000..584fd18a64c --- /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 00000000000..56288e6acb7 --- /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 00000000000..851d7a4b7e9 --- /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 00000000000..76a60b064e5 --- /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 135/189] 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 b436f3b412a..00000000000 --- 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 136/189] 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 2a3f136f117..7a77a4c3e13 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 46021269d71..0638595afb8 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 e2f5bc0e838..00000000000 --- 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 d269658c8aa..00000000000 --- 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 82bf331546f..00000000000 --- 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 16a9234d68c..00000000000 --- 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 7db90c4eccc..00000000000 --- 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 56288e6acb7..ae05798ea1f 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 76a60b064e5..819e964878c 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 6589cbbc9d5..ceca0e45464 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 8fcc304e9ef..69a4fd75acf 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 137/189] 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 03f2643d46d..0dd948c9fae 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 00000000000..4b412da9b55 --- /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 80bd6b422da..a0f0107d0ac 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 +predicate resolveAlgorithmFromExpr(Expr e, string normalizedName, string algType) { + resolveAlgorithmFromCall(e, normalizedName, algType) + or + resolveAlgorithmFromLiteral(e, normalizedName, algType) +} + class KnownOpenSSLAlgorithmConstant extends Expr { - string normalizedName; - string algType; + KnownOpenSSLAlgorithmConstant() { resolveAlgorithmFromExpr(this, _, _) } - KnownOpenSSLAlgorithmConstant() { - resolveAlgorithmFromCall(this, normalizedName, algType) - or - resolveAlgorithmFromLiteral(this, normalizedName, algType) - } + string getNormalizedName() { resolveAlgorithmFromExpr(this, result, _) } - string getNormalizedName() { result = normalizedName } - - 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 00000000000..753bb356e7a --- /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 00000000000..cd0dac94001 --- /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 00000000000..b7771e240a4 --- /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 138/189] 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 09b08bf4d27..914a0be40c9 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 9290f65d5b2..daca5d73f55 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 9d05f9bf06d..dbb615bf06c 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 9d05f9bf06d..dbb615bf06c 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 9d05f9bf06d..dbb615bf06c 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 9290f65d5b2..daca5d73f55 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 9d05f9bf06d..dbb615bf06c 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 9d05f9bf06d..dbb615bf06c 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 9d05f9bf06d..dbb615bf06c 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 9d05f9bf06d..dbb615bf06c 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 96b0b028bdd..0ce0c6870b7 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 9290f65d5b2..daca5d73f55 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 c5b4a958655..ebbb0432489 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 20a0480c8e2..ba17ecb5638 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 9290f65d5b2..daca5d73f55 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 cce2f114af6..ce5d6db635a 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 7404a7573b2..595b1a2bac0 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 96b0b028bdd..0ce0c6870b7 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 9290f65d5b2..daca5d73f55 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 ab08ee323e2..aff430e13cc 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 c5b4a958655..ebbb0432489 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 96b0b028bdd..0ce0c6870b7 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 9d05f9bf06d..dbb615bf06c 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 9d05f9bf06d..dbb615bf06c 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 fb93d69d6b4..d43edf41c56 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 ab08ee323e2..aff430e13cc 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 9290f65d5b2..daca5d73f55 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 9290f65d5b2..daca5d73f55 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 ab08ee323e2..aff430e13cc 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 96b0b028bdd..0ce0c6870b7 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 9d05f9bf06d..dbb615bf06c 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 9d05f9bf06d..dbb615bf06c 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 9d05f9bf06d..dbb615bf06c 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 9290f65d5b2..daca5d73f55 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 9290f65d5b2..daca5d73f55 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 750b4e67189..62b643d45cb 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 9290f65d5b2..daca5d73f55 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 9d05f9bf06d..dbb615bf06c 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 a5d7077ef37..1fcc7e1cf48 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 7404a7573b2..595b1a2bac0 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 9290f65d5b2..daca5d73f55 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 9290f65d5b2..daca5d73f55 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 9290f65d5b2..daca5d73f55 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 96b0b028bdd..0ce0c6870b7 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 5e2b8b8284e..0af89500401 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 96b0b028bdd..0ce0c6870b7 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 96b0b028bdd..0ce0c6870b7 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 939c70c792e..d0f03f3af55 100644 --- a/csharp/ql/test/resources/stubs/System.Net.cs +++ b/csharp/ql/test/resources/stubs/System.Net.cs @@ -49,6 +49,22 @@ namespace System.Net.Http { 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 d1942c07dc1..56f51208e54 100644 --- a/csharp/ql/test/resources/stubs/System.Web.cs +++ b/csharp/ql/test/resources/stubs/System.Web.cs @@ -19,6 +19,15 @@ namespace System.Web 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 @@ namespace System.Web.UI { public System.Security.Principal.IPrincipal User { get; } public System.Web.HttpRequest Request { get; } + public HttpResponse Response => null; } interface IPostBackDataHandler @@ -153,6 +192,7 @@ namespace System.Web 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 @@ namespace System.Web 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 @@ namespace System.Web 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 @@ namespace System.Web.Mvc 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 @@ namespace System.Web.Script.Serialization 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 7231f53b6ee98780cd6626ab5a3e6855e8767d93 Mon Sep 17 00:00:00 2001 From: Sid Gawri Date: Mon, 5 May 2025 21:59:37 -0400 Subject: [PATCH 139/189] 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 d0f03f3af55..49ad43b1d39 100644 --- a/csharp/ql/test/resources/stubs/System.Net.cs +++ b/csharp/ql/test/resources/stubs/System.Net.cs @@ -50,21 +50,6 @@ namespace System.Net.Http 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 140/189] 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 737af893993..cfdc82cbd2b 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 0fbc8831fb3..3341c6aa4dd 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 141/189] 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 79ac9192e02..2822da61ff1 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 142/189] (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 f687f54c977..c4544390753 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 143/189] 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 ba7eeae0008..7a5fd2d000f 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 9b4565f1e1a..d351460c8a7 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 00000000000..2fd067a0583 --- /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 144/189] 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 d351460c8a7..1f1dbdec49d 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 2fd067a0583..0f27d57639b 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 145/189] 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 1f1dbdec49d..5b3ef166b15 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 0f27d57639b..395010e7ef7 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 146/189] 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 395010e7ef7..e3ab61274d2 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 147/189] 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 9be24ca6efa..00000000000 --- 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 9abf3e7fa7e..00000000000 --- 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 802ad23cf9d..00000000000 --- 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 67f21ad0b24..2da0dd61f88 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 148/189] 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 149/189] 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 (64%) diff --git a/cpp/ql/lib/experimental/Quantum/Language.qll b/cpp/ql/lib/experimental/Quantum/Language.qll index 2d076a1323c..c3e2e3ad55f 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 25cdea6accf..72c3ffcfad4 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 1e17c64f34c..2566c1188a6 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 0dd948c9fae..7483572848e 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 4b412da9b55..985e36dbdd7 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 a0f0107d0ac..77caf0bb378 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 6a206773bfb..dc49c139cf0 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 219289c7da0..4fb4d081869 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 19777bc06d1..8fa65860b60 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 cebe7a86a12..ffc9a7c3991 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 753bb356e7a..b041b986754 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 dddcf14c713..3f6e2bd4dc8 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 009b22cf1b8..3f7ce20d6b3 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 6b28c4ee8e4..f53812093c4 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 584fd18a64c..fdf60ef757e 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 ae05798ea1f..45c7d41b029 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 b7771e240a4..45776b6668b 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 851d7a4b7e9..4798f5650a9 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 eceff874874..e599ed82169 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 6bb19968c82..335360caeb2 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 d9658105aeb..f741e3c9f94 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 6f7dc88157b..572d5716e02 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 52fa4620b46..036218757a8 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 de283f89775..88598e61589 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 9c06884328b..b2c6f919d5f 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 439295f74e3..701f3064e92 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 0c91e66d52b..4ce404f01b0 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 020ac1b8925..b4e9de9ac94 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" + ] +} - bindingset[algorithmString] +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 @@ -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 a9eb70076a0..fc2387fda37 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 985527318ff..096cfa82216 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 503d6003922..2b1d6ebcf06 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 c489320528d..9408aac7e3b 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 76ef6951a7e..b319c95a62b 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 1e5a7c5bced..7ae2a0f0888 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 962a6b72015..c7242ed11c5 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 0900401b80d..a14a0dfbaba 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 4096fe16d29..f126c3d9ae1 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 048bcd8182c..c3f69d91cb7 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 632872725e7..ed24b62364d 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 b3556393173..23fc6235e80 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 ce0f4d37d4d..8af3c09dd10 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 584ffef0bbf..e0970353a98 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 8c77b2aa984..240a4ea3fc5 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 cf9a4e96f4d..9afbd7d7f2f 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 21949f1c8c6..d8467305df9 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 0076c478dec..d02524a7df3 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 61a27c75dac..7559579d863 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 063cda564b6..bc79d5d4ce6 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 64% rename from shared/cryptography/qlpack.yml rename to shared/experimental/qlpack.yml index 768c64a0704..2976c56ba49 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 150/189] 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 c3e2e3ad55f..176db9736ad 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 3f48f156a43..98a35d2a9e9 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 572d5716e02..eaf63aa5be2 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 151/189] 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 152/189] 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 ef558ccf432..00000000000 --- 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 6bd0d19712c..00000000000 --- 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 153/189] 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 c7242ed11c5..b903e152a29 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 154/189] 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 3cd359ce58b..5ff02cd9519 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 155/189] 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 fdf60ef757e..3e8607ef8ec 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 45c7d41b029..b544079579a 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 156/189] 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 cd0dac94001..46d414ece6c 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 45776b6668b..a187b62a7bd 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 157/189] 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 98a35d2a9e9..00000000000 --- 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 158/189] 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 fc2387fda37..00000000000 --- 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 9408aac7e3b..00000000000 --- 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 7ae2a0f0888..918be510b6c 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 b903e152a29..b40910b10f4 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 a14a0dfbaba..b3e0097ec4c 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 f126c3d9ae1..de80f2a6d1a 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 c3f69d91cb7..dd204bfd54e 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 ed24b62364d..26762543740 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 23fc6235e80..2edfa6190ea 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 8af3c09dd10..6ee2ce9ac4d 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 e0970353a98..28de1170d27 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 240a4ea3fc5..c0ee9c88b2b 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 9afbd7d7f2f..db27630cafa 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 d8467305df9..6c5f9c63677 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 d02524a7df3..cb16064667a 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 7559579d863..962e8945e81 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 159/189] 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 918be510b6c..a74da7d1acc 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 b40910b10f4..69643d92cd2 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 b3e0097ec4c..224ee1161fb 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 de80f2a6d1a..da3371a59b3 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 dd204bfd54e..ca72e2de251 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 26762543740..042f3b3dc91 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 2edfa6190ea..b004fae7fbb 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 6ee2ce9ac4d..38d197bb7dd 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 28de1170d27..5a9744c966b 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 c0ee9c88b2b..95623ec7a1e 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 db27630cafa..efbfd9ed865 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 6c5f9c63677..e4a8d3ff867 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 cb16064667a..2b81cf22dba 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 962e8945e81..8469924a850 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 160/189] 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 a74da7d1acc..b4d0b908bbe 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 161/189] 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 b4e9de9ac94..7291ea554a5 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 162/189] 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 b2c6f919d5f..f00621d4d2b 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 701f3064e92..d8d9d125070 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 d8adccace55..b7b7c27ec6b 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 4ce404f01b0..21bca11cc1a 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 163/189] 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 d8d9d125070..2dd5b0b006b 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 b7b7c27ec6b..ed2872bb67e 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 164/189] 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 68b8c8b0ab4..20ffa7c40c0 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 f6e89eede03..0fbc365c134 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 165/189] 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 (64%) diff --git a/cpp/ql/lib/experimental/quantum/Language.qll b/cpp/ql/lib/experimental/quantum/Language.qll index 176db9736ad..db9737cf152 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 335360caeb2..b7bf768c3f2 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 eaf63aa5be2..8e00f34f02b 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 036218757a8..eeaa063e473 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 64% rename from shared/experimental/qlpack.yml rename to shared/quantum/qlpack.yml index 2976c56ba49..8e34c19c112 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 166/189] Update CODEOWNERS to specify shared pack directory --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/CODEOWNERS b/CODEOWNERS index 318d9f2c6de..96aa46df949 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 167/189] 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 26486686cb2..b3615bddb33 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 00000000000..7b2d1a9d62e --- /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 168/189] 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 00000000000..8b0f1661e63 --- /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 9290f65d5b2..1fcc7e1cf48 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 a2859a6265b..8b0f1661e63 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 d449cb3057f..8b0f1661e63 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 96b0b028bdd..8b0f1661e63 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 169/189] 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 9e6c4ff8b81..794fd340bcf 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 170/189] 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 794fd340bcf..95d29153f47 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 171/189] 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 f741e3c9f94..32979da1065 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 bc79d5d4ce6..f9c59432846 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 172/189] 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 8e00f34f02b..864ca6dd931 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 b4d0b908bbe..e796cc9e109 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 224ee1161fb..98a8aa38a03 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 2b81cf22dba..14148354d0f 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 69a4fd75acf..54691c306bd 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 173/189] 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 864ca6dd931..59164901c10 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 e796cc9e109..dbdc832c70b 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 98a8aa38a03..060b7df99a9 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 54691c306bd..1a192e84778 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 174/189] 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 1a192e84778..a87aee2e69c 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 175/189] 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 e3ab61274d2..ec742c71459 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 176/189] 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 ec742c71459..2e4ac22257f 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 177/189] 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 2e4ac22257f..a6949c569c0 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 178/189] 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 7a5fd2d000f..11d0df45d59 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 a6949c569c0..6bfee08a3d2 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 179/189] 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 b3615bddb33..dad24e980ed 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 7b2d1a9d62e..deffd72086d 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 180/189] 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 dad24e980ed..035e4ce81f2 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 42ac0521db3..966d6493637 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 56cc43babd0..75e2969fabc 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 a50167812d046a3a7026c0aaddb9e927a32ec4ee Mon Sep 17 00:00:00 2001 From: yoff Date: Mon, 12 May 2025 20:53:04 +0200 Subject: [PATCH 181/189] 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 db6b7590220..94b2f19caaa 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 00000000000..c62510ba5ba --- /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 a7b37515d7f..808ce42dd85 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 182/189] 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 914a0be40c9..f81b977ac98 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 daca5d73f55..9290f65d5b2 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 dbb615bf06c..9d05f9bf06d 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 dbb615bf06c..9d05f9bf06d 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 dbb615bf06c..9d05f9bf06d 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 daca5d73f55..9290f65d5b2 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 dbb615bf06c..9d05f9bf06d 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 dbb615bf06c..9d05f9bf06d 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 dbb615bf06c..9d05f9bf06d 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 dbb615bf06c..9d05f9bf06d 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 1fcc7e1cf48..63ce15b2b4f 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 8b0f1661e63..96b0b028bdd 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 0ce0c6870b7..96b0b028bdd 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 daca5d73f55..9290f65d5b2 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 ebbb0432489..c5b4a958655 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 ba17ecb5638..20a0480c8e2 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 daca5d73f55..9290f65d5b2 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 ce5d6db635a..cce2f114af6 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 595b1a2bac0..7404a7573b2 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 0ce0c6870b7..96b0b028bdd 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 daca5d73f55..9290f65d5b2 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 cffffd06410..5dfd0afb374 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 aff430e13cc..ab08ee323e2 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 ebbb0432489..c5b4a958655 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 0ce0c6870b7..96b0b028bdd 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 dbb615bf06c..9d05f9bf06d 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 dbb615bf06c..9d05f9bf06d 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 d43edf41c56..9d05f9bf06d 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 aff430e13cc..ab08ee323e2 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 daca5d73f55..9290f65d5b2 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 daca5d73f55..9290f65d5b2 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 aff430e13cc..ab08ee323e2 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 0ce0c6870b7..96b0b028bdd 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 dbb615bf06c..9d05f9bf06d 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 dbb615bf06c..9d05f9bf06d 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 dbb615bf06c..9d05f9bf06d 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 daca5d73f55..9290f65d5b2 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 daca5d73f55..9290f65d5b2 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 62b643d45cb..750b4e67189 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 daca5d73f55..9290f65d5b2 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 daca5d73f55..7553ab79ad3 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 dbb615bf06c..9d05f9bf06d 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 1fcc7e1cf48..9290f65d5b2 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 595b1a2bac0..7404a7573b2 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 daca5d73f55..9290f65d5b2 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 daca5d73f55..9290f65d5b2 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 daca5d73f55..9290f65d5b2 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 0ce0c6870b7..96b0b028bdd 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 0af89500401..5e2b8b8284e 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 0ce0c6870b7..96b0b028bdd 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 0ce0c6870b7..96b0b028bdd 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 8b0f1661e63..96b0b028bdd 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 183/189] 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 607e4d6d0e2..64185aa2c15 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 8b0f1661e63..00000000000 --- 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 184/189] 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 64185aa2c15..607e4d6d0e2 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 185/189] 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 8b0f1661e63..ea31b8476dd 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 00000000000..7cb6d36c74d --- /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 56f51208e54..f0572742f88 100644 --- a/csharp/ql/test/resources/stubs/System.Web.cs +++ b/csharp/ql/test/resources/stubs/System.Web.cs @@ -60,21 +60,6 @@ namespace System.Web } } -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 186/189] 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 187/189] 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 60674ed54ed..a5f8ffc8fa0 100755 --- a/misc/scripts/models-as-data/generate_mad.py +++ b/misc/scripts/models-as-data/generate_mad.py @@ -75,7 +75,7 @@ class Generator: @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 @@ class Generator: 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 188/189] 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 824b37180a1..00000000000 --- 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 0a2d9e797fc..00000000000 --- 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 189/189] 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 72cc4ffdf57..eaf1ff06b7d 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() = "!" }