Skip to content

Commit a2e54b1

Browse files
committed
add support for this references in classes that extend EventEmitter
1 parent 816a8d1 commit a2e54b1

File tree

1 file changed

+22
-9
lines changed

1 file changed

+22
-9
lines changed

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

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,11 @@ module NodeJSLib {
892892
* Get a Node that refers to a NodeJS EventEmitter instance.
893893
*/
894894
DataFlow::SourceNode ref() { result = EventEmitter::trackEventEmitter(this) }
895+
896+
/**
897+
* Gets the node that will used for comparison when determining whether one EventEmitter can send an event to another EventEmitter.
898+
*/
899+
DataFlow::SourceNode getBaseEmitter() {result = this}
895900
}
896901

897902
/**
@@ -906,9 +911,7 @@ module NodeJSLib {
906911
* An instance of an EventEmitter that is imported through the 'events' module.
907912
*/
908913
private class ImportedNodeJSEventEmitter extends NodeJSEventEmitter {
909-
ImportedNodeJSEventEmitter() {
910-
this = getAnEventEmitterImport().getAnInstantiation()
911-
}
914+
ImportedNodeJSEventEmitter() { this = getAnEventEmitterImport().getAnInstantiation() }
912915
}
913916

914917
/**
@@ -922,20 +925,27 @@ module NodeJSLib {
922925
}
923926

924927
/**
925-
* An instantiation of a class that extends EventEmitter.
926-
*
928+
* An instantiation of a class that extends EventEmitter.
929+
*
927930
* By extending `NodeJSEventEmitter' we get data-flow on the events passing through this EventEmitter.
928931
*/
929-
private class CustomEventEmitter extends NodeJSEventEmitter {
932+
class CustomEventEmitter extends NodeJSEventEmitter {
933+
EventEmitterSubClass clazz;
930934
CustomEventEmitter() {
931-
this = any(EventEmitterSubClass clazz).getAClassReference().getAnInstantiation()
935+
this = clazz.getAnInstanceReference()
936+
}
937+
938+
// we define that events can flow between all instances of the same class, as we thereby support the `this` references in the class itself.
939+
override DataFlow::SourceNode getBaseEmitter() {
940+
result = clazz
932941
}
933942
}
934943

935944
/**
936945
* A registration of an event handler on a NodeJS EventEmitter instance.
937946
*/
938-
private class NodeJSEventRegistration extends EventRegistration::DefaultEventRegistration, DataFlow::MethodCallNode {
947+
private class NodeJSEventRegistration extends EventRegistration::DefaultEventRegistration,
948+
DataFlow::MethodCallNode {
939949
override NodeJSEventEmitter emitter;
940950

941951
NodeJSEventRegistration() { this = emitter.ref().getAMethodCall(EventEmitter::on()) }
@@ -944,9 +954,12 @@ module NodeJSLib {
944954
/**
945955
* A dispatch of an event on a NodeJS EventEmitter instance.
946956
*/
947-
private class NodeJSEventDispatch extends EventDispatch::DefaultEventDispatch, DataFlow::MethodCallNode {
957+
private class NodeJSEventDispatch extends EventDispatch::DefaultEventDispatch,
958+
DataFlow::MethodCallNode {
948959
override NodeJSEventEmitter emitter;
949960

950961
NodeJSEventDispatch() { this = emitter.ref().getAMethodCall("emit") }
962+
963+
override EventRegistration::Range getAReceiver() { emitter.getBaseEmitter() = result.getEmitter().(NodeJSEventEmitter).getBaseEmitter() }
951964
}
952965
}

0 commit comments

Comments
 (0)