Skip to content

Commit cd84fa4

Browse files
committed
JS: Make getInstance() propagate to subclasses
1 parent a8dac17 commit cd84fa4

File tree

4 files changed

+39
-0
lines changed

4 files changed

+39
-0
lines changed

javascript/ql/lib/semmle/javascript/ApiGraphs.qll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,17 @@ module API {
891891
(propDesc = Promises::errorProp() or propDesc = "")
892892
}
893893

894+
pragma[nomagic]
895+
private DataFlow::ClassNode getALocalSubclass(DataFlow::SourceNode node) {
896+
result.getASuperClassNode().getALocalSource() = node
897+
}
898+
899+
bindingset[node]
900+
pragma[inline_late]
901+
private DataFlow::ClassNode getALocalSubclassFwd(DataFlow::SourceNode node) {
902+
result = getALocalSubclass(node)
903+
}
904+
894905
/**
895906
* Holds if `ref` is a use of a node that should have an incoming edge from `base` labeled
896907
* `lbl` in the API graph.
@@ -927,6 +938,15 @@ module API {
927938
or
928939
lbl = Label::forwardingFunction() and
929940
DataFlow::functionForwardingStep(pred.getALocalUse(), ref)
941+
or
942+
exists(DataFlow::ClassNode cls |
943+
lbl = Label::instance() and
944+
cls = getALocalSubclassFwd(pred).getADirectSubClass*()
945+
|
946+
ref = cls.getAReceiverNode()
947+
or
948+
ref = cls.getAClassReference().getAnInstantiation()
949+
)
930950
)
931951
or
932952
exists(DataFlow::Node def, DataFlow::FunctionNode fn |

javascript/ql/test/library-tests/frameworks/data/test.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ taintFlow
7474
| test.js:249:28:249:35 | source() | test.js:249:28:249:35 | source() |
7575
| test.js:252:15:252:22 | source() | test.js:252:15:252:22 | source() |
7676
| test.js:254:32:254:39 | source() | test.js:254:32:254:39 | source() |
77+
| test.js:262:10:262:31 | this.ba ... ource() | test.js:262:10:262:31 | this.ba ... ource() |
78+
| test.js:265:6:265:39 | new MyS ... ource() | test.js:265:6:265:39 | new MyS ... ource() |
79+
| test.js:269:10:269:31 | this.ba ... ource() | test.js:269:10:269:31 | this.ba ... ource() |
80+
| test.js:272:6:272:40 | new MyS ... ource() | test.js:272:6:272:40 | new MyS ... ource() |
7781
isSink
7882
| test.js:54:18:54:25 | source() | test-sink |
7983
| test.js:55:22:55:29 | source() | test-sink |

javascript/ql/test/library-tests/frameworks/data/test.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,3 +256,17 @@ function fuzzy() {
256256
fuzzyCall(source()); // OK - does not come from 'testlib'
257257
require('blah').fuzzyCall(source()); // OK - does not come from 'testlib'
258258
}
259+
260+
class MySubclass extends testlib.BaseClass {
261+
foo() {
262+
sink(this.baseclassSource()); // NOT OK
263+
}
264+
}
265+
sink(new MySubclass().baseclassSource()); // NOT OK
266+
267+
class MySubclass2 extends MySubclass {
268+
foo2() {
269+
sink(this.baseclassSource()); // NOT OK
270+
}
271+
}
272+
sink(new MySubclass2().baseclassSource()); // NOT OK

javascript/ql/test/library-tests/frameworks/data/test.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class Sources extends ModelInput::SourceModelCsv {
8080
"testlib;Member[ParamDecoratorSource].DecoratedParameter;test-source",
8181
"testlib;Member[MethodDecorator].DecoratedMember.Parameter[0];test-source",
8282
"testlib;Member[MethodDecoratorWithArgs].ReturnValue.DecoratedMember.Parameter[0];test-source",
83+
"testlib;Member[BaseClass].Instance.Member[baseclassSource].ReturnValue;test-source",
8384
]
8485
}
8586
}

0 commit comments

Comments
 (0)