diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll index 192d2e6faa4..d88dab4d431 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll @@ -1262,6 +1262,12 @@ module ClassNode { result.getFile() = f } + pragma[nomagic] + private DataFlow::NewNode getAnInstantiationInFile(string name, File f) { + result = AccessPath::getAReferenceTo(name).(DataFlow::LocalSourceNode).getAnInstantiation() and + result.getFile() = f + } + /** * Gets a reference to the function `func`, where there exists a read/write of the "prototype" property on that reference. */ @@ -1273,7 +1279,7 @@ module ClassNode { } /** - * A function definition with prototype manipulation as a `ClassNode` instance. + * A function definition, targeted by a `new`-call or with prototype manipulation, seen as a `ClassNode` instance. */ class FunctionStyleClass extends Range, DataFlow::ValueNode { override Function astNode; @@ -1284,9 +1290,12 @@ module ClassNode { ( exists(getAFunctionValueWithPrototype(function)) or - exists(string name | - this = AccessPath::getAnAssignmentTo(name) and + function = any(NewNode new).getCalleeNode().analyze().getAValue() + or + exists(string name | this = AccessPath::getAnAssignmentTo(name) | exists(getAPrototypeReferenceInFile(name, this.getFile())) + or + exists(getAnInstantiationInFile(name, this.getFile())) ) ) } diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll index 8ee507f0f98..682c9a2dffa 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll @@ -249,7 +249,13 @@ module CallGraph { or result = node.(DataFlow::ObjectLiteralNode).getPropertySetter(_) ) and - not node.getTopLevel().isExterns() + not node.getTopLevel().isExterns() and + // Do not track instance methods on classes + not exists(DataFlow::ClassNode cls | + node = cls.getConstructor().getReceiver() + or + node = cls.(DataFlow::ClassNode::FunctionStyleClass).getAPrototypeReference() + ) } private predicate shouldTrackObjectWithMethods(DataFlow::SourceNode node) {