Skip to content

Commit bc88c41

Browse files
authored
Merge pull request #2668 from erik-krogh/MoreEvents
Approved by esbena
2 parents d5daee4 + 569ee8f commit bc88c41

File tree

3 files changed

+55
-6
lines changed

3 files changed

+55
-6
lines changed

javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -894,17 +894,52 @@ module NodeJSLib {
894894
DataFlow::SourceNode ref() { result = EventEmitter::trackEventEmitter(this) }
895895
}
896896

897+
/**
898+
* Gets an import of the NodeJS EventEmitter.
899+
*/
900+
private DataFlow::SourceNode getAnEventEmitterImport() {
901+
result = DataFlow::moduleImport("events") or
902+
result = DataFlow::moduleMember("events", "EventEmitter")
903+
}
904+
897905
/**
898906
* An instance of an EventEmitter that is imported through the 'events' module.
899907
*/
900908
private class ImportedNodeJSEventEmitter extends NodeJSEventEmitter {
901909
ImportedNodeJSEventEmitter() {
902-
exists(DataFlow::SourceNode clazz |
903-
clazz = DataFlow::moduleImport("events") or
904-
clazz = DataFlow::moduleMember("events", "EventEmitter")
905-
|
906-
this = clazz.getAnInstantiation()
907-
)
910+
this = getAnEventEmitterImport().getAnInstantiation()
911+
}
912+
}
913+
914+
/**
915+
* A class that extends EventEmitter.
916+
*/
917+
private class EventEmitterSubClass extends DataFlow::ClassNode {
918+
EventEmitterSubClass() {
919+
this.getASuperClassNode().getALocalSource() = getAnEventEmitterImport() or
920+
this.getADirectSuperClass() instanceof EventEmitterSubClass
921+
}
922+
923+
private DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
924+
t.start() and result = this
925+
or
926+
exists (DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
927+
}
928+
929+
/**
930+
* Gets a reference to this class.
931+
*/
932+
DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) }
933+
}
934+
935+
/**
936+
* An instantiation of a class that extends EventEmitter.
937+
*
938+
* By extending `NodeJSEventEmitter' we get data-flow on the events passing through this EventEmitter.
939+
*/
940+
private class CustomEventEmitter extends NodeJSEventEmitter {
941+
CustomEventEmitter() {
942+
this = any(EventEmitterSubClass clazz).ref().getAnInstantiation()
908943
}
909944
}
910945

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@
44
| tst.js:20:17:20:21 | "foo" | tst.js:19:16:19:18 | foo |
55
| tst.js:21:17:21:21 | "bar" | tst.js:19:39:19:41 | bar |
66
| tst.js:28:17:28:22 | "blab" | tst.js:25:16:25:20 | event |
7+
| tst.js:34:18:34:22 | "BOH" | tst.js:33:17:33:17 | x |
8+
| tst.js:40:20:40:27 | "yabity" | tst.js:39:19:39:19 | x |

javascript/ql/test/library-tests/frameworks/EventEmitter/tst.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,15 @@ em3.on("bla", (event) => {
2626
event.returnValue = "foo"
2727
});
2828
em3.emit("bla", "blab");
29+
30+
class MyEventEmitter extends emitter {};
31+
32+
var em4 = new MyEventEmitter();
33+
em4.on("blab", (x) => {});
34+
em4.emit("blab", "BOH");
35+
36+
class ExtendsMyCustomEmitter extends MyEventEmitter{}
37+
38+
var em5 = new ExtendsMyCustomEmitter();
39+
em5.on("yibity", (x) => {});
40+
em5.emit("yibity", "yabity");

0 commit comments

Comments
 (0)