Skip to content

Commit e818f4c

Browse files
committed
refactored some duplicated methods into the abstract class, and specialized the type of emitter in NodeJS EventEmitter dispatch/registration
1 parent 267c4c0 commit e818f4c

File tree

2 files changed

+27
-31
lines changed

2 files changed

+27
-31
lines changed

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

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ module Electron {
7373
/**
7474
* A reference to the `webContents` property of a browser object.
7575
*/
76-
class WebContents extends DataFlow::SourceNode {
76+
class WebContents extends DataFlow::SourceNode, EventEmitter::EventEmitterRange::NodeJSEventEmitter {
7777
WebContents() { this.(DataFlow::PropRead).accesses(any(BrowserObject bo), "webContents") }
7878
}
7979

@@ -96,7 +96,7 @@ module Electron {
9696
* Communication in an electron app generally happens from the renderer process to the main process.
9797
*/
9898
class MainProcess extends Process {
99-
MainProcess() { this = main() or this instanceof WebContents }
99+
MainProcess() { this = main() }
100100
}
101101

102102
/**
@@ -127,20 +127,14 @@ module Electron {
127127
DataFlow::MethodCallNode {
128128
override Process emitter;
129129

130-
IPCSendRegistration() { this = emitter.ref().getAMethodCall("on") }
131-
132-
override string getChannel() { this.getArgument(0).mayHaveStringValue(result) }
133-
134-
override DataFlow::Node getEventHandlerParameter(int i) {
135-
result = this.getABoundCallbackParameter(1, i + 1)
136-
}
130+
IPCSendRegistration() { this = emitter.ref().getAMethodCall(EventEmitter::on()) }
137131

138132
override DataFlow::Node getAReturnedValue() {
139133
result = this.getABoundCallbackParameter(1, 0).getAPropertyWrite("returnValue").getRhs()
140134
}
141135

142136
override predicate canReturnTo(EventEmitter::EventDispatch dispatch) {
143-
dispatch.(DataFlow::InvokeNode).getCalleeName() = "sendSync"
137+
dispatch.getCalleeName() = "sendSync"
144138
}
145139
}
146140

@@ -158,8 +152,6 @@ module Electron {
158152
)
159153
}
160154

161-
override string getChannel() { this.getArgument(0).mayHaveStringValue(result) }
162-
163155
/**
164156
* Gets the `i`th dispatched argument to the event handler.
165157
* The 0th parameter in the callback is a event generated by the IPC system,

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

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@ module EventEmitter {
6464
DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) }
6565
}
6666

67-
private class NodeJSEventEmitter extends Range {
68-
NodeJSEventEmitter() {
67+
abstract class NodeJSEventEmitter extends Range {}
68+
69+
private class ImportedNodeJSEventEmitter extends NodeJSEventEmitter {
70+
ImportedNodeJSEventEmitter() {
6971
exists(DataFlow::SourceNode clazz |
7072
clazz = DataFlow::moduleImport("events") or
7173
clazz = DataFlow::moduleMember("events", "EventEmitter")
@@ -107,35 +109,35 @@ module EventEmitter {
107109
}
108110

109111
module EventRegistration {
110-
abstract class Range extends DataFlow::Node {
112+
abstract class Range extends DataFlow::CallNode {
111113
EventEmitterRange::Range emitter;
112114

113115
final EventEmitter getEmitter() { result = emitter }
114116

115-
abstract string getChannel();
117+
string getChannel() {
118+
this.getArgument(0).mayHaveStringValue(result)
119+
}
116120

117-
abstract DataFlow::Node getEventHandlerParameter(int i);
121+
DataFlow::Node getEventHandlerParameter(int i) {
122+
result = this.getABoundCallbackParameter(1, i)
123+
}
118124

119125
DataFlow::Node getAReturnedValue() { none() }
120126

121127
predicate canReturnTo(EventDispatch dispatch) { none() }
122128
}
123129

124130
private class NodeJSEventRegistration extends Range, DataFlow::MethodCallNode {
125-
NodeJSEventRegistration() { this = emitter.ref().getAMethodCall(EventEmitter::on()) }
126-
127-
override string getChannel() { this.getArgument(0).mayHaveStringValue(result) }
131+
override EventEmitterRange::NodeJSEventEmitter emitter;
128132

129-
override DataFlow::Node getEventHandlerParameter(int i) {
130-
result = this.(DataFlow::MethodCallNode).getABoundCallbackParameter(1, i)
131-
}
133+
NodeJSEventRegistration() { this = emitter.ref().getAMethodCall(EventEmitter::on()) }
132134
}
133135
}
134136

135137
/**
136138
* A dispatch of an event on an EventEmitter.
137139
*/
138-
final class EventDispatch extends DataFlow::Node {
140+
final class EventDispatch extends DataFlow::CallNode {
139141
EventDispatch::Range range;
140142

141143
EventDispatch() { this = range }
@@ -157,26 +159,28 @@ module EventEmitter {
157159
}
158160

159161
module EventDispatch {
160-
abstract class Range extends DataFlow::Node {
162+
abstract class Range extends DataFlow::CallNode {
161163
EventEmitterRange::Range emitter;
162164

163165
final EventEmitter getEmitter() { result = emitter }
164166

165-
abstract string getChannel();
167+
string getChannel() {
168+
this.getArgument(0).mayHaveStringValue(result)
169+
}
166170

167-
abstract DataFlow::Node getDispatchedArgument(int i);
171+
DataFlow::Node getDispatchedArgument(int i) {
172+
result = this.getArgument(i + 1)
173+
}
168174

169175
predicate canSendTo(EventRegistration destination) {
170176
this.getEmitter() = destination.getEmitter()
171177
}
172178
}
173179

174180
private class NodeJSEventDispatch extends Range, DataFlow::MethodCallNode {
175-
NodeJSEventDispatch() { this = emitter.ref().getAMethodCall("emit") }
176-
177-
override string getChannel() { this.getArgument(0).mayHaveStringValue(result) }
181+
override EventEmitterRange::NodeJSEventEmitter emitter;
178182

179-
override DataFlow::Node getDispatchedArgument(int i) { result = this.getArgument(i + 1) }
183+
NodeJSEventDispatch() { this = emitter.ref().getAMethodCall("emit") }
180184
}
181185
}
182186

0 commit comments

Comments
 (0)