Merge pull request #11660 from erik-krogh/dynamic-useInstanceOf

Py/JS/RB: Use instanceof in more places
This commit is contained in:
Erik Krogh Kristensen
2022-12-13 21:50:13 +01:00
committed by GitHub
88 changed files with 256 additions and 574 deletions

View File

@@ -11,9 +11,7 @@
private import python
/** A control flow node which might correspond to a special method call. */
class PotentialSpecialMethodCallNode extends ControlFlowNode {
PotentialSpecialMethodCallNode() { this instanceof SpecialMethod::Potential }
}
class PotentialSpecialMethodCallNode extends ControlFlowNode instanceof SpecialMethod::Potential { }
/**
* Machinery for detecting special method calls.

View File

@@ -15,13 +15,9 @@ private import semmle.python.Concepts
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `RemoteFlowSource::Range` instead.
*/
class RemoteFlowSource extends DataFlow::Node {
RemoteFlowSource::Range self;
RemoteFlowSource() { this = self }
class RemoteFlowSource extends DataFlow::Node instanceof RemoteFlowSource::Range {
/** Gets a string that describes the type of this remote flow source. */
string getSourceType() { result = self.getSourceType() }
string getSourceType() { result = super.getSourceType() }
}
/** Provides a class for modeling new sources of remote user input. */

View File

@@ -21,11 +21,8 @@ module SensitiveDataClassification = SensitiveDataHeuristics::SensitiveDataClass
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `SensitiveDataSource::Range` instead.
*/
class SensitiveDataSource extends DataFlow::Node {
SensitiveDataSource::Range range;
class SensitiveDataSource extends DataFlow::Node instanceof SensitiveDataSource::Range {
SensitiveDataSource() {
this = range and
// ignore sensitive password sources in getpass.py, that can escape through `getpass.getpass()` return value,
// since `getpass.getpass()` is considered a source itself.
not exists(Module getpass |
@@ -39,7 +36,7 @@ class SensitiveDataSource extends DataFlow::Node {
/**
* Gets the classification of the sensitive data.
*/
SensitiveDataClassification getClassification() { result = range.getClassification() }
SensitiveDataClassification getClassification() { result = super.getClassification() }
}
/** Provides a class for modeling new sources of sensitive data, such as secrets, certificates, or passwords. */

View File

@@ -207,16 +207,13 @@ class AssignmentTarget extends ControlFlowNode {
}
/** A direct (or top-level) target of an unpacking assignment. */
class UnpackingAssignmentDirectTarget extends ControlFlowNode {
class UnpackingAssignmentDirectTarget extends ControlFlowNode instanceof SequenceNode {
Expr value;
UnpackingAssignmentDirectTarget() {
this instanceof SequenceNode and
(
value = this.(AssignmentTarget).getValue()
or
value = this.(ForTarget).getSource()
)
value = this.(AssignmentTarget).getValue()
or
value = this.(ForTarget).getSource()
}
Expr getValue() { result = value }

View File

@@ -197,9 +197,7 @@ class TaintTrackingNode extends TTaintTrackingNode {
* It is implemented as a separate class for clarity and to keep the code
* in `TaintTracking::Configuration` simpler.
*/
class TaintTrackingImplementation extends string {
TaintTrackingImplementation() { this instanceof TaintTracking::Configuration }
class TaintTrackingImplementation extends string instanceof TaintTracking::Configuration {
/**
* Hold if there is a flow from `source`, which is a taint source, to
* `sink`, which is a taint sink, with this configuration.
@@ -218,7 +216,7 @@ class TaintTrackingImplementation extends string {
) {
context = TNoParam() and
path = TNoAttribute() and
this.(TaintTracking::Configuration).isSource(node, kind)
super.isSource(node, kind)
}
/** Hold if `source` is a source of taint. */
@@ -234,7 +232,7 @@ class TaintTrackingImplementation extends string {
exists(DataFlow::Node node, AttributePath path, TaintKind kind |
sink = TTaintTrackingNode_(node, _, path, kind, this) and
path = TNoAttribute() and
this.(TaintTracking::Configuration).isSink(node, kind)
super.isSink(node, kind)
)
}
@@ -259,11 +257,11 @@ class TaintTrackingImplementation extends string {
) {
this.unprunedStep(src, node, context, path, kind, edgeLabel) and
node.getBasicBlock().likelyReachable() and
not this.(TaintTracking::Configuration).isBarrier(node) and
not super.isBarrier(node) and
(
not path = TNoAttribute()
or
not this.(TaintTracking::Configuration).isBarrier(node, kind) and
not super.isBarrier(node, kind) and
exists(DataFlow::Node srcnode, TaintKind srckind |
src = TTaintTrackingNode_(srcnode, _, _, srckind, this) and
not this.prunedEdge(srcnode, node, srckind, kind)
@@ -274,9 +272,9 @@ class TaintTrackingImplementation extends string {
private predicate prunedEdge(
DataFlow::Node srcnode, DataFlow::Node destnode, TaintKind srckind, TaintKind destkind
) {
this.(TaintTracking::Configuration).isBarrierEdge(srcnode, destnode, srckind, destkind)
super.isBarrierEdge(srcnode, destnode, srckind, destkind)
or
srckind = destkind and this.(TaintTracking::Configuration).isBarrierEdge(srcnode, destnode)
srckind = destkind and super.isBarrierEdge(srcnode, destnode)
}
private predicate unprunedStep(
@@ -314,14 +312,14 @@ class TaintTrackingImplementation extends string {
this.legacyExtensionStep(src, node, context, path, kind, edgeLabel)
or
exists(DataFlow::Node srcnode, TaintKind srckind |
this.(TaintTracking::Configuration).isAdditionalFlowStep(srcnode, node, srckind, kind) and
super.isAdditionalFlowStep(srcnode, node, srckind, kind) and
src = TTaintTrackingNode_(srcnode, context, path, srckind, this) and
path.noAttribute() and
edgeLabel = "additional with kind"
)
or
exists(DataFlow::Node srcnode |
this.(TaintTracking::Configuration).isAdditionalFlowStep(srcnode, node) and
super.isAdditionalFlowStep(srcnode, node) and
src = TTaintTrackingNode_(srcnode, context, path, kind, this) and
path.noAttribute() and
edgeLabel = "additional"
@@ -618,7 +616,7 @@ class TaintTrackingImplementation extends string {
TaintKind kind, string edgeLabel
) {
exists(TaintTracking::Extension extension, DataFlow::Node srcnode, TaintKind srckind |
this.(TaintTracking::Configuration).isExtension(extension) and
super.isExtension(extension) and
src = TTaintTrackingNode_(srcnode, context, path, srckind, this) and
srcnode.asCfgNode() = extension
|
@@ -646,9 +644,7 @@ class TaintTrackingImplementation extends string {
* Another taint-tracking class to help partition the code for clarity
* This class handle tracking of ESSA variables.
*/
private class EssaTaintTracking extends string {
EssaTaintTracking() { this instanceof TaintTracking::Configuration }
private class EssaTaintTracking extends string instanceof TaintTracking::Configuration {
pragma[noinline]
predicate taintedDefinition(
TaintTrackingNode src, EssaDefinition defn, TaintTrackingContext context, AttributePath path,
@@ -691,7 +687,7 @@ private class EssaTaintTracking extends string {
defn = phi.asVariable().getDefinition() and
predvar = defn.getInput(pred) and
not pred.unlikelySuccessor(defn.getBasicBlock()) and
not this.(TaintTracking::Configuration).isBarrierEdge(srcnode, phi) and
not super.isBarrierEdge(srcnode, phi) and
srcnode.asVariable() = predvar
)
}
@@ -781,7 +777,7 @@ private class EssaTaintTracking extends string {
exists(DataFlow::Node srcnode |
src = TTaintTrackingNode_(srcnode, context, path, kind, this) and
srcnode.asVariable() = defn.getInput() and
not this.(TaintTracking::Configuration).isBarrierTest(defn.getTest(), defn.getSense())
not super.isBarrierTest(defn.getTest(), defn.getSense())
)
}
@@ -801,7 +797,7 @@ private class EssaTaintTracking extends string {
) {
exists(DataFlow::Node srcnode, ControlFlowNode use |
src = TTaintTrackingNode_(srcnode, context, path, kind, this) and
not this.(TaintTracking::Configuration).isBarrierTest(defn.getTest(), defn.getSense()) and
not super.isBarrierTest(defn.getTest(), defn.getSense()) and
defn.getSense() = this.testEvaluates(defn, defn.getTest(), use, src)
)
}
@@ -815,7 +811,7 @@ private class EssaTaintTracking extends string {
src = TTaintTrackingNode_(srcnode, context, path, kind, this) and
piNodeTestAndUse(defn, test, use) and
srcnode.asVariable() = defn.getInput() and
not this.(TaintTracking::Configuration).isBarrierTest(test, defn.getSense()) and
not super.isBarrierTest(test, defn.getSense()) and
testEvaluatesMaybe(test, use)
)
}

View File

@@ -205,22 +205,19 @@ class BuiltinVariable extends SsaSourceVariable {
override CallNode redefinedAtCallSite() { none() }
}
class ModuleVariable extends SsaSourceVariable {
class ModuleVariable extends SsaSourceVariable instanceof GlobalVariable {
ModuleVariable() {
this instanceof GlobalVariable and
(
exists(this.(Variable).getAStore())
or
this.(Variable).getId() = "__name__"
or
this.(Variable).getId() = "__package__"
or
exists(ImportStar is | is.getScope() = this.(Variable).getScope())
)
exists(this.(Variable).getAStore())
or
this.(Variable).getId() = "__name__"
or
this.(Variable).getId() = "__package__"
or
exists(ImportStar is | is.getScope() = this.(Variable).getScope())
}
pragma[nomagic]
private Scope scope_as_global_variable() { result = this.(GlobalVariable).getScope() }
private Scope scope_as_global_variable() { result = GlobalVariable.super.getScope() }
pragma[noinline]
CallNode global_variable_callnode() { result.getScope() = this.scope_as_global_variable() }
@@ -263,7 +260,7 @@ class ModuleVariable extends SsaSourceVariable {
class_with_global_metaclass(s, this)
or
/* Variable is used in scope */
this.(GlobalVariable).getAUse().getScope() = s
GlobalVariable.super.getAUse().getScope() = s
)
or
exists(ImportTimeScope scope | scope.entryEdge(_, result) |

View File

@@ -59,24 +59,24 @@ module AiohttpWebModel {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `AiohttpRouteSetup::Range` instead.
*/
class AiohttpRouteSetup extends Http::Server::RouteSetup::Range {
AiohttpRouteSetup::Range range;
AiohttpRouteSetup() { this = range }
class AiohttpRouteSetup extends Http::Server::RouteSetup::Range instanceof AiohttpRouteSetup::Range {
override Parameter getARoutedParameter() { none() }
override string getFramework() { result = "aiohttp.web" }
/** Gets the argument specifying the handler (either a coroutine or a view-class). */
DataFlow::Node getHandlerArg() { result = range.getHandlerArg() }
DataFlow::Node getHandlerArg() { result = super.getHandlerArg() }
override DataFlow::Node getUrlPatternArg() { result = range.getUrlPatternArg() }
override DataFlow::Node getUrlPatternArg() {
result = AiohttpRouteSetup::Range.super.getUrlPatternArg()
}
/** Gets the view-class that is referenced in the view-class handler argument, if any. */
Class getViewClass() { result = range.getViewClass() }
Class getViewClass() { result = super.getViewClass() }
override Function getARequestHandler() { result = range.getARequestHandler() }
override Function getARequestHandler() {
result = AiohttpRouteSetup::Range.super.getARequestHandler()
}
}
/** Provides a class for modeling new aiohttp.web route setups. */

View File

@@ -2526,11 +2526,10 @@ module PrivateDjango {
*
* Needs this subclass to be considered a RegexString.
*/
private class DjangoRouteRegex extends RegexString {
private class DjangoRouteRegex extends RegexString instanceof StrConst {
DjangoRegexRouteSetup rePathCall;
DjangoRouteRegex() {
this instanceof StrConst and
rePathCall.getUrlPatternArg().getALocalSource() = DataFlow::exprNode(this)
}

View File

@@ -385,13 +385,10 @@ module Tornado {
*
* Needs this subclass to be considered a RegexString.
*/
private class TornadoRouteRegex extends RegexString {
private class TornadoRouteRegex extends RegexString instanceof StrConst {
TornadoRouteSetup setup;
TornadoRouteRegex() {
this instanceof StrConst and
setup.getUrlPatternArg().getALocalSource() = DataFlow::exprNode(this)
}
TornadoRouteRegex() { setup.getUrlPatternArg().getALocalSource() = DataFlow::exprNode(this) }
TornadoRouteSetup getRouteSetup() { result = setup }
}

View File

@@ -41,9 +41,7 @@ module StackTraceExposure {
/**
* A source of exception info, considered as a flow source.
*/
class ExceptionInfoAsSource extends Source {
ExceptionInfoAsSource() { this instanceof ExceptionInfo }
}
class ExceptionInfoAsSource extends Source instanceof ExceptionInfo { }
/**
* The body of a HTTP response that will be returned from a server, considered as a flow sink.

View File

@@ -30,9 +30,7 @@ module XmlBomb {
abstract class Sanitizer extends DataFlow::Node { }
/** A source of remote user input, considered as a flow source for XML bomb vulnerabilities. */
class RemoteFlowSourceAsSource extends Source {
RemoteFlowSourceAsSource() { this instanceof RemoteFlowSource }
}
class RemoteFlowSourceAsSource extends Source instanceof RemoteFlowSource { }
/**
* A call to an XML parser that is vulnerable to XML bombs.

View File

@@ -30,9 +30,7 @@ module Xxe {
abstract class Sanitizer extends DataFlow::Node { }
/** A source of remote user input, considered as a flow source for XXE vulnerabilities. */
class RemoteFlowSourceAsSource extends Source {
RemoteFlowSourceAsSource() { this instanceof RemoteFlowSource }
}
class RemoteFlowSourceAsSource extends Source instanceof RemoteFlowSource { }
/**
* A call to an XML parser that is vulnerable to XXE.

View File

@@ -80,9 +80,7 @@ class NoqaSuppressionComment extends LineSuppressionComment {
/**
* The scope of an alert suppression comment.
*/
class SuppressionScope extends @py_comment {
SuppressionScope() { this instanceof SuppressionComment }
class SuppressionScope extends @py_comment instanceof SuppressionComment {
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
@@ -93,7 +91,7 @@ class SuppressionScope extends @py_comment {
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.(SuppressionComment).covers(filepath, startline, startcolumn, endline, endcolumn)
super.covers(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets a textual representation of this element. */

View File

@@ -42,14 +42,10 @@ module CopyFile {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `CopyFile::Range` instead.
*/
class CopyFile extends DataFlow::Node {
CopyFile::Range range;
class CopyFile extends DataFlow::Node instanceof CopyFile::Range {
DataFlow::Node getAPathArgument() { result = super.getAPathArgument() }
CopyFile() { this = range }
DataFlow::Node getAPathArgument() { result = range.getAPathArgument() }
DataFlow::Node getfsrcArgument() { result = range.getfsrcArgument() }
DataFlow::Node getfsrcArgument() { result = super.getfsrcArgument() }
}
/** Provides classes for modeling log related APIs. */
@@ -74,12 +70,8 @@ module LogOutput {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `LogOutput::Range` instead.
*/
class LogOutput extends DataFlow::Node {
LogOutput::Range range;
LogOutput() { this = range }
DataFlow::Node getAnInput() { result = range.getAnInput() }
class LogOutput extends DataFlow::Node instanceof LogOutput::Range {
DataFlow::Node getAnInput() { result = super.getAnInput() }
}
/** Provides classes for modeling LDAP query execution-related APIs. */
@@ -107,15 +99,11 @@ deprecated module LDAPQuery = LdapQuery;
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `LDAPQuery::Range` instead.
*/
class LdapQuery extends DataFlow::Node {
LdapQuery::Range range;
LdapQuery() { this = range }
class LdapQuery extends DataFlow::Node instanceof LdapQuery::Range {
/**
* Gets the argument containing the executed expression.
*/
DataFlow::Node getQuery() { result = range.getQuery() }
DataFlow::Node getQuery() { result = super.getQuery() }
}
/** DEPRECATED: Alias for LdapQuery */
@@ -146,15 +134,11 @@ deprecated module LDAPEscape = LdapEscape;
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `LDAPEscape::Range` instead.
*/
class LdapEscape extends DataFlow::Node {
LdapEscape::Range range;
LdapEscape() { this = range }
class LdapEscape extends DataFlow::Node instanceof LdapEscape::Range {
/**
* Gets the argument containing the escaped expression.
*/
DataFlow::Node getAnInput() { result = range.getAnInput() }
DataFlow::Node getAnInput() { result = super.getAnInput() }
}
/** DEPRECATED: Alias for LdapEscape */
@@ -198,25 +182,21 @@ deprecated module LDAPBind = LdapBind;
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `LDAPBind::Range` instead.
*/
class LdapBind extends DataFlow::Node {
LdapBind::Range range;
LdapBind() { this = range }
class LdapBind extends DataFlow::Node instanceof LdapBind::Range {
/**
* Gets the argument containing the binding host.
*/
DataFlow::Node getHost() { result = range.getHost() }
DataFlow::Node getHost() { result = super.getHost() }
/**
* Gets the argument containing the binding expression.
*/
DataFlow::Node getPassword() { result = range.getPassword() }
DataFlow::Node getPassword() { result = super.getPassword() }
/**
* Holds if the binding process use SSL.
*/
predicate useSsl() { range.useSsl() }
predicate useSsl() { super.useSsl() }
/** DEPRECATED: Alias for useSsl */
deprecated predicate useSSL() { useSsl() }
@@ -250,15 +230,11 @@ deprecated module SQLEscape = SqlEscape;
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `SQLEscape::Range` instead.
*/
class SqlEscape extends DataFlow::Node {
SqlEscape::Range range;
SqlEscape() { this = range }
class SqlEscape extends DataFlow::Node instanceof SqlEscape::Range {
/**
* Gets the argument containing the raw SQL statement.
*/
DataFlow::Node getAnInput() { result = range.getAnInput() }
DataFlow::Node getAnInput() { result = super.getAnInput() }
}
/** DEPRECATED: Alias for SqlEscape */
@@ -287,13 +263,9 @@ deprecated module NoSQLQuery = NoSqlQuery;
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `NoSQLQuery::Range` instead.
*/
class NoSqlQuery extends DataFlow::Node {
NoSqlQuery::Range range;
NoSqlQuery() { this = range }
class NoSqlQuery extends DataFlow::Node instanceof NoSqlQuery::Range {
/** Gets the argument that specifies the NoSql query to be executed. */
DataFlow::Node getQuery() { result = range.getQuery() }
DataFlow::Node getQuery() { result = super.getQuery() }
}
/** DEPRECATED: Alias for NoSqlQuery */
@@ -322,13 +294,9 @@ deprecated module NoSQLSanitizer = NoSqlSanitizer;
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `NoSQLSanitizer::Range` instead.
*/
class NoSqlSanitizer extends DataFlow::Node {
NoSqlSanitizer::Range range;
NoSqlSanitizer() { this = range }
class NoSqlSanitizer extends DataFlow::Node instanceof NoSqlSanitizer::Range {
/** Gets the argument that specifies the NoSql query to be sanitized. */
DataFlow::Node getAnInput() { result = range.getAnInput() }
DataFlow::Node getAnInput() { result = super.getAnInput() }
}
/** DEPRECATED: Alias for NoSqlSanitizer */
@@ -361,20 +329,16 @@ module HeaderDeclaration {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `HeaderDeclaration::Range` instead.
*/
class HeaderDeclaration extends DataFlow::Node {
HeaderDeclaration::Range range;
HeaderDeclaration() { this = range }
class HeaderDeclaration extends DataFlow::Node instanceof HeaderDeclaration::Range {
/**
* Gets the argument containing the header name.
*/
DataFlow::Node getNameArg() { result = range.getNameArg() }
DataFlow::Node getNameArg() { result = super.getNameArg() }
/**
* Gets the argument containing the header value.
*/
DataFlow::Node getValueArg() { result = range.getValueArg() }
DataFlow::Node getValueArg() { result = super.getValueArg() }
}
/** Provides classes for modeling Csv writer APIs. */
@@ -399,15 +363,11 @@ module CsvWriter {
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `CsvWriter::Range` instead.
*/
class CsvWriter extends DataFlow::Node {
CsvWriter::Range range;
CsvWriter() { this = range }
class CsvWriter extends DataFlow::Node instanceof CsvWriter::Range {
/**
* Get the parameter value of the csv writer function.
*/
DataFlow::Node getAnInput() { result = range.getAnInput() }
DataFlow::Node getAnInput() { result = super.getAnInput() }
}
/**

View File

@@ -28,7 +28,6 @@ import experimental.semmle.python.Concepts
*/
class CookieHeader extends Cookie::Range instanceof HeaderDeclaration {
CookieHeader() {
this instanceof HeaderDeclaration and
exists(StrConst str |
str.getText() = "Set-Cookie" and
DataFlow::exprNode(str)