Python: Rewrite concepts to use extends ... instanceof ...

This caused compilation time for `ConceptsTest.ql` to go from 1m24s to
7s
This commit is contained in:
Rasmus Wriedt Larsen
2022-04-05 12:31:09 +02:00
parent a7dab53ed2
commit b7f56dd17e

View File

@@ -17,13 +17,9 @@ private import semmle.python.Frameworks
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `SystemCommandExecution::Range` instead.
*/
class SystemCommandExecution extends DataFlow::Node {
SystemCommandExecution::Range range;
SystemCommandExecution() { this = range }
class SystemCommandExecution extends DataFlow::Node instanceof SystemCommandExecution::Range {
/** Gets the argument that specifies the command to be executed. */
DataFlow::Node getCommand() { result = range.getCommand() }
DataFlow::Node getCommand() { result = super.getCommand() }
}
/** Provides a class for modeling new system-command execution APIs. */
@@ -48,13 +44,9 @@ module SystemCommandExecution {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `FileSystemAccess::Range` instead.
*/
class FileSystemAccess extends DataFlow::Node {
FileSystemAccess::Range range;
FileSystemAccess() { this = range }
class FileSystemAccess extends DataFlow::Node instanceof FileSystemAccess::Range {
/** Gets an argument to this file system access that is interpreted as a path. */
DataFlow::Node getAPathArgument() { result = range.getAPathArgument() }
DataFlow::Node getAPathArgument() { result = super.getAPathArgument() }
}
/** Provides a class for modeling new file system access APIs. */
@@ -78,14 +70,12 @@ module FileSystemAccess {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `FileSystemWriteAccess::Range` instead.
*/
class FileSystemWriteAccess extends FileSystemAccess {
override FileSystemWriteAccess::Range range;
class FileSystemWriteAccess extends FileSystemAccess instanceof FileSystemWriteAccess::Range {
/**
* Gets a node that represents data to be written to the file system (possibly with
* some transformation happening before it is written, like JSON encoding).
*/
DataFlow::Node getADataNode() { result = range.getADataNode() }
DataFlow::Node getADataNode() { result = super.getADataNode() }
}
/** Provides a class for modeling new file system writes. */
@@ -111,13 +101,9 @@ module Path {
* A data-flow node that performs path normalization. This is often needed in order
* to safely access paths.
*/
class PathNormalization extends DataFlow::Node {
PathNormalization::Range range;
PathNormalization() { this = range }
class PathNormalization extends DataFlow::Node instanceof PathNormalization::Range {
/** Gets an argument to this path normalization that is interpreted as a path. */
DataFlow::Node getPathArg() { result = range.getPathArg() }
DataFlow::Node getPathArg() { result = super.getPathArg() }
}
/** Provides a class for modeling new path normalization APIs. */
@@ -133,12 +119,10 @@ module Path {
}
/** A data-flow node that checks that a path is safe to access. */
class SafeAccessCheck extends DataFlow::BarrierGuard {
SafeAccessCheck::Range range;
SafeAccessCheck() { this = range }
override predicate checks(ControlFlowNode node, boolean branch) { range.checks(node, branch) }
class SafeAccessCheck extends DataFlow::BarrierGuard instanceof SafeAccessCheck::Range {
override predicate checks(ControlFlowNode node, boolean branch) {
SafeAccessCheck::Range.super.checks(node, branch)
}
}
/** Provides a class for modeling new path safety checks. */
@@ -160,22 +144,18 @@ module Path {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `Decoding::Range` instead.
*/
class Decoding extends DataFlow::Node {
Decoding::Range range;
Decoding() { this = range }
class Decoding extends DataFlow::Node instanceof Decoding::Range {
/** Holds if this call may execute code embedded in its input. */
predicate mayExecuteInput() { range.mayExecuteInput() }
predicate mayExecuteInput() { super.mayExecuteInput() }
/** Gets an input that is decoded by this function. */
DataFlow::Node getAnInput() { result = range.getAnInput() }
DataFlow::Node getAnInput() { result = super.getAnInput() }
/** Gets the output that contains the decoded data produced by this function. */
DataFlow::Node getOutput() { result = range.getOutput() }
DataFlow::Node getOutput() { result = super.getOutput() }
/** Gets an identifier for the format this function decodes from, such as "JSON". */
string getFormat() { result = range.getFormat() }
string getFormat() { result = super.getFormat() }
}
/** Provides a class for modeling new decoding mechanisms. */
@@ -226,19 +206,15 @@ private class DecodingAdditionalTaintStep extends TaintTracking::AdditionalTaint
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `Encoding::Range` instead.
*/
class Encoding extends DataFlow::Node {
Encoding::Range range;
Encoding() { this = range }
class Encoding extends DataFlow::Node instanceof Encoding::Range {
/** Gets an input that is encoded by this function. */
DataFlow::Node getAnInput() { result = range.getAnInput() }
DataFlow::Node getAnInput() { result = super.getAnInput() }
/** Gets the output that contains the encoded data produced by this function. */
DataFlow::Node getOutput() { result = range.getOutput() }
DataFlow::Node getOutput() { result = super.getOutput() }
/** Gets an identifier for the format this function decodes from, such as "JSON". */
string getFormat() { result = range.getFormat() }
string getFormat() { result = super.getFormat() }
}
/** Provides a class for modeling new encoding mechanisms. */
@@ -280,13 +256,9 @@ private class EncodingAdditionalTaintStep extends TaintTracking::AdditionalTaint
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `Logging::Range` instead.
*/
class Logging extends DataFlow::Node {
Logging::Range range;
Logging() { this = range }
class Logging extends DataFlow::Node instanceof Logging::Range {
/** Gets an input that is logged. */
DataFlow::Node getAnInput() { result = range.getAnInput() }
DataFlow::Node getAnInput() { result = super.getAnInput() }
}
/** Provides a class for modeling new logging mechanisms. */
@@ -309,13 +281,9 @@ module Logging {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `CodeExecution::Range` instead.
*/
class CodeExecution extends DataFlow::Node {
CodeExecution::Range range;
CodeExecution() { this = range }
class CodeExecution extends DataFlow::Node instanceof CodeExecution::Range {
/** Gets the argument that specifies the code to be executed. */
DataFlow::Node getCode() { result = range.getCode() }
DataFlow::Node getCode() { result = super.getCode() }
}
/** Provides a class for modeling new dynamic code execution APIs. */
@@ -343,13 +311,9 @@ module CodeExecution {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `SqlConstruction::Range` instead.
*/
class SqlConstruction extends DataFlow::Node {
SqlConstruction::Range range;
SqlConstruction() { this = range }
class SqlConstruction extends DataFlow::Node instanceof SqlConstruction::Range {
/** Gets the argument that specifies the SQL statements to be constructed. */
DataFlow::Node getSql() { result = range.getSql() }
DataFlow::Node getSql() { result = super.getSql() }
}
/** Provides a class for modeling new SQL execution APIs. */
@@ -380,13 +344,9 @@ module SqlConstruction {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `SqlExecution::Range` instead.
*/
class SqlExecution extends DataFlow::Node {
SqlExecution::Range range;
SqlExecution() { this = range }
class SqlExecution extends DataFlow::Node instanceof SqlExecution::Range {
/** Gets the argument that specifies the SQL statements to be executed. */
DataFlow::Node getSql() { result = range.getSql() }
DataFlow::Node getSql() { result = super.getSql() }
}
/** Provides a class for modeling new SQL execution APIs. */
@@ -412,22 +372,18 @@ module SqlExecution {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `RegexExecution::Range` instead.
*/
class RegexExecution extends DataFlow::Node {
RegexExecution::Range range;
RegexExecution() { this = range }
class RegexExecution extends DataFlow::Node instanceof RegexExecution::Range {
/** Gets the data flow node for the regex being executed by this node. */
DataFlow::Node getRegex() { result = range.getRegex() }
DataFlow::Node getRegex() { result = super.getRegex() }
/** Gets a dataflow node for the string to be searched or matched against. */
DataFlow::Node getString() { result = range.getString() }
DataFlow::Node getString() { result = super.getString() }
/**
* Gets the name of this regex execution, typically the name of an executing method.
* This is used for nice alert messages and should include the module if possible.
*/
string getName() { result = range.getName() }
string getName() { result = super.getName() }
}
/** Provides classes for modeling new regular-expression execution APIs. */
@@ -466,19 +422,15 @@ module XML {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `XPathConstruction::Range` instead.
*/
class XPathConstruction extends DataFlow::Node {
XPathConstruction::Range range;
XPathConstruction() { this = range }
class XPathConstruction extends DataFlow::Node instanceof XPathConstruction::Range {
/** Gets the argument that specifies the XPath expressions to be constructed. */
DataFlow::Node getXPath() { result = range.getXPath() }
DataFlow::Node getXPath() { result = super.getXPath() }
/**
* Gets the name of this XPath expression construction, typically the name of an executing method.
* This is used for nice alert messages and should include the module if possible.
*/
string getName() { result = range.getName() }
string getName() { result = super.getName() }
}
/** Provides a class for modeling new XPath construction APIs. */
@@ -513,19 +465,15 @@ module XML {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `XPathExecution::Range` instead.
*/
class XPathExecution extends DataFlow::Node {
XPathExecution::Range range;
XPathExecution() { this = range }
class XPathExecution extends DataFlow::Node instanceof XPathExecution::Range {
/** Gets the data flow node for the XPath expression being executed by this node. */
DataFlow::Node getXPath() { result = range.getXPath() }
DataFlow::Node getXPath() { result = super.getXPath() }
/**
* Gets the name of this XPath expression execution, typically the name of an executing method.
* This is used for nice alert messages and should include the module if possible.
*/
string getName() { result = range.getName() }
string getName() { result = super.getName() }
}
/** Provides classes for modeling new regular-expression execution APIs. */
@@ -616,16 +564,12 @@ module LDAP {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `LDAPQuery::Range` instead.
*/
class LdapExecution extends DataFlow::Node {
LdapExecution::Range range;
LdapExecution() { this = range }
class LdapExecution extends DataFlow::Node instanceof LdapExecution::Range {
/** Gets the argument containing the filter string. */
DataFlow::Node getFilter() { result = range.getFilter() }
DataFlow::Node getFilter() { result = super.getFilter() }
/** Gets the argument containing the base DN. */
DataFlow::Node getBaseDn() { result = range.getBaseDn() }
DataFlow::Node getBaseDn() { result = super.getBaseDn() }
}
/** Provides classes for modeling new LDAP query execution-related APIs. */
@@ -653,26 +597,23 @@ module LDAP {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `Escaping::Range` instead.
*/
class Escaping extends DataFlow::Node {
Escaping::Range range;
class Escaping extends DataFlow::Node instanceof Escaping::Range {
Escaping() {
this = range and
// escapes that don't have _both_ input/output defined are not valid
exists(range.getAnInput()) and
exists(range.getOutput())
exists(super.getAnInput()) and
exists(super.getOutput())
}
/** Gets an input that will be escaped. */
DataFlow::Node getAnInput() { result = range.getAnInput() }
DataFlow::Node getAnInput() { result = super.getAnInput() }
/** Gets the output that contains the escaped data. */
DataFlow::Node getOutput() { result = range.getOutput() }
DataFlow::Node getOutput() { result = super.getOutput() }
/**
* Gets the context that this function escapes for, such as `html`, or `url`.
*/
string getKind() { result = range.getKind() }
string getKind() { result = super.getKind() }
}
/** Provides a class for modeling new escaping APIs. */
@@ -730,7 +671,7 @@ module Escaping {
* `<p>{}</p>`.
*/
class HtmlEscaping extends Escaping {
HtmlEscaping() { range.getKind() = Escaping::getHtmlKind() }
HtmlEscaping() { super.getKind() = Escaping::getHtmlKind() }
}
/**
@@ -738,7 +679,7 @@ class HtmlEscaping extends Escaping {
* the body of a regex.
*/
class RegexEscaping extends Escaping {
RegexEscaping() { range.getKind() = Escaping::getRegexKind() }
RegexEscaping() { super.getKind() = Escaping::getRegexKind() }
}
/**
@@ -746,14 +687,14 @@ class RegexEscaping extends Escaping {
* in an LDAP search.
*/
class LdapDnEscaping extends Escaping {
LdapDnEscaping() { range.getKind() = Escaping::getLdapDnKind() }
LdapDnEscaping() { super.getKind() = Escaping::getLdapDnKind() }
}
/**
* An escape of a string so it can be safely used as a filter in an LDAP search.
*/
class LdapFilterEscaping extends Escaping {
LdapFilterEscaping() { range.getKind() = Escaping::getLdapFilterKind() }
LdapFilterEscaping() { super.getKind() = Escaping::getLdapFilterKind() }
}
/** Provides classes for modeling HTTP-related APIs. */
@@ -772,29 +713,25 @@ module HTTP {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `RouteSetup::Range` instead.
*/
class RouteSetup extends DataFlow::Node {
RouteSetup::Range range;
RouteSetup() { this = range }
class RouteSetup extends DataFlow::Node instanceof RouteSetup::Range {
/** Gets the URL pattern for this route, if it can be statically determined. */
string getUrlPattern() { result = range.getUrlPattern() }
string getUrlPattern() { result = super.getUrlPattern() }
/**
* Gets a function that will handle incoming requests for this route, if any.
*
* NOTE: This will be modified in the near future to have a `RequestHandler` result, instead of a `Function`.
*/
Function getARequestHandler() { result = range.getARequestHandler() }
Function getARequestHandler() { result = super.getARequestHandler() }
/**
* Gets a parameter that will receive parts of the url when handling incoming
* requests for this route, if any. These automatically become a `RemoteFlowSource`.
*/
Parameter getARoutedParameter() { result = range.getARoutedParameter() }
Parameter getARoutedParameter() { result = super.getARoutedParameter() }
/** Gets a string that identifies the framework used for this route setup. */
string getFramework() { result = range.getFramework() }
string getFramework() { result = super.getFramework() }
}
/** Provides a class for modeling new HTTP routing APIs. */
@@ -841,19 +778,15 @@ module HTTP {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `RequestHandler::Range` instead.
*/
class RequestHandler extends Function {
RequestHandler::Range range;
RequestHandler() { this = range }
class RequestHandler extends Function instanceof RequestHandler::Range {
/**
* Gets a parameter that could receive parts of the url when handling incoming
* requests, if any. These automatically become a `RemoteFlowSource`.
*/
Parameter getARoutedParameter() { result = range.getARoutedParameter() }
Parameter getARoutedParameter() { result = super.getARoutedParameter() }
/** Gets a string that identifies the framework used for this route setup. */
string getFramework() { result = range.getFramework() }
string getFramework() { result = super.getFramework() }
}
/** Provides a class for modeling new HTTP request handlers. */
@@ -909,16 +842,12 @@ module HTTP {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `HttpResponse::Range` instead.
*/
class HttpResponse extends DataFlow::Node {
HttpResponse::Range range;
HttpResponse() { this = range }
class HttpResponse extends DataFlow::Node instanceof HttpResponse::Range {
/** Gets the data-flow node that specifies the body of this HTTP response. */
DataFlow::Node getBody() { result = range.getBody() }
DataFlow::Node getBody() { result = super.getBody() }
/** Gets the mimetype of this HTTP response, if it can be statically determined. */
string getMimetype() { result = range.getMimetype() }
string getMimetype() { result = super.getMimetype() }
}
/** Provides a class for modeling new HTTP response APIs. */
@@ -964,13 +893,9 @@ module HTTP {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `HttpRedirectResponse::Range` instead.
*/
class HttpRedirectResponse extends HttpResponse {
override HttpRedirectResponse::Range range;
HttpRedirectResponse() { this = range }
class HttpRedirectResponse extends HttpResponse instanceof HttpRedirectResponse::Range {
/** Gets the data-flow node that specifies the location of this HTTP redirect response. */
DataFlow::Node getRedirectLocation() { result = range.getRedirectLocation() }
DataFlow::Node getRedirectLocation() { result = super.getRedirectLocation() }
}
/** Provides a class for modeling new HTTP redirect response APIs. */
@@ -996,25 +921,21 @@ module HTTP {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `HTTP::CookieWrite::Range` instead.
*/
class CookieWrite extends DataFlow::Node {
CookieWrite::Range range;
CookieWrite() { this = range }
class CookieWrite extends DataFlow::Node instanceof CookieWrite::Range {
/**
* Gets the argument, if any, specifying the raw cookie header.
*/
DataFlow::Node getHeaderArg() { result = range.getHeaderArg() }
DataFlow::Node getHeaderArg() { result = super.getHeaderArg() }
/**
* Gets the argument, if any, specifying the cookie name.
*/
DataFlow::Node getNameArg() { result = range.getNameArg() }
DataFlow::Node getNameArg() { result = super.getNameArg() }
/**
* Gets the argument, if any, specifying the cookie value.
*/
DataFlow::Node getValueArg() { result = range.getValueArg() }
DataFlow::Node getValueArg() { result = super.getValueArg() }
}
/** Provides a class for modeling new cookie writes on HTTP responses. */
@@ -1131,27 +1052,23 @@ module Cryptography {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `KeyGeneration::Range` instead.
*/
class KeyGeneration extends DataFlow::Node {
KeyGeneration::Range range;
KeyGeneration() { this = range }
class KeyGeneration extends DataFlow::Node instanceof KeyGeneration::Range {
/** Gets the name of the cryptographic algorithm (for example `"RSA"` or `"AES"`). */
string getName() { result = range.getName() }
string getName() { result = super.getName() }
/** Gets the argument that specifies the size of the key in bits, if available. */
DataFlow::Node getKeySizeArg() { result = range.getKeySizeArg() }
DataFlow::Node getKeySizeArg() { result = super.getKeySizeArg() }
/**
* Gets the size of the key generated (in bits), as well as the `origin` that
* explains how we obtained this specific key size.
*/
int getKeySizeWithOrigin(DataFlow::Node origin) {
result = range.getKeySizeWithOrigin(origin)
result = super.getKeySizeWithOrigin(origin)
}
/** Gets the minimum key size (in bits) for this algorithm to be considered secure. */
int minimumSecureKeySize() { result = range.minimumSecureKeySize() }
int minimumSecureKeySize() { result = super.minimumSecureKeySize() }
}
/** Provides classes for modeling new key-pair generation APIs. */
@@ -1230,16 +1147,12 @@ module Cryptography {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `CryptographicOperation::Range` instead.
*/
class CryptographicOperation extends DataFlow::Node {
CryptographicOperation::Range range;
CryptographicOperation() { this = range }
class CryptographicOperation extends DataFlow::Node instanceof CryptographicOperation::Range {
/** Gets the algorithm used, if it matches a known `CryptographicAlgorithm`. */
CryptographicAlgorithm getAlgorithm() { result = range.getAlgorithm() }
CryptographicAlgorithm getAlgorithm() { result = super.getAlgorithm() }
/** Gets an input the algorithm is used on, for example the plain text input to be encrypted. */
DataFlow::Node getAnInput() { result = range.getAnInput() }
DataFlow::Node getAnInput() { result = super.getAnInput() }
}
/** Provides classes for modeling new applications of a cryptographic algorithms. */