mirror of
https://github.com/github/codeql.git
synced 2026-04-29 10:45:15 +02:00
@@ -906,9 +906,7 @@ module NodeJSLib {
|
||||
* An instance of an EventEmitter that is imported through the 'events' module.
|
||||
*/
|
||||
private class ImportedNodeJSEventEmitter extends NodeJSEventEmitter {
|
||||
ImportedNodeJSEventEmitter() {
|
||||
this = getAnEventEmitterImport().getAnInstantiation()
|
||||
}
|
||||
ImportedNodeJSEventEmitter() { this = getAnEventEmitterImport().getAnInstantiation() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -922,20 +920,33 @@ module NodeJSLib {
|
||||
}
|
||||
|
||||
/**
|
||||
* An instantiation of a class that extends EventEmitter.
|
||||
*
|
||||
* An instantiation of a class that extends EventEmitter.
|
||||
*
|
||||
* By extending `NodeJSEventEmitter' we get data-flow on the events passing through this EventEmitter.
|
||||
*/
|
||||
private class CustomEventEmitter extends NodeJSEventEmitter {
|
||||
class CustomEventEmitter extends NodeJSEventEmitter {
|
||||
EventEmitterSubClass clazz;
|
||||
CustomEventEmitter() {
|
||||
this = any(EventEmitterSubClass clazz).getAClassReference().getAnInstantiation()
|
||||
if exists(clazz.getAClassReference().getAnInstantiation()) then
|
||||
this = clazz.getAClassReference().getAnInstantiation()
|
||||
else
|
||||
// In case there are no explicit instantiations of the clazz, then we still want to track data flow between `this` nodes.
|
||||
// This cannot produce false flow as the `.ref()` method below is always used when creating event-registrations/event-dispatches.
|
||||
this = clazz
|
||||
}
|
||||
|
||||
override DataFlow::SourceNode ref() {
|
||||
result = NodeJSEventEmitter.super.ref() and not this = clazz
|
||||
or
|
||||
result = clazz.getAReceiverNode()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A registration of an event handler on a NodeJS EventEmitter instance.
|
||||
*/
|
||||
private class NodeJSEventRegistration extends EventRegistration::DefaultEventRegistration, DataFlow::MethodCallNode {
|
||||
private class NodeJSEventRegistration extends EventRegistration::DefaultEventRegistration,
|
||||
DataFlow::MethodCallNode {
|
||||
override NodeJSEventEmitter emitter;
|
||||
|
||||
NodeJSEventRegistration() { this = emitter.ref().getAMethodCall(EventEmitter::on()) }
|
||||
@@ -944,9 +955,94 @@ module NodeJSLib {
|
||||
/**
|
||||
* A dispatch of an event on a NodeJS EventEmitter instance.
|
||||
*/
|
||||
private class NodeJSEventDispatch extends EventDispatch::DefaultEventDispatch, DataFlow::MethodCallNode {
|
||||
private class NodeJSEventDispatch extends EventDispatch::DefaultEventDispatch,
|
||||
DataFlow::MethodCallNode {
|
||||
override NodeJSEventEmitter emitter;
|
||||
|
||||
NodeJSEventDispatch() { this = emitter.ref().getAMethodCall("emit") }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instance of net.createServer(), which creates a new TCP/IPC server.
|
||||
*/
|
||||
private class NodeJSNetServer extends DataFlow::SourceNode {
|
||||
NodeJSNetServer() { this = DataFlow::moduleMember("net", "createServer").getAnInvocation() }
|
||||
|
||||
private DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
|
||||
t.start() and result = this
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to this server.
|
||||
*/
|
||||
DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A connection opened on a NodeJS net server.
|
||||
*/
|
||||
private class NodeJSNetServerConnection extends EventEmitter::Range {
|
||||
NodeJSNetServer server;
|
||||
|
||||
NodeJSNetServerConnection() {
|
||||
exists(DataFlow::MethodCallNode call |
|
||||
call = server.ref().getAMethodCall("on") and
|
||||
call.getArgument(0).mayHaveStringValue("connection")
|
||||
|
|
||||
this = call.getCallback(1).getParameter(0)
|
||||
)
|
||||
}
|
||||
|
||||
DataFlow::SourceNode ref() { result = EventEmitter::trackEventEmitter(this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A registration of an event handler on a NodeJS net server instance.
|
||||
*/
|
||||
private class NodeJSNetServerRegistration extends EventRegistration::DefaultEventRegistration,
|
||||
DataFlow::MethodCallNode {
|
||||
override NodeJSNetServerConnection emitter;
|
||||
|
||||
NodeJSNetServerRegistration() { this = emitter.ref().getAMethodCall(EventEmitter::on()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow node representing data received from a client to a NodeJS net server, viewed as remote user input.
|
||||
*/
|
||||
private class NodeJSNetServerItemAsRemoteFlow extends RemoteFlowSource {
|
||||
NodeJSNetServerRegistration reg;
|
||||
|
||||
NodeJSNetServerItemAsRemoteFlow() { this = reg.getReceivedItem(_) }
|
||||
|
||||
override string getSourceType() { result = "NodeJS server" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instantiation of the `respjs` library, which is an EventEmitter.
|
||||
*/
|
||||
private class RespJS extends NodeJSEventEmitter {
|
||||
RespJS() {
|
||||
this = DataFlow::moduleImport("respjs").getAnInstantiation()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A event dispatch that serializes the input data and emits the result on the "data" channel.
|
||||
*/
|
||||
private class RespWrite extends EventDispatch::DefaultEventDispatch,
|
||||
DataFlow::MethodCallNode {
|
||||
override RespJS emitter;
|
||||
|
||||
RespWrite() { this = emitter.ref().getAMethodCall("write") }
|
||||
|
||||
override string getChannel() {
|
||||
result = "data"
|
||||
}
|
||||
|
||||
override DataFlow::Node getSentItem(int i) {
|
||||
i = 0 and result = this.getArgument(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
const EventEmitter = require("events");
|
||||
|
||||
class MyEmitter extends EventEmitter {
|
||||
foo() {
|
||||
this.emit("foo", "bar");
|
||||
this.on("foo", (data) => {});
|
||||
}
|
||||
}
|
||||
|
||||
class MySecondEmitter extends EventEmitter {
|
||||
foo() {
|
||||
this.emit("bar", "baz");
|
||||
this.on("bar", (data) => {});
|
||||
}
|
||||
}
|
||||
|
||||
var x = new MySecondEmitter();
|
||||
x.emit("bar", "baz2");
|
||||
|
||||
var y = new MySecondEmitter();
|
||||
y.emit("bar", "baz3");
|
||||
y.on("bar", (yData) => {})
|
||||
@@ -1,3 +1,9 @@
|
||||
| customEmitter.js:5:20:5:24 | "bar" | customEmitter.js:6:19:6:22 | data |
|
||||
| customEmitter.js:12:21:12:25 | "baz" | customEmitter.js:13:23:13:26 | data |
|
||||
| customEmitter.js:12:21:12:25 | "baz" | customEmitter.js:22:14:22:18 | yData |
|
||||
| customEmitter.js:18:15:18:20 | "baz2" | customEmitter.js:13:23:13:26 | data |
|
||||
| customEmitter.js:21:15:21:20 | "baz3" | customEmitter.js:13:23:13:26 | data |
|
||||
| customEmitter.js:21:15:21:20 | "baz3" | customEmitter.js:22:14:22:18 | yData |
|
||||
| tst.js:9:23:9:33 | 'FirstData' | tst.js:6:40:6:44 | first |
|
||||
| tst.js:10:24:10:35 | 'SecondData' | tst.js:7:32:7:37 | second |
|
||||
| tst.js:15:24:15:39 | 'OtherFirstData' | tst.js:14:41:14:50 | otherFirst |
|
||||
|
||||
Reference in New Issue
Block a user