@@ -19,53 +19,57 @@ module EventEmitter {
1919 result = "prependOnceListener"
2020 }
2121
22+
23+ private DataFlow:: SourceNode trackEventEmitter ( DataFlow:: TypeTracker t , EventEmitterRange:: Range emitter ) {
24+ t .start ( ) and result = emitter
25+ or
26+ exists ( DataFlow:: TypeTracker t2 , DataFlow:: SourceNode pred | pred = trackEventEmitter ( t2 , emitter ) |
27+ result = pred .track ( t2 , t )
28+ or
29+ // invocation of a chainable method
30+ exists ( DataFlow:: MethodCallNode mcn |
31+ mcn = pred .getAMethodCall ( EventEmitter:: chainableMethod ( ) ) and
32+ // exclude getter versions
33+ exists ( mcn .getAnArgument ( ) ) and
34+ result = mcn and
35+ t = t2 .continue ( )
36+ )
37+ )
38+ }
39+
2240 /**
23- * An instance of the NodeJS EventEmitter class.
24- * Extend this class to mark something as being an instance of the EventEmitter class.
41+ * Type tracking of an EventEmitter. Types are tracked through the chainable methods in the NodeJS eventEmitter.
42+ */
43+ DataFlow:: SourceNode trackEventEmitter ( EventEmitterRange:: Range emitter ) {
44+ result = trackEventEmitter ( DataFlow:: TypeTracker:: end ( ) , emitter )
45+ }
46+
47+ /**
48+ * An EventEmitter instance that implements the NodeJS EventEmitter API.
2549 */
2650 final class EventEmitter extends DataFlow:: Node {
2751 EventEmitterRange:: Range range ;
2852
2953 EventEmitter ( ) { this = range }
54+ }
3055
56+ module EventEmitterRange {
3157 /**
32- * Get a method name that returns `this` on this type of emitter.
58+ * An object that implements the EventEmitter API.
59+ * Extending this class does nothing, its mostly to indicate intent.
60+ * The magic only happens when extending EventRegistration::Range and EventDispatch::Range.
3361 */
34- string getAChainableMethod ( ) { result = range . getAChainableMethod ( ) }
62+ abstract class Range extends DataFlow :: Node { }
3563
3664 /**
37- * Get a reference through type-tracking to this EventEmitter.
38- * The type-tracking tracks through chainable methods.
65+ * An NodeJS EventEmitter instance.
66+ * Events dispatched on this EventEmitter will be handled by event handlers registered on this EventEmitter.
67+ * (That is opposed to e.g. SocketIO, which implements the same interface, but where events cross object boundaries).
3968 */
40- DataFlow:: SourceNode ref ( ) { result = range .ref ( ) }
41- }
42-
43- module EventEmitterRange {
44- abstract class Range extends DataFlow:: Node {
45- string getAChainableMethod ( ) { result = EventEmitter:: chainableMethod ( ) }
46-
47- private DataFlow:: SourceNode ref ( DataFlow:: TypeTracker t ) {
48- t .start ( ) and result = this
49- or
50- exists ( DataFlow:: TypeTracker t2 , DataFlow:: SourceNode pred | pred = ref ( t2 ) |
51- result = pred .track ( t2 , t )
52- or
53- // invocation of a chainable method
54- exists ( DataFlow:: MethodCallNode mcn |
55- mcn = pred .getAMethodCall ( this .getAChainableMethod ( ) ) and
56- // exclude getter versions
57- exists ( mcn .getAnArgument ( ) ) and
58- result = mcn and
59- t = t2 .continue ( )
60- )
61- )
62- }
63-
64- DataFlow:: SourceNode ref ( ) { result = ref ( DataFlow:: TypeTracker:: end ( ) ) }
69+ abstract class NodeJSEventEmitter extends Range {
70+ DataFlow:: SourceNode ref ( ) { result = trackEventEmitter ( this ) }
6571 }
6672
67- abstract class NodeJSEventEmitter extends Range { }
68-
6973 private class ImportedNodeJSEventEmitter extends NodeJSEventEmitter {
7074 ImportedNodeJSEventEmitter ( ) {
7175 exists ( DataFlow:: SourceNode clazz |
@@ -79,7 +83,7 @@ module EventEmitter {
7983 }
8084
8185 /**
82- * A registration of an event handler on a particular EventEmitter.
86+ * A registration of an event handler on an EventEmitter.
8387 */
8488 final class EventRegistration extends DataFlow:: Node {
8589 EventRegistration:: Range range ;
@@ -93,7 +97,7 @@ module EventEmitter {
9397 string getChannel ( ) { result = range .getChannel ( ) }
9498
9599 /** Gets the `i`th parameter in the event handler. */
96- DataFlow:: Node getEventHandlerParameter ( int i ) { result = range .getEventHandlerParameter ( i ) }
100+ DataFlow:: Node getReceivedItem ( int i ) { result = range .getReceivedItem ( i ) }
97101
98102 /**
99103 * Gets a value that is returned by the event handler.
@@ -109,17 +113,23 @@ module EventEmitter {
109113 }
110114
111115 module EventRegistration {
112- abstract class Range extends DataFlow:: CallNode {
116+ /**
117+ * A registration of an event handler on an EventEmitter.
118+ * The default implementation assumes that `this` is a DataFlow::InvokeNode where the
119+ * first argument is a string describing which channel is registered, and the second
120+ * argument is the event handler callback.
121+ */
122+ abstract class Range extends DataFlow:: Node {
113123 EventEmitterRange:: Range emitter ;
114124
115125 final EventEmitter getEmitter ( ) { result = emitter }
116126
117127 string getChannel ( ) {
118- this .getArgument ( 0 ) .mayHaveStringValue ( result )
128+ this .( DataFlow :: InvokeNode ) . getArgument ( 0 ) .mayHaveStringValue ( result )
119129 }
120130
121- DataFlow:: Node getEventHandlerParameter ( int i ) {
122- result = this .getABoundCallbackParameter ( 1 , i )
131+ DataFlow:: Node getReceivedItem ( int i ) {
132+ result = this .( DataFlow :: InvokeNode ) . getABoundCallbackParameter ( 1 , i )
123133 }
124134
125135 DataFlow:: Node getAReturnedValue ( ) { none ( ) }
@@ -137,7 +147,7 @@ module EventEmitter {
137147 /**
138148 * A dispatch of an event on an EventEmitter.
139149 */
140- final class EventDispatch extends DataFlow:: CallNode {
150+ final class EventDispatch extends DataFlow:: Node {
141151 EventDispatch:: Range range ;
142152
143153 EventDispatch ( ) { this = range }
@@ -149,31 +159,38 @@ module EventEmitter {
149159 string getChannel ( ) { result = range .getChannel ( ) }
150160
151161 /** Gets the `i`th argument that is send to the event handler. */
152- DataFlow:: Node getDispatchedArgument ( int i ) { result = range .getDispatchedArgument ( i ) }
162+ DataFlow:: Node getSentItem ( int i ) { result = range .getSentItem ( i ) }
153163
154164 /**
155- * Holds if this event dispatch can send an event to the given even registration .
165+ * Get an EventRegistration that this event dispatch can send an event to.
156166 * The default implementation is that the emitters of the dispatch and registration have to be equal.
167+ * Channels are by default ignored.
157168 */
158- predicate canSendTo ( EventRegistration destination ) { range .canSendTo ( destination ) }
169+ EventRegistration getAReceiver ( ) { result = range .getAReceiver ( ) }
159170 }
160171
161172 module EventDispatch {
162- abstract class Range extends DataFlow:: CallNode {
173+ /**
174+ * A dispatch of an event on an EventEmitter.
175+ * The default implementation assumes that the dispatch is a DataFlow::InvokeNode,
176+ * where the first argument is a string describing the channel, and the `i`+1 argument
177+ * is the `i`th item sent to the event handler.
178+ */
179+ abstract class Range extends DataFlow:: Node {
163180 EventEmitterRange:: Range emitter ;
164181
165182 final EventEmitter getEmitter ( ) { result = emitter }
166183
167184 string getChannel ( ) {
168- this .getArgument ( 0 ) .mayHaveStringValue ( result )
185+ this .( DataFlow :: InvokeNode ) . getArgument ( 0 ) .mayHaveStringValue ( result )
169186 }
170187
171- DataFlow:: Node getDispatchedArgument ( int i ) {
172- result = this .getArgument ( i + 1 )
188+ DataFlow:: Node getSentItem ( int i ) {
189+ result = this .( DataFlow :: InvokeNode ) . getArgument ( i + 1 )
173190 }
174191
175- predicate canSendTo ( EventRegistration destination ) {
176- this .getEmitter ( ) = destination .getEmitter ( )
192+ EventRegistration:: Range getAReceiver ( ) {
193+ this .getEmitter ( ) = result .getEmitter ( )
177194 }
178195 }
179196
@@ -193,14 +210,14 @@ module EventEmitter {
193210
194211 EventEmitterTaintStep ( ) {
195212 this = dispatch and
196- dispatch .canSendTo ( reg ) and
197- reg .getChannel ( ) = dispatch .getChannel ( )
213+ reg = dispatch .getAReceiver ( ) and
214+ not dispatch .getChannel ( ) != reg .getChannel ( )
198215 }
199216
200217 override predicate step ( DataFlow:: Node pred , DataFlow:: Node succ ) {
201218 exists ( int i | i >= 0 |
202- pred = dispatch .getDispatchedArgument ( i ) and
203- succ = reg .getEventHandlerParameter ( i )
219+ pred = dispatch .getSentItem ( i ) and
220+ succ = reg .getReceivedItem ( i )
204221 )
205222 or
206223 reg .canReturnTo ( dispatch ) and
0 commit comments