Merge pull request #15823 from asgerf/js/lift-cg-restriction

JS: Call graph improvements
This commit is contained in:
Asger F
2024-03-08 13:40:38 +01:00
committed by GitHub
4 changed files with 39 additions and 12 deletions

View File

@@ -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()))
)
)
}

View File

@@ -241,24 +241,25 @@ module CallGraph {
)
}
private DataFlow::FunctionNode getAMethodOnPlainObject(DataFlow::SourceNode node) {
private DataFlow::FunctionNode getAMethodOnObject(DataFlow::SourceNode node) {
(
(
node instanceof DataFlow::ObjectLiteralNode
or
node instanceof DataFlow::FunctionNode
) and
result = node.getAPropertySource()
or
result = node.(DataFlow::ObjectLiteralNode).getPropertyGetter(_)
or
result = node.(DataFlow::ObjectLiteralNode).getPropertySetter(_)
) and
not node.getTopLevel().isExterns()
not node.getTopLevel().isExterns() and
// Ignore writes to `this` inside a constructor, since this is already handled by instance method tracking
not exists(DataFlow::ClassNode cls |
node = cls.getConstructor().getReceiver()
or
node = cls.(DataFlow::ClassNode::FunctionStyleClass).getAPrototypeReference()
)
}
private predicate shouldTrackObjectWithMethods(DataFlow::SourceNode node) {
exists(getAMethodOnPlainObject(node))
exists(getAMethodOnObject(node))
}
/**
@@ -292,7 +293,7 @@ module CallGraph {
predicate impliedReceiverStep(DataFlow::SourceNode pred, DataFlow::SourceNode succ) {
exists(DataFlow::SourceNode host |
pred = getAnAllocationSiteRef(host) and
succ = getAMethodOnPlainObject(host).getReceiver()
succ = getAMethodOnObject(host).getReceiver()
)
}
}