@@ -19,11 +19,21 @@ module EventEmitter {
1919 result = "prependOnceListener"
2020 }
2121
22+ /**
23+ * Gets a node that refers to an EventEmitter object.
24+ */
25+ DataFlow:: SourceNode trackEventEmitter ( EventEmitter:: Range emitter ) {
26+ result = trackEventEmitter ( DataFlow:: TypeTracker:: end ( ) , emitter )
27+ }
2228
23- private DataFlow:: SourceNode trackEventEmitter ( DataFlow:: TypeTracker t , EventEmitterRange:: Range emitter ) {
29+ private DataFlow:: SourceNode trackEventEmitter (
30+ DataFlow:: TypeTracker t , EventEmitter:: Range emitter
31+ ) {
2432 t .start ( ) and result = emitter
2533 or
26- exists ( DataFlow:: TypeTracker t2 , DataFlow:: SourceNode pred | pred = trackEventEmitter ( t2 , emitter ) |
34+ exists ( DataFlow:: TypeTracker t2 , DataFlow:: SourceNode pred |
35+ pred = trackEventEmitter ( t2 , emitter )
36+ |
2737 result = pred .track ( t2 , t )
2838 or
2939 // invocation of a chainable method
@@ -38,192 +48,178 @@ module EventEmitter {
3848 }
3949
4050 /**
41- * Type tracking of an EventEmitter. Types are tracked through the chainable methods in the NodeJS eventEmitter.
51+ * An object that implements the EventEmitter API.
52+ * Extending this class does nothing, its mostly to indicate intent.
53+ * The magic only happens when extending EventRegistration::Range and EventDispatch::Range.
4254 */
43- DataFlow:: SourceNode trackEventEmitter ( EventEmitterRange:: Range emitter ) {
44- result = trackEventEmitter ( DataFlow:: TypeTracker:: end ( ) , emitter )
45- }
55+ abstract class Range extends DataFlow:: Node { }
4656
4757 /**
48- * An EventEmitter instance that implements the NodeJS EventEmitter API.
49- * Extend EventEmitter::Range to mark something as being an EventEmitter.
58+ * An NodeJS EventEmitter instance.
59+ * Events dispatched on this EventEmitter will be handled by event handlers registered on this EventEmitter.
60+ * (That is opposed to e.g. SocketIO, which implements the same interface, but where events cross object boundaries).
5061 */
51- class EventEmitter extends DataFlow:: Node {
52- EventEmitterRange:: Range range ;
53-
54- EventEmitter ( ) { this = range }
55- }
56-
57- module EventEmitterRange {
62+ abstract class NodeJSEventEmitter extends Range {
5863 /**
59- * An object that implements the EventEmitter API.
60- * Extending this class does nothing, its mostly to indicate intent.
61- * The magic only happens when extending EventRegistration::Range and EventDispatch::Range.
64+ * Get a Node that refers to a NodeJS EventEmitter instance.
6265 */
63- abstract class Range extends DataFlow:: Node { }
64-
65- /**
66- * An NodeJS EventEmitter instance.
67- * Events dispatched on this EventEmitter will be handled by event handlers registered on this EventEmitter.
68- * (That is opposed to e.g. SocketIO, which implements the same interface, but where events cross object boundaries).
69- */
70- abstract class NodeJSEventEmitter extends Range {
71- DataFlow:: SourceNode ref ( ) { result = trackEventEmitter ( this ) }
72- }
66+ DataFlow:: SourceNode ref ( ) { result = trackEventEmitter ( this ) }
67+ }
7368
74- private class ImportedNodeJSEventEmitter extends NodeJSEventEmitter {
75- ImportedNodeJSEventEmitter ( ) {
76- exists ( DataFlow:: SourceNode clazz |
77- clazz = DataFlow:: moduleImport ( "events" ) or
78- clazz = DataFlow:: moduleMember ( "events" , "EventEmitter" )
79- |
80- this = clazz .getAnInstantiation ( )
81- )
82- }
69+ private class ImportedNodeJSEventEmitter extends NodeJSEventEmitter {
70+ ImportedNodeJSEventEmitter ( ) {
71+ exists ( DataFlow:: SourceNode clazz |
72+ clazz = DataFlow:: moduleImport ( "events" ) or
73+ clazz = DataFlow:: moduleMember ( "events" , "EventEmitter" )
74+ |
75+ this = clazz .getAnInstantiation ( )
76+ )
8377 }
8478 }
79+ }
8580
86- /**
87- * A registration of an event handler on an EventEmitter.
88- */
89- class EventRegistration extends DataFlow:: Node {
90- EventRegistration:: Range range ;
81+ /**
82+ * An EventEmitter instance that implements the NodeJS EventEmitter API.
83+ * Extend EventEmitter::Range to mark something as being an EventEmitter.
84+ */
85+ class EventEmitter extends DataFlow:: Node {
86+ EventEmitter:: Range range ;
9187
92- EventRegistration ( ) { this = range }
88+ EventEmitter ( ) { this = range }
89+ }
9390
94- /** Gets the EventEmitter that the event handler is registered on. */
95- final EventEmitter getEmitter ( ) { result = range .getEmitter ( ) }
91+ /**
92+ * A registration of an event handler on an EventEmitter.
93+ */
94+ class EventRegistration extends DataFlow:: Node {
95+ EventRegistration:: Range range ;
9696
97- /** Gets the name of the channel if possible. */
98- string getChannel ( ) { result = range .getChannel ( ) }
97+ EventRegistration ( ) { this = range }
9998
100- /** Gets the `i`th parameter in the event handler. */
101- DataFlow :: Node getReceivedItem ( int i ) { result = range .getReceivedItem ( i ) }
99+ /** Gets the EventEmitter that the event handler is registered on . */
100+ final EventEmitter getEmitter ( ) { result = range .getEmitter ( ) }
102101
103- /**
104- * Gets a value that is returned by the event handler.
105- * The default implementation is that no value can be returned.
106- */
107- DataFlow:: Node getAReturnedValue ( ) { result = range .getAReturnedValue ( ) }
102+ /** Gets the name of the channel if possible. */
103+ string getChannel ( ) { result = range .getChannel ( ) }
108104
109- /**
110- * Holds if this event handler can return a value to the given `dispatch`.
111- * The default implementation is that there exists no such dispatch.
112- */
113- predicate canReturnTo ( EventDispatch dispatch ) { range .canReturnTo ( dispatch ) }
114- }
105+ /** Gets the `i`th parameter in the event handler. */
106+ DataFlow:: Node getReceivedItem ( int i ) { result = range .getReceivedItem ( i ) }
115107
116- module EventRegistration {
117- /**
118- * A registration of an event handler on an EventEmitter.
119- * The default implementation assumes that `this` is a DataFlow::InvokeNode where the
120- * first argument is a string describing which channel is registered, and the second
121- * argument is the event handler callback.
122- */
123- abstract class Range extends DataFlow:: Node {
124- EventEmitterRange:: Range emitter ;
108+ /**
109+ * Gets a value that is returned by the event handler.
110+ * The default implementation is that no value can be returned.
111+ */
112+ DataFlow:: Node getAReturnedValue ( ) { result = range .getAReturnedValue ( ) }
125113
126- final EventEmitter getEmitter ( ) { result = emitter }
114+ /**
115+ * Get a dispatch that this event handler can return a value to.
116+ * The default implementation is that there exists no such dispatch.
117+ */
118+ EventDispatch getAReturnDispatch ( ) { result = range .getAReturnDispatch ( ) }
119+ }
127120
128- string getChannel ( ) {
129- this .( DataFlow:: InvokeNode ) .getArgument ( 0 ) .mayHaveStringValue ( result )
130- }
121+ module EventRegistration {
122+ /**
123+ * A registration of an event handler on an EventEmitter.
124+ * The default implementation assumes that `this` is a DataFlow::InvokeNode where the
125+ * first argument is a string describing which channel is registered, and the second
126+ * argument is the event handler callback.
127+ */
128+ abstract class Range extends DataFlow:: Node {
129+ EventEmitter:: Range emitter ;
131130
132- DataFlow:: Node getReceivedItem ( int i ) {
133- result = this .( DataFlow:: InvokeNode ) .getABoundCallbackParameter ( 1 , i )
134- }
131+ final EventEmitter getEmitter ( ) { result = emitter }
135132
136- DataFlow:: Node getAReturnedValue ( ) { none ( ) }
133+ string getChannel ( ) { this . ( DataFlow:: InvokeNode ) . getArgument ( 0 ) . mayHaveStringValue ( result ) }
137134
138- predicate canReturnTo ( EventDispatch dispatch ) { none ( ) }
135+ DataFlow:: Node getReceivedItem ( int i ) {
136+ result = this .( DataFlow:: InvokeNode ) .getABoundCallbackParameter ( 1 , i )
139137 }
140138
141- private class NodeJSEventRegistration extends Range , DataFlow:: MethodCallNode {
142- override EventEmitterRange:: NodeJSEventEmitter emitter ;
139+ DataFlow:: Node getAReturnedValue ( ) { none ( ) }
143140
144- NodeJSEventRegistration ( ) { this = emitter .ref ( ) .getAMethodCall ( EventEmitter:: on ( ) ) }
145- }
141+ EventDispatch:: Range getAReturnDispatch ( ) { none ( ) }
146142 }
147143
148- /**
149- * A dispatch of an event on an EventEmitter.
150- */
151- class EventDispatch extends DataFlow:: Node {
152- EventDispatch:: Range range ;
144+ private class NodeJSEventRegistration extends Range , DataFlow:: MethodCallNode {
145+ override EventEmitter:: NodeJSEventEmitter emitter ;
153146
154- EventDispatch ( ) { this = range }
147+ NodeJSEventRegistration ( ) { this = emitter .ref ( ) .getAMethodCall ( EventEmitter:: on ( ) ) }
148+ }
149+ }
155150
156- /** Gets the emitter that the event dispatch happens on. */
157- EventEmitter getEmitter ( ) { result = range .getEmitter ( ) }
151+ /**
152+ * A dispatch of an event on an EventEmitter.
153+ */
154+ class EventDispatch extends DataFlow:: Node {
155+ EventDispatch:: Range range ;
158156
159- /** Gets the name of the channel if possible. */
160- string getChannel ( ) { result = range .getChannel ( ) }
157+ EventDispatch ( ) { this = range }
161158
162- /** Gets the `i`th argument that is send to the event handler . */
163- DataFlow :: Node getSentItem ( int i ) { result = range .getSentItem ( i ) }
159+ /** Gets the emitter that the event dispatch happens on . */
160+ EventEmitter getEmitter ( ) { result = range .getEmitter ( ) }
164161
165- /**
166- * Get an EventRegistration that this event dispatch can send an event to.
167- * The default implementation is that the emitters of the dispatch and registration have to be equal.
168- * Channels are by default ignored.
169- */
170- EventRegistration getAReceiver ( ) { result = range .getAReceiver ( ) }
171- }
162+ /** Gets the name of the channel if possible. */
163+ string getChannel ( ) { result = range .getChannel ( ) }
172164
173- module EventDispatch {
174- /**
175- * A dispatch of an event on an EventEmitter.
176- * The default implementation assumes that the dispatch is a DataFlow::InvokeNode,
177- * where the first argument is a string describing the channel, and the `i`+1 argument
178- * is the `i`th item sent to the event handler.
179- */
180- abstract class Range extends DataFlow:: Node {
181- EventEmitterRange:: Range emitter ;
165+ /** Gets the `i`th argument that is send to the event handler. */
166+ DataFlow:: Node getSentItem ( int i ) { result = range .getSentItem ( i ) }
182167
183- final EventEmitter getEmitter ( ) { result = emitter }
168+ /**
169+ * Get an EventRegistration that this event dispatch can send an event to.
170+ * The default implementation is that the emitters of the dispatch and registration have to be equal.
171+ * Channels are by default ignored.
172+ */
173+ EventRegistration getAReceiver ( ) { result = range .getAReceiver ( ) }
174+ }
184175
185- string getChannel ( ) {
186- this .( DataFlow:: InvokeNode ) .getArgument ( 0 ) .mayHaveStringValue ( result )
187- }
176+ module EventDispatch {
177+ /**
178+ * A dispatch of an event on an EventEmitter.
179+ * The default implementation assumes that the dispatch is a DataFlow::InvokeNode,
180+ * where the first argument is a string describing the channel, and the `i`+1 argument
181+ * is the `i`th item sent to the event handler.
182+ */
183+ abstract class Range extends DataFlow:: Node {
184+ EventEmitter:: Range emitter ;
188185
189- DataFlow:: Node getSentItem ( int i ) {
190- result = this .( DataFlow:: InvokeNode ) .getArgument ( i + 1 )
191- }
186+ final EventEmitter getEmitter ( ) { result = emitter }
192187
193- EventRegistration:: Range getAReceiver ( ) {
194- this .getEmitter ( ) = result .getEmitter ( )
195- }
196- }
188+ string getChannel ( ) { this .( DataFlow:: InvokeNode ) .getArgument ( 0 ) .mayHaveStringValue ( result ) }
197189
198- private class NodeJSEventDispatch extends Range , DataFlow:: MethodCallNode {
199- override EventEmitterRange:: NodeJSEventEmitter emitter ;
190+ DataFlow:: Node getSentItem ( int i ) { result = this .( DataFlow:: InvokeNode ) .getArgument ( i + 1 ) }
200191
201- NodeJSEventDispatch ( ) { this = emitter .ref ( ) .getAMethodCall ( "emit" ) }
202- }
192+ EventRegistration:: Range getAReceiver ( ) { this .getEmitter ( ) = result .getEmitter ( ) }
203193 }
204194
205- /**
206- * A taint-step that models data-flow between event handlers and event dispatchers.
207- */
208- private class EventEmitterTaintStep extends DataFlow:: AdditionalFlowStep {
209- EventRegistration reg ;
210- EventDispatch dispatch ;
211-
212- EventEmitterTaintStep ( ) {
213- this = dispatch and
214- reg = dispatch .getAReceiver ( ) and
215- not dispatch .getChannel ( ) != reg .getChannel ( )
216- }
195+ private class NodeJSEventDispatch extends Range , DataFlow:: MethodCallNode {
196+ override EventEmitter:: NodeJSEventEmitter emitter ;
217197
218- override predicate step ( DataFlow:: Node pred , DataFlow:: Node succ ) {
219- exists ( int i | i >= 0 |
220- pred = dispatch .getSentItem ( i ) and
221- succ = reg .getReceivedItem ( i )
222- )
223- or
224- reg .canReturnTo ( dispatch ) and
225- pred = reg .getAReturnedValue ( ) and
226- succ = dispatch
227- }
198+ NodeJSEventDispatch ( ) { this = emitter .ref ( ) .getAMethodCall ( "emit" ) }
199+ }
200+ }
201+
202+ /**
203+ * A taint-step that models data-flow between event handlers and event dispatchers.
204+ */
205+ private class EventEmitterTaintStep extends DataFlow:: AdditionalFlowStep {
206+ EventRegistration reg ;
207+ EventDispatch dispatch ;
208+
209+ EventEmitterTaintStep ( ) {
210+ this = dispatch and
211+ reg = dispatch .getAReceiver ( ) and
212+ not dispatch .getChannel ( ) != reg .getChannel ( )
213+ }
214+
215+ override predicate step ( DataFlow:: Node pred , DataFlow:: Node succ ) {
216+ exists ( int i | i >= 0 |
217+ pred = dispatch .getSentItem ( i ) and
218+ succ = reg .getReceivedItem ( i )
219+ )
220+ or
221+ dispatch = reg .getAReturnDispatch ( ) and
222+ pred = reg .getAReturnedValue ( ) and
223+ succ = dispatch
228224 }
229225}
0 commit comments