Skip to content

Commit 5b2df06

Browse files
author
Max Schaefer
authored
Merge pull request #921 from asger-semmle/class-node-absval
JS: use type inference to back up function-style classes
2 parents ca6f145 + 74a9c4b commit 5b2df06

File tree

4 files changed

+25
-9
lines changed

4 files changed

+25
-9
lines changed

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

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -725,8 +725,15 @@ module ClassNode {
725725
*/
726726
class FunctionStyleClass extends Range, DataFlow::ValueNode {
727727
override Function astNode;
728+
AbstractFunction function;
728729

729-
FunctionStyleClass() { exists(getAPropertyReference("prototype")) }
730+
FunctionStyleClass() {
731+
function.getFunction() = astNode and
732+
exists (DataFlow::PropRef read |
733+
read.getPropertyName() = "prototype" and
734+
read.getBase().analyze().getAValue() = function
735+
)
736+
}
730737

731738
override string getName() { result = astNode.getName() }
732739

@@ -775,14 +782,16 @@ module ClassNode {
775782
/**
776783
* Gets a reference to the prototype of this class.
777784
*/
778-
private DataFlow::SourceNode getAPrototypeReference() {
779-
result = getAPropertyRead("prototype")
780-
or
781-
result = getAPropertySource("prototype")
782-
or
783-
exists(ExtendCall call |
784-
call.getDestinationOperand() = getAPropertyRead("prototype") and
785-
result = call.getASourceOperand()
785+
DataFlow::SourceNode getAPrototypeReference() {
786+
exists (DataFlow::SourceNode base | base.analyze().getAValue() = function |
787+
result = base.getAPropertyRead("prototype")
788+
or
789+
result = base.getAPropertySource("prototype")
790+
or
791+
exists(ExtendCall call |
792+
call.getDestinationOperand() = base.getAPropertyRead("prototype") and
793+
result = call.getASourceOperand()
794+
)
786795
)
787796
}
788797

javascript/ql/test/library-tests/ClassNode/InstanceMember.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
| namespace.js:5:32:5:44 | function() {} | Baz.method | method |
12
| tst.js:4:17:4:21 | () {} | A.instanceMethod | method |
23
| tst.js:7:6:7:10 | () {} | A.bar | method |
34
| tst.js:9:10:9:14 | () {} | A.baz | getter |

javascript/ql/test/library-tests/ClassNode/InstanceMethod.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
| namespace.js:5:32:5:44 | function() {} | Baz.method |
12
| tst.js:4:17:4:21 | () {} | A.instanceMethod |
23
| tst.js:7:6:7:10 | () {} | A.bar |
34
| tst.js:17:19:17:31 | function() {} | B.foo |
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
goog.provide('foo.bar.baz');
2+
3+
foo.bar.baz = function Baz() {};
4+
5+
foo.bar.baz.prototype.method = function() {};

0 commit comments

Comments
 (0)