From 1abdce50e86226581567301ed6df92c302c52dc4 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Fri, 29 Jan 2021 14:53:16 +0100 Subject: [PATCH] http: refactor to avoid unsafe array iteration --- lib/_http_agent.js | 21 ++++++++++++++------- lib/_http_outgoing.js | 7 ++++--- lib/_http_server.js | 6 +++--- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/_http_agent.js b/lib/_http_agent.js index ba165b42b1dc3a..53f6ade00ce524 100644 --- a/lib/_http_agent.js +++ b/lib/_http_agent.js @@ -201,8 +201,9 @@ function maybeEnableKeylog(eventName) { agent.emit('keylog', keylog, this); }; // Existing sockets will start listening on keylog now. - for (const socket of ObjectValues(this.sockets)) { - socket.on('keylog', this[kOnKeylog]); + const sockets = ObjectValues(this.sockets); + for (let i = 0; i < sockets.length; i++) { + sockets[i].on('keylog', this[kOnKeylog]); } } } @@ -426,7 +427,9 @@ Agent.prototype.removeSocket = function removeSocket(s, options) { if (!s.writable) ArrayPrototypePush(sets, this.freeSockets); - for (const sockets of sets) { + for (let sk = 0; sk < sets.length; sk++) { + const sockets = sets[sk]; + if (sockets[name]) { const index = ArrayPrototypeIndexOf(sockets[name], s); if (index !== -1) { @@ -492,10 +495,14 @@ Agent.prototype.reuseSocket = function reuseSocket(socket, req) { }; Agent.prototype.destroy = function destroy() { - for (const set of [this.freeSockets, this.sockets]) { - for (const key of ObjectKeys(set)) { - for (const setName of set[key]) { - setName.destroy(); + const sets = [this.freeSockets, this.sockets]; + for (let s = 0; s < sets.length; s++) { + const set = sets[s]; + const keys = ObjectKeys(set); + for (let v = 0; v < keys.length; v++) { + const setName = set[keys[v]]; + for (let n = 0; n < setName.length; n++) { + setName[n].destroy(); } } } diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index 872fc04edbadc8..37ef44f2f2eee2 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -23,6 +23,7 @@ const { ArrayIsArray, + ArrayPrototypeForEach, ArrayPrototypeJoin, ArrayPrototypePush, ArrayPrototypeUnshift, @@ -390,9 +391,9 @@ function _storeHeader(firstLine, headers) { } } else if (ArrayIsArray(headers)) { if (headers.length && ArrayIsArray(headers[0])) { - for (const entry of headers) { - processHeader(this, state, entry[0], entry[1], true); - } + ArrayPrototypeForEach(headers, (entry) => + processHeader(this, state, entry[0], entry[1], true) + ); } else { if (headers.length % 2 !== 0) { throw new ERR_INVALID_ARG_VALUE('headers', headers); diff --git a/lib/_http_server.js b/lib/_http_server.js index a0b1ea7720066d..d13b2cbbd38fbb 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -23,6 +23,7 @@ const { ArrayIsArray, + ArrayPrototypeForEach, ArrayPrototypePush, ArrayPrototypeShift, Error, @@ -417,9 +418,8 @@ Server.prototype[EE.captureRejectionSymbol] = function(err, event, ...args) { const [ , res] = args; if (!res.headersSent && !res.writableEnded) { // Don't leak headers. - for (const name of res.getHeaderNames()) { - res.removeHeader(name); - } + ArrayPrototypeForEach(res.getHeaderNames(), + (name) => res.removeHeader(name)); res.statusCode = 500; res.end(STATUS_CODES[500]); } else {