diff --git a/javascript/ql/src/semmle/javascript/Base64.qll b/javascript/ql/src/semmle/javascript/Base64.qll index f2e91a7060ce..90fb7ff70ecf 100644 --- a/javascript/ql/src/semmle/javascript/Base64.qll +++ b/javascript/ql/src/semmle/javascript/Base64.qll @@ -6,16 +6,13 @@ import javascript module Base64 { /** A call to a base64 encoder. */ - class Encode extends DataFlow::Node { - Encode::Range encode; - - Encode() { this = encode } + class Encode extends DataFlow::Node instanceof Encode::Range { /** Gets the input passed to the encoder. */ - DataFlow::Node getInput() { result = encode.getInput() } + DataFlow::Node getInput() { result = this.(Encode::Range).getInput() } /** Gets the base64-encoded output of the encoder. */ - DataFlow::Node getOutput() { result = encode.getOutput() } + DataFlow::Node getOutput() { result = this.(Encode::Range).getOutput() } } module Encode { @@ -34,16 +31,13 @@ module Base64 { } /** A call to a base64 decoder. */ - class Decode extends DataFlow::Node { - Decode::Range encode; - - Decode() { this = encode } + class Decode extends DataFlow::Node instanceof Decode::Range { /** Gets the base64-encoded input passed to the decoder. */ - DataFlow::Node getInput() { result = encode.getInput() } + DataFlow::Node getInput() { result = this.(Decode::Range).getInput() } /** Gets the output of the decoder. */ - DataFlow::Node getOutput() { result = encode.getOutput() } + DataFlow::Node getOutput() { result = this.(Decode::Range).getOutput() } } module Decode { diff --git a/javascript/ql/src/semmle/javascript/Closure.qll b/javascript/ql/src/semmle/javascript/Closure.qll index 5a4e9b4c7e79..bc80e2534f9c 100644 --- a/javascript/ql/src/semmle/javascript/Closure.qll +++ b/javascript/ql/src/semmle/javascript/Closure.qll @@ -8,15 +8,14 @@ module Closure { /** * A reference to a Closure namespace. */ - class ClosureNamespaceRef extends DataFlow::Node { - ClosureNamespaceRef::Range range; - - ClosureNamespaceRef() { this = range } + class ClosureNamespaceRef extends DataFlow::Node instanceof ClosureNamespaceRef::Range { /** * Gets the namespace being referenced. */ - string getClosureNamespace() { result = range.getClosureNamespace() } + string getClosureNamespace() { + result = this.(ClosureNamespaceRef::Range).getClosureNamespace() + } } module ClosureNamespaceRef { @@ -36,8 +35,7 @@ module Closure { /** * A data flow node that returns the value of a closure namespace. */ - class ClosureNamespaceAccess extends ClosureNamespaceRef { - override ClosureNamespaceAccess::Range range; + class ClosureNamespaceAccess extends ClosureNamespaceRef instanceof ClosureNamespaceAccess::Range { } module ClosureNamespaceAccess { @@ -80,8 +78,7 @@ module Closure { /** * A top-level call to `goog.provide`. */ - class ClosureProvideCall extends ClosureNamespaceRef, DataFlow::MethodCallNode { - override DefaultClosureProvideCall range; + class ClosureProvideCall extends ClosureNamespaceRef, DataFlow::MethodCallNode instanceof DefaultClosureProvideCall { } /** @@ -94,8 +91,7 @@ module Closure { /** * A call to `goog.require`. */ - class ClosureRequireCall extends ClosureNamespaceAccess, DataFlow::MethodCallNode { - override DefaultClosureRequireCall range; + class ClosureRequireCall extends ClosureNamespaceAccess, DataFlow::MethodCallNode instanceof DefaultClosureRequireCall { } /** @@ -111,8 +107,7 @@ module Closure { /** * A top-level call to `goog.module` or `goog.declareModuleId`. */ - class ClosureModuleDeclaration extends ClosureNamespaceRef, DataFlow::MethodCallNode { - override DefaultClosureModuleDeclaration range; + class ClosureModuleDeclaration extends ClosureNamespaceRef, DataFlow::MethodCallNode instanceof DefaultClosureModuleDeclaration { } private GlobalVariable googVariable() { variables(result, "goog", any(GlobalScope sc)) } diff --git a/javascript/ql/src/semmle/javascript/InclusionTests.qll b/javascript/ql/src/semmle/javascript/InclusionTests.qll index 2d0cf1752a48..09ad75a91b45 100644 --- a/javascript/ql/src/semmle/javascript/InclusionTests.qll +++ b/javascript/ql/src/semmle/javascript/InclusionTests.qll @@ -16,16 +16,13 @@ private import javascript * ~A.indexOf(B) * ``` */ -class InclusionTest extends DataFlow::Node { - InclusionTest::Range range; - - InclusionTest() { this = range } +class InclusionTest extends DataFlow::Node instanceof InclusionTest::Range { /** Gets the `A` in `A.includes(B)`. */ - DataFlow::Node getContainerNode() { result = range.getContainerNode() } + DataFlow::Node getContainerNode() { result = this.(InclusionTest::Range).getContainerNode() } /** Gets the `B` in `A.includes(B)`. */ - DataFlow::Node getContainedNode() { result = range.getContainedNode() } + DataFlow::Node getContainedNode() { result = this.(InclusionTest::Range).getContainedNode() } /** * Gets the polarity of the check. @@ -33,7 +30,7 @@ class InclusionTest extends DataFlow::Node { * If the polarity is `false` the check returns `true` if the container does not contain * the given element. */ - boolean getPolarity() { result = range.getPolarity() } + boolean getPolarity() { result = this.(InclusionTest::Range).getPolarity() } } module InclusionTest { diff --git a/javascript/ql/src/semmle/javascript/MembershipCandidates.qll b/javascript/ql/src/semmle/javascript/MembershipCandidates.qll index 89573252ab5d..6d8e4a918dd9 100644 --- a/javascript/ql/src/semmle/javascript/MembershipCandidates.qll +++ b/javascript/ql/src/semmle/javascript/MembershipCandidates.qll @@ -9,27 +9,24 @@ import javascript * * Additional candidates can be added by subclassing `MembershipCandidate::Range` */ -class MembershipCandidate extends DataFlow::Node { - MembershipCandidate::Range range; - - MembershipCandidate() { this = range } +class MembershipCandidate extends DataFlow::Node instanceof MembershipCandidate::Range { /** * Gets the expression that performs the membership test, if any. */ - DataFlow::Node getTest() { result = range.getTest() } + DataFlow::Node getTest() { result = this.(MembershipCandidate::Range).getTest() } /** * Gets a string that this candidate is tested against, if * it can be determined. */ - string getAMemberString() { result = range.getAMemberString() } + string getAMemberString() { result = this.(MembershipCandidate::Range).getAMemberString() } /** * Gets a node that this candidate is tested against, if * it can be determined. */ - DataFlow::Node getAMemberNode() { result = range.getAMemberNode() } + DataFlow::Node getAMemberNode() { result = this.(MembershipCandidate::Range).getAMemberNode() } /** * Gets the polarity of the test. @@ -37,7 +34,7 @@ class MembershipCandidate extends DataFlow::Node { * If the polarity is `false` the test returns `true` if the * collection does not contain this candidate. */ - boolean getTestPolarity() { result = range.getTestPolarity() } + boolean getTestPolarity() { result = this.(MembershipCandidate::Range).getTestPolarity() } } /** diff --git a/javascript/ql/src/semmle/javascript/StringOps.qll b/javascript/ql/src/semmle/javascript/StringOps.qll index 119eea5ebba2..0e44f45616f5 100644 --- a/javascript/ql/src/semmle/javascript/StringOps.qll +++ b/javascript/ql/src/semmle/javascript/StringOps.qll @@ -8,20 +8,17 @@ module StringOps { /** * A expression that is equivalent to `A.startsWith(B)` or `!A.startsWith(B)`. */ - class StartsWith extends DataFlow::Node { - StartsWith::Range range; - - StartsWith() { range = this } + class StartsWith extends DataFlow::Node instanceof StartsWith::Range { /** * Gets the `A` in `A.startsWith(B)`. */ - DataFlow::Node getBaseString() { result = range.getBaseString() } + DataFlow::Node getBaseString() { result = this.(StartsWith::Range).getBaseString() } /** * Gets the `B` in `A.startsWith(B)`. */ - DataFlow::Node getSubstring() { result = range.getSubstring() } + DataFlow::Node getSubstring() { result = this.(StartsWith::Range).getSubstring() } /** * Gets the polarity of the check. @@ -29,7 +26,7 @@ module StringOps { * If the polarity is `false` the check returns `true` if the string does not start * with the given substring. */ - boolean getPolarity() { result = range.getPolarity() } + boolean getPolarity() { result = this.(StartsWith::Range).getPolarity() } } module StartsWith { @@ -237,20 +234,17 @@ module StringOps { /** * An expression that is equivalent to `A.endsWith(B)` or `!A.endsWith(B)`. */ - class EndsWith extends DataFlow::Node { - EndsWith::Range range; - - EndsWith() { this = range } + class EndsWith extends DataFlow::Node instanceof EndsWith::Range { /** * Gets the `A` in `A.startsWith(B)`. */ - DataFlow::Node getBaseString() { result = range.getBaseString() } + DataFlow::Node getBaseString() { result = this.(EndsWith::Range).getBaseString() } /** * Gets the `B` in `A.startsWith(B)`. */ - DataFlow::Node getSubstring() { result = range.getSubstring() } + DataFlow::Node getSubstring() { result = this.(EndsWith::Range).getSubstring() } /** * Gets the polarity if the check. @@ -258,7 +252,7 @@ module StringOps { * If the polarity is `false` the check returns `true` if the string does not end * with the given substring. */ - boolean getPolarity() { result = range.getPolarity() } + boolean getPolarity() { result = this.(EndsWith::Range).getPolarity() } } module EndsWith { @@ -662,10 +656,7 @@ module StringOps { * if (!match) { ... } // <--- 'match' is the RegExpTest * ``` */ - class RegExpTest extends DataFlow::Node { - RegExpTest::Range range; - - RegExpTest() { this = range } + class RegExpTest extends DataFlow::Node instanceof RegExpTest::Range { /** * Gets the AST of the regular expression used in the test, if it can be seen locally. @@ -673,7 +664,7 @@ module StringOps { RegExpTerm getRegExp() { result = getRegExpOperand().getALocalSource().(DataFlow::RegExpCreationNode).getRoot() or - result = range.getRegExpOperand(true).asExpr().(StringLiteral).asRegExp() + result = this.(RegExpTest::Range).getRegExpOperand(true).asExpr().(StringLiteral).asRegExp() } /** @@ -681,12 +672,12 @@ module StringOps { * * In some cases this represents a string value being coerced to a RegExp object. */ - DataFlow::Node getRegExpOperand() { result = range.getRegExpOperand(_) } + DataFlow::Node getRegExpOperand() { result = this.(RegExpTest::Range).getRegExpOperand(_) } /** * Gets the data flow node corresponding to the string being tested against the regular expression. */ - DataFlow::Node getStringOperand() { result = range.getStringOperand() } + DataFlow::Node getStringOperand() { result = this.(RegExpTest::Range).getStringOperand() } /** * Gets the return value indicating that the string matched the regular expression. @@ -694,7 +685,7 @@ module StringOps { * For example, for `regexp.exec(str) == null`, the polarity is `false`, and for * `regexp.exec(str) != null` the polarity is `true`. */ - boolean getPolarity() { result = range.getPolarity() } + boolean getPolarity() { result = this.(RegExpTest::Range).getPolarity() } } /** diff --git a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll index 19fe93da259b..561f93867f18 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll @@ -701,13 +701,10 @@ class ArrayCreationNode extends DataFlow::ValueNode, DataFlow::SourceNode { * define(["fs"], function(fs) { ... }); // AMD module * ``` */ -class ModuleImportNode extends DataFlow::SourceNode { - ModuleImportNode::Range range; - - ModuleImportNode() { this = range } +class ModuleImportNode extends DataFlow::SourceNode instanceof ModuleImportNode::Range { /** Gets the path of the imported module. */ - string getPath() { result = range.getPath() } + string getPath() { result = this.(ModuleImportNode::Range).getPath() } } module ModuleImportNode { @@ -843,25 +840,22 @@ module MemberKind { * * Additional patterns can be recognized as class nodes, by extending `DataFlow::ClassNode::Range`. */ -class ClassNode extends DataFlow::SourceNode { - ClassNode::Range impl; - - ClassNode() { this = impl } +class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range { /** * Gets the unqualified name of the class, if it has one or one can be determined from the context. */ - string getName() { result = impl.getName() } + string getName() { result = this.(ClassNode::Range).getName() } /** * Gets a description of the class. */ - string describe() { result = impl.describe() } + string describe() { result = this.(ClassNode::Range).describe() } /** * Gets the constructor function of this class. */ - FunctionNode getConstructor() { result = impl.getConstructor() } + FunctionNode getConstructor() { result = this.(ClassNode::Range).getConstructor() } /** * Gets an instance method declared in this class, with the given name, if any. @@ -869,7 +863,7 @@ class ClassNode extends DataFlow::SourceNode { * Does not include methods from superclasses. */ FunctionNode getInstanceMethod(string name) { - result = impl.getInstanceMember(name, MemberKind::method()) + result = this.(ClassNode::Range).getInstanceMember(name, MemberKind::method()) } /** @@ -879,7 +873,9 @@ class ClassNode extends DataFlow::SourceNode { * * Does not include methods from superclasses. */ - FunctionNode getAnInstanceMethod() { result = impl.getAnInstanceMember(MemberKind::method()) } + FunctionNode getAnInstanceMethod() { + result = this.(ClassNode::Range).getAnInstanceMember(MemberKind::method()) + } /** * Gets the instance method, getter, or setter with the given name and kind. @@ -887,7 +883,7 @@ class ClassNode extends DataFlow::SourceNode { * Does not include members from superclasses. */ FunctionNode getInstanceMember(string name, MemberKind kind) { - result = impl.getInstanceMember(name, kind) + result = this.(ClassNode::Range).getInstanceMember(name, kind) } /** @@ -895,31 +891,35 @@ class ClassNode extends DataFlow::SourceNode { * * Does not include members from superclasses. */ - FunctionNode getAnInstanceMember(MemberKind kind) { result = impl.getAnInstanceMember(kind) } + FunctionNode getAnInstanceMember(MemberKind kind) { + result = this.(ClassNode::Range).getAnInstanceMember(kind) + } /** * Gets an instance method, getter, or setter declared in this class. * * Does not include members from superclasses. */ - FunctionNode getAnInstanceMember() { result = impl.getAnInstanceMember(_) } + FunctionNode getAnInstanceMember() { result = this.(ClassNode::Range).getAnInstanceMember(_) } /** * Gets the static method declared in this class with the given name. */ - FunctionNode getStaticMethod(string name) { result = impl.getStaticMethod(name) } + FunctionNode getStaticMethod(string name) { + result = this.(ClassNode::Range).getStaticMethod(name) + } /** * Gets a static method declared in this class. * * The constructor is not considered a static method. */ - FunctionNode getAStaticMethod() { result = impl.getAStaticMethod() } + FunctionNode getAStaticMethod() { result = this.(ClassNode::Range).getAStaticMethod() } /** * Gets a dataflow node that refers to the superclass of this class. */ - DataFlow::Node getASuperClassNode() { result = impl.getASuperClassNode() } + DataFlow::Node getASuperClassNode() { result = this.(ClassNode::Range).getASuperClassNode() } /** * Gets a direct super class of this class. @@ -1065,13 +1065,13 @@ class ClassNode extends DataFlow::SourceNode { * Gets the type annotation for the field `fieldName`, if any. */ TypeAnnotation getFieldTypeAnnotation(string fieldName) { - result = impl.getFieldTypeAnnotation(fieldName) + result = this.(ClassNode::Range).getFieldTypeAnnotation(fieldName) } /** * Gets a decorator applied to this class. */ - DataFlow::Node getADecorator() { result = impl.getADecorator() } + DataFlow::Node getADecorator() { result = this.(ClassNode::Range).getADecorator() } } module ClassNode { @@ -1357,10 +1357,7 @@ module ClassNode { * _.partial(fn, x, y, z) * ``` */ -class PartialInvokeNode extends DataFlow::Node { - PartialInvokeNode::Range range; - - PartialInvokeNode() { this = range } +class PartialInvokeNode extends DataFlow::Node instanceof PartialInvokeNode::Range { /** Gets a node holding a callback invoked by this partial invocation node. */ DataFlow::Node getACallbackNode() { @@ -1373,26 +1370,26 @@ class PartialInvokeNode extends DataFlow::Node { * Holds if `argument` is passed as argument `index` to the function in `callback`. */ predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) { - range.isPartialArgument(callback, argument, index) + this.(PartialInvokeNode::Range).isPartialArgument(callback, argument, index) } /** * Gets a node referring to a bound version of `callback` with `boundArgs` arguments bound. */ DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) { - result = range.getBoundFunction(callback, boundArgs) + result = this.(PartialInvokeNode::Range).getBoundFunction(callback, boundArgs) } /** * Gets the node holding the receiver to be passed to the bound function, if specified. */ - DataFlow::Node getBoundReceiver() { result = range.getBoundReceiver(_) } + DataFlow::Node getBoundReceiver() { result = this.(PartialInvokeNode::Range).getBoundReceiver(_) } /** * Gets the node holding the receiver to be passed to the bound function, if specified. */ DataFlow::Node getBoundReceiver(DataFlow::Node callback) { - result = range.getBoundReceiver(callback) + result = this.(PartialInvokeNode::Range).getBoundReceiver(callback) } } diff --git a/javascript/ql/src/semmle/javascript/frameworks/Cheerio.qll b/javascript/ql/src/semmle/javascript/frameworks/Cheerio.qll index b9705aebfbdd..beffe148ee3b 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Cheerio.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Cheerio.qll @@ -32,10 +32,7 @@ module Cheerio { * Creation of `cheerio` object, a collection of virtual DOM elements * with an interface similar to that of a jQuery object. */ - class CheerioObjectCreation extends DataFlow::SourceNode { - CheerioObjectCreation::Range range; - - CheerioObjectCreation() { this = range } + class CheerioObjectCreation extends DataFlow::SourceNode instanceof CheerioObjectCreation::Range { } module CheerioObjectCreation { diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll index 451ad3f24d22..151c7eea11c6 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll @@ -18,25 +18,22 @@ import javascript * To model additional APIs, extend `ClientRequest::Range` and implement its abstract member * predicates. */ -class ClientRequest extends DataFlow::InvokeNode { - ClientRequest::Range self; - - ClientRequest() { this = self } +class ClientRequest extends DataFlow::InvokeNode instanceof ClientRequest::Range { /** * Gets the URL of the request. */ - DataFlow::Node getUrl() { result = self.getUrl() } + DataFlow::Node getUrl() { result = this.(ClientRequest::Range).getUrl() } /** * Gets the host of the request. */ - DataFlow::Node getHost() { result = self.getHost() } + DataFlow::Node getHost() { result = this.(ClientRequest::Range).getHost() } /** * Gets a node that contributes to the data-part this request. */ - DataFlow::Node getADataNode() { result = self.getADataNode() } + DataFlow::Node getADataNode() { result = this.(ClientRequest::Range).getADataNode() } /** * Gets a data flow node that refers to some representation of the response, possibly @@ -60,7 +57,7 @@ class ClientRequest extends DataFlow::InvokeNode { * - Any value provided by custom implementations of `ClientRequest::Range`. */ DataFlow::Node getAResponseDataNode(string responseType, boolean promise) { - result = self.getAResponseDataNode(responseType, promise) + result = this.(ClientRequest::Range).getAResponseDataNode(responseType, promise) } /** @@ -72,7 +69,7 @@ class ClientRequest extends DataFlow::InvokeNode { /** * Gets a data-flow node that determines where in the file-system the result of the request should be saved. */ - DataFlow::Node getASavePath() { result = self.getASavePath() } + DataFlow::Node getASavePath() { result = this.(ClientRequest::Range).getASavePath() } } deprecated class CustomClientRequest = ClientRequest::Range; diff --git a/javascript/ql/src/semmle/javascript/frameworks/ComposedFunctions.qll b/javascript/ql/src/semmle/javascript/frameworks/ComposedFunctions.qll index 8da2286ad792..89bd7942e2be 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/ComposedFunctions.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/ComposedFunctions.qll @@ -8,10 +8,7 @@ import javascript * A call to a function that constructs a function composition `f(g(h(...)))` from a * series functions `f, g, h, ...`. */ -class FunctionCompositionCall extends DataFlow::CallNode { - FunctionCompositionCall::Range range; - - FunctionCompositionCall() { this = range } +class FunctionCompositionCall extends DataFlow::CallNode instanceof FunctionCompositionCall::Range { /** * Gets the `i`th function in the composition `f(g(h(...)))`, counting from left to right. @@ -19,7 +16,9 @@ class FunctionCompositionCall extends DataFlow::CallNode { * Note that this is the opposite of the order in which the function are invoked, * that is, `g` occurs later than `f` in `f(g(...))` but is invoked before `f`. */ - DataFlow::Node getOperandNode(int i) { result = range.getOperandNode(i) } + DataFlow::Node getOperandNode(int i) { + result = this.(FunctionCompositionCall::Range).getOperandNode(i) + } /** Gets a node holding one of the functions to be composed. */ final DataFlow::Node getAnOperandNode() { result = getOperandNode(_) } @@ -38,7 +37,7 @@ class FunctionCompositionCall extends DataFlow::CallNode { final DataFlow::Node getAnOperandFunction() { result = getOperandFunction(_) } /** Gets the number of functions being composed. */ - int getNumOperand() { result = range.getNumOperand() } + int getNumOperand() { result = this.(FunctionCompositionCall::Range).getNumOperand() } } /** diff --git a/javascript/ql/src/semmle/javascript/frameworks/Electron.qll b/javascript/ql/src/semmle/javascript/frameworks/Electron.qll index 7d0999327389..168e9c1bc9ab 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Electron.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Electron.qll @@ -181,8 +181,7 @@ module Electron { /** * A Node.js-style HTTP or HTTPS request made using an Electron module. */ - class ElectronClientRequest extends NodeJSLib::NodeJSClientRequest { - override ElectronClientRequest::Range self; + class ElectronClientRequest extends NodeJSLib::NodeJSClientRequest instanceof ElectronClientRequest::Range { } module ElectronClientRequest { diff --git a/javascript/ql/src/semmle/javascript/frameworks/EventEmitter.qll b/javascript/ql/src/semmle/javascript/frameworks/EventEmitter.qll index f044d69524df..2c9bf02673f4 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/EventEmitter.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/EventEmitter.qll @@ -68,40 +68,40 @@ module EventEmitter { * An EventEmitter instance that implements the EventEmitter API. * Extend EventEmitter::Range to mark something as being an EventEmitter. */ -class EventEmitter extends DataFlow::Node { - EventEmitter::Range range; - - EventEmitter() { this = range } +class EventEmitter extends DataFlow::Node instanceof EventEmitter::Range { } /** * A registration of an event handler on an EventEmitter. */ -class EventRegistration extends DataFlow::Node { - EventRegistration::Range range; - - EventRegistration() { this = range } +class EventRegistration extends DataFlow::Node instanceof EventRegistration::Range { /** Gets the EventEmitter that the event handler is registered on. */ - final EventEmitter getEmitter() { result = range.getEmitter() } + final EventEmitter getEmitter() { result = this.(EventRegistration::Range).getEmitter() } /** Gets the name of the channel if possible. */ - string getChannel() { result = range.getChannel() } + string getChannel() { result = this.(EventRegistration::Range).getChannel() } /** Gets the `i`th parameter in the event handler. */ - DataFlow::Node getReceivedItem(int i) { result = range.getReceivedItem(i) } + DataFlow::Node getReceivedItem(int i) { + result = this.(EventRegistration::Range).getReceivedItem(i) + } /** * Gets a value that is returned by the event handler. * The default implementation is that no value can be returned. */ - DataFlow::Node getAReturnedValue() { result = range.getAReturnedValue() } + DataFlow::Node getAReturnedValue() { + result = this.(EventRegistration::Range).getAReturnedValue() + } /** * Get a dispatch that this event handler can return a value to. * The default implementation is that there exists no such dispatch. */ - EventDispatch getAReturnDispatch() { result = range.getAReturnDispatch() } + EventDispatch getAReturnDispatch() { + result = this.(EventRegistration::Range).getAReturnDispatch() + } } module EventRegistration { @@ -140,26 +140,23 @@ module EventRegistration { /** * A dispatch of an event on an EventEmitter. */ -class EventDispatch extends DataFlow::Node { - EventDispatch::Range range; - - EventDispatch() { this = range } +class EventDispatch extends DataFlow::Node instanceof EventDispatch::Range { /** Gets the emitter that the event dispatch happens on. */ - EventEmitter getEmitter() { result = range.getEmitter() } + EventEmitter getEmitter() { result = this.(EventDispatch::Range).getEmitter() } /** Gets the name of the channel if possible. */ - string getChannel() { result = range.getChannel() } + string getChannel() { result = this.(EventDispatch::Range).getChannel() } /** Gets the `i`th argument that is send to the event handler. */ - DataFlow::Node getSentItem(int i) { result = range.getSentItem(i) } + DataFlow::Node getSentItem(int i) { result = this.(EventDispatch::Range).getSentItem(i) } /** * Get an EventRegistration that this event dispatch can send an event to. * The default implementation is that the emitters of the dispatch and registration have to be equal. * Channels are by default ignored. */ - EventRegistration getAReceiver() { result = range.getAReceiver() } + EventRegistration getAReceiver() { result = this.(EventDispatch::Range).getAReceiver() } } module EventDispatch { diff --git a/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll b/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll index 9475c32eeab2..bdedce9cefc9 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll @@ -540,16 +540,13 @@ module HTTP { /** * An object that contains one or more potential route handlers. */ - class RouteHandlerCandidateContainer extends DataFlow::Node { - RouteHandlerCandidateContainer::Range self; - - RouteHandlerCandidateContainer() { this = self } + class RouteHandlerCandidateContainer extends DataFlow::Node instanceof RouteHandlerCandidateContainer::Range { /** * Gets the route handler in this container that is accessed at `access`. */ DataFlow::SourceNode getRouteHandler(DataFlow::SourceNode access) { - result = self.getRouteHandler(access) + result = this.(RouteHandlerCandidateContainer::Range).getRouteHandler(access) } } diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll index 840e9ea9b785..04ed6c09c72c 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll @@ -831,8 +831,7 @@ module NodeJSLib { * A data flow node that is an HTTP or HTTPS client request made by a Node.js application, * for example `http.request(url)`. */ - class NodeJSClientRequest extends ClientRequest { - override NodeJSClientRequest::Range self; + class NodeJSClientRequest extends ClientRequest instanceof NodeJSClientRequest::Range { } module NodeJSClientRequest { diff --git a/javascript/ql/src/semmle/javascript/frameworks/PropertyProjection.qll b/javascript/ql/src/semmle/javascript/frameworks/PropertyProjection.qll index e3fe62be1642..c7d79a6ee9de 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/PropertyProjection.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/PropertyProjection.qll @@ -14,20 +14,17 @@ import javascript * To model additional APIs, extend `PropertyProjection::Range` and implement its abstract member * predicates. */ -class PropertyProjection extends DataFlow::CallNode { - PropertyProjection::Range self; - - PropertyProjection() { this = self } +class PropertyProjection extends DataFlow::CallNode instanceof PropertyProjection::Range { /** * Gets the argument for the object to project properties from, such as `o` in `_.get(o, 'a.b')`. */ - DataFlow::Node getObject() { result = self.getObject() } + DataFlow::Node getObject() { result = this.(PropertyProjection::Range).getObject() } /** * Gets an argument that selects the properties to project, such as `'a.b'` in `_.get(o, 'a.b')`. */ - DataFlow::Node getASelector() { result = self.getASelector() } + DataFlow::Node getASelector() { result = this.(PropertyProjection::Range).getASelector() } /** * Holds if this call returns the value of a single projected property, as opposed to an object that can contain multiple projected properties. @@ -36,7 +33,7 @@ class PropertyProjection extends DataFlow::CallNode { * - This predicate holds for `_.get({a: 'b'}, 'a')`, which returns `'b'`, * - This predicate does not hold for `_.pick({a: 'b', c: 'd'}}, 'a')`, which returns `{a: 'b'}`, */ - predicate isSingletonProjection() { self.isSingletonProjection() } + predicate isSingletonProjection() { this.(PropertyProjection::Range).isSingletonProjection() } } module PropertyProjection { diff --git a/javascript/ql/src/semmle/javascript/frameworks/Redux.qll b/javascript/ql/src/semmle/javascript/frameworks/Redux.qll index ad3f985c3978..c87a273b0bda 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Redux.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Redux.qll @@ -56,10 +56,7 @@ module Redux { /** * Creation of a redux store, usually via a call to `createStore`. */ - class StoreCreation extends DataFlow::SourceNode { - StoreCreation::Range range; - - StoreCreation() { this = range } + class StoreCreation extends DataFlow::SourceNode instanceof StoreCreation::Range { /** Gets a reference to the store. */ DataFlow::SourceNode ref() { result = asApiNode().getAUse() } @@ -68,7 +65,7 @@ module Redux { API::Node asApiNode() { result.getAnImmediateUse() = this } /** Gets the data flow node holding the root reducer for this store. */ - DataFlow::Node getReducerArg() { result = range.getReducerArg() } + DataFlow::Node getReducerArg() { result = this.(StoreCreation::Range).getReducerArg() } /** Gets a data flow node referring to the root reducer. */ DataFlow::SourceNode getAReducerSource() { result = getReducerArg().(ReducerArg).getASource() } @@ -423,13 +420,10 @@ module Redux { * Some action creators dispatch the action to a store, while for others, the value is returned and it is simply assumed to be dispatched * at some point. We model all action creators as if they dispatch the action they create. */ - class ActionCreator extends DataFlow::SourceNode { - ActionCreator::Range range; - - ActionCreator() { this = range } + class ActionCreator extends DataFlow::SourceNode instanceof ActionCreator::Range { /** Gets the `type` property of actions created by this action creator, if it is known. */ - string getTypeTag() { result = range.getTypeTag() } + string getTypeTag() { result = this.(ActionCreator::Range).getTypeTag() } /** * Gets the middleware function that transforms arguments passed to this function into the @@ -442,7 +436,7 @@ module Redux { * the action payload. Otherwise, the return value is the payload itself. */ DataFlow::FunctionNode getMiddlewareFunction(boolean async) { - result = range.getMiddlewareFunction(async) + result = this.(ActionCreator::Range).getMiddlewareFunction(async) } /** Gets a data flow node referring to this action creator. */ diff --git a/javascript/ql/src/semmle/javascript/frameworks/ShellJS.qll b/javascript/ql/src/semmle/javascript/frameworks/ShellJS.qll index 3fc1644fdfd3..16dd035c0178 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/ShellJS.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/ShellJS.qll @@ -14,13 +14,10 @@ module ShellJS { } /** A member of the `shelljs` library. */ - class Member extends DataFlow::SourceNode { - Member::Range range; - - Member() { this = range } + class Member extends DataFlow::SourceNode instanceof Member::Range { /** Gets the name of `shelljs` member being referenced, such as `cat` in `shelljs.cat`. */ - string getName() { result = range.getName() } + string getName() { result = this.(Member::Range).getName() } } module Member {