Skip to content

Commit b8b2b9a

Browse files
committed
JS: Resolve calls downward in the class hierarchy
1 parent aff458d commit b8b2b9a

File tree

2 files changed

+34
-9
lines changed

2 files changed

+34
-9
lines changed

javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,20 +1066,45 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
10661066
result = this.getAnInstanceReference(DataFlow::TypeTracker::end())
10671067
}
10681068

1069+
pragma[nomagic]
1070+
private DataFlow::PropRead getAnOwnInstanceMemberAccess(string name, DataFlow::TypeTracker t) {
1071+
result = this.getAnInstanceReference(t.continue()).getAPropertyRead(name)
1072+
}
1073+
1074+
pragma[nomagic]
1075+
private DataFlow::PropRead getAnInstanceMemberAccessOnSubClass(
1076+
string name, DataFlow::TypeTracker t
1077+
) {
1078+
exists(DataFlow::ClassNode subclass |
1079+
subclass = this.getADirectSubClass() and
1080+
not exists(subclass.getInstanceMember(name, _))
1081+
|
1082+
result = subclass.getAnOwnInstanceMemberAccess(name, t)
1083+
or
1084+
result = subclass.getAnInstanceMemberAccessOnSubClass(name, t)
1085+
)
1086+
}
1087+
1088+
pragma[nomagic]
1089+
private DataFlow::PropRead getAnInstanceMemberAccessOnSuperClass(string name) {
1090+
result = this.getADirectSuperClass().getAReceiverNode().getAPropertyRead(name)
1091+
or
1092+
result = this.getADirectSuperClass().getAnInstanceMemberAccessOnSuperClass(name)
1093+
}
1094+
10691095
/**
10701096
* Gets a property read that accesses the property `name` on an instance of this class.
10711097
*
10721098
* Concretely, this holds when the base is an instance of this class or a subclass thereof.
10731099
*/
10741100
pragma[nomagic]
10751101
DataFlow::PropRead getAnInstanceMemberAccess(string name, DataFlow::TypeTracker t) {
1076-
result = this.getAnInstanceReference(t.continue()).getAPropertyRead(name)
1102+
result = this.getAnOwnInstanceMemberAccess(name, t)
10771103
or
1078-
exists(DataFlow::ClassNode subclass |
1079-
result = subclass.getAnInstanceMemberAccess(name, t) and
1080-
not exists(subclass.getInstanceMember(name, _)) and
1081-
this = subclass.getADirectSuperClass()
1082-
)
1104+
result = this.getAnInstanceMemberAccessOnSubClass(name, t)
1105+
or
1106+
t.start() and
1107+
result = this.getAnInstanceMemberAccessOnSuperClass(name)
10831108
}
10841109

10851110
/**

javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/subclasses.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@ class Base {
55
/** calls:methodInBase */
66
this.methodInBase();
77

8-
/** calls:NONE */
8+
/** calls:methodInSub1 calls:methodInSub2 */
99
this.methodInSub();
1010

11-
/** calls:overridenInSub0 */
11+
/** calls:overridenInSub0 calls:overridenInSub1 calls:overridenInSub2 */
1212
this.overridenInSub();
1313
}
1414

1515
/** name:methodInBase */
1616
methodInBase() {
17-
/** calls:NONE */
17+
/** calls:methodInSub1 calls:methodInSub2 */
1818
this.methodInSub();
1919
}
2020

0 commit comments

Comments
 (0)