JS: Resolve calls downward in the class hierarchy

This commit is contained in:
Asger F
2025-02-14 11:15:42 +01:00
parent aff458d948
commit b8b2b9a470
2 changed files with 34 additions and 9 deletions

View File

@@ -1066,6 +1066,32 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
result = this.getAnInstanceReference(DataFlow::TypeTracker::end()) result = this.getAnInstanceReference(DataFlow::TypeTracker::end())
} }
pragma[nomagic]
private DataFlow::PropRead getAnOwnInstanceMemberAccess(string name, DataFlow::TypeTracker t) {
result = this.getAnInstanceReference(t.continue()).getAPropertyRead(name)
}
pragma[nomagic]
private DataFlow::PropRead getAnInstanceMemberAccessOnSubClass(
string name, DataFlow::TypeTracker t
) {
exists(DataFlow::ClassNode subclass |
subclass = this.getADirectSubClass() and
not exists(subclass.getInstanceMember(name, _))
|
result = subclass.getAnOwnInstanceMemberAccess(name, t)
or
result = subclass.getAnInstanceMemberAccessOnSubClass(name, t)
)
}
pragma[nomagic]
private DataFlow::PropRead getAnInstanceMemberAccessOnSuperClass(string name) {
result = this.getADirectSuperClass().getAReceiverNode().getAPropertyRead(name)
or
result = this.getADirectSuperClass().getAnInstanceMemberAccessOnSuperClass(name)
}
/** /**
* Gets a property read that accesses the property `name` on an instance of this class. * Gets a property read that accesses the property `name` on an instance of this class.
* *
@@ -1073,13 +1099,12 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
*/ */
pragma[nomagic] pragma[nomagic]
DataFlow::PropRead getAnInstanceMemberAccess(string name, DataFlow::TypeTracker t) { DataFlow::PropRead getAnInstanceMemberAccess(string name, DataFlow::TypeTracker t) {
result = this.getAnInstanceReference(t.continue()).getAPropertyRead(name) result = this.getAnOwnInstanceMemberAccess(name, t)
or or
exists(DataFlow::ClassNode subclass | result = this.getAnInstanceMemberAccessOnSubClass(name, t)
result = subclass.getAnInstanceMemberAccess(name, t) and or
not exists(subclass.getInstanceMember(name, _)) and t.start() and
this = subclass.getADirectSuperClass() result = this.getAnInstanceMemberAccessOnSuperClass(name)
)
} }
/** /**

View File

@@ -5,16 +5,16 @@ class Base {
/** calls:methodInBase */ /** calls:methodInBase */
this.methodInBase(); this.methodInBase();
/** calls:NONE */ /** calls:methodInSub1 calls:methodInSub2 */
this.methodInSub(); this.methodInSub();
/** calls:overridenInSub0 */ /** calls:overridenInSub0 calls:overridenInSub1 calls:overridenInSub2 */
this.overridenInSub(); this.overridenInSub();
} }
/** name:methodInBase */ /** name:methodInBase */
methodInBase() { methodInBase() {
/** calls:NONE */ /** calls:methodInSub1 calls:methodInSub2 */
this.methodInSub(); this.methodInSub();
} }