From 8e7ac25aa6e5aec345c13f4a4e26ade49a1de66a Mon Sep 17 00:00:00 2001 From: Mattias Holmlund Date: Thu, 10 Aug 2017 15:11:19 +0200 Subject: [PATCH 01/24] http, tls: better support for IPv6 addresses - Properly handle IPv6 in Host header when setting servername. - When comparing IP addresses against addresses in the subjectAltName field of a certificate, format the address correctly before doing the string comparison. PR-URL: https://github.com/nodejs/node/pull/14772 Fixes: https://github.com/nodejs/node/issues/14736 Reviewed-By: Ben Noordhuis Reviewed-By: Anatoli Papirovski Reviewed-By: James M Snell --- lib/_http_agent.js | 41 +++++++++++++++++--------- lib/tls.js | 5 ++-- src/cares_wrap.cc | 23 +++++++++++++++ test/parallel/test-tls-canonical-ip.js | 31 +++++++++++++++++++ 4 files changed, 84 insertions(+), 16 deletions(-) create mode 100644 test/parallel/test-tls-canonical-ip.js diff --git a/lib/_http_agent.js b/lib/_http_agent.js index c92242e38bf8c1..f11fa9fd6d2f5f 100644 --- a/lib/_http_agent.js +++ b/lib/_http_agent.js @@ -124,13 +124,8 @@ Agent.prototype.addRequest = function(req, options) { options = util._extend({}, options); options = util._extend(options, this.options); - if (!options.servername) { - options.servername = options.host; - const hostHeader = req.getHeader('host'); - if (hostHeader) { - options.servername = hostHeader.replace(/:.*$/, ''); - } - } + if (!options.servername) + options.servername = calculateServerName(options, req); var name = this.getName(options); if (!this.sockets[name]) { @@ -178,13 +173,8 @@ Agent.prototype.createSocket = function(req, options, cb) { options = util._extend({}, options); options = util._extend(options, self.options); - if (!options.servername) { - options.servername = options.host; - const hostHeader = req.getHeader('host'); - if (hostHeader) { - options.servername = hostHeader.replace(/:.*$/, ''); - } - } + if (!options.servername) + options.servername = calculateServerName(options, req); var name = self.getName(options); options._agentKey = name; @@ -211,6 +201,29 @@ Agent.prototype.createSocket = function(req, options, cb) { } }; +function calculateServerName(options, req) { + let servername = options.host; + const hostHeader = req.getHeader('host'); + if (hostHeader) { + // abc => abc + // abc:123 => abc + // [::1] => ::1 + // [::1]:123 => ::1 + if (hostHeader.startsWith('[')) { + const index = hostHeader.indexOf(']'); + if (index === -1) { + // Leading '[', but no ']'. Need to do something... + servername = hostHeader; + } else { + servername = hostHeader.substr(1, index - 1); + } + } else { + servername = hostHeader.split(':', 1)[0]; + } + } + return servername; +} + function installListeners(agent, s, options) { function onFree() { debug('CLIENT socket onFree'); diff --git a/lib/tls.js b/lib/tls.js index c2a19d56e5e0e3..3c98e7a481e7ba 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -7,6 +7,7 @@ const net = require('net'); const url = require('url'); const binding = process.binding('crypto'); const Buffer = require('buffer').Buffer; +const canonicalizeIP = process.binding('cares_wrap').canonicalizeIP; // Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations // every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more @@ -156,7 +157,7 @@ exports.checkServerIdentity = function checkServerIdentity(host, cert) { const uri = url.parse(name.slice(4)); uriNames.push(uri.hostname); // TODO(bnoordhuis) Also use scheme. } else if (name.startsWith('IP Address:')) { - ips.push(name.slice(11)); + ips.push(canonicalizeIP(name.slice(11))); } } } @@ -165,7 +166,7 @@ exports.checkServerIdentity = function checkServerIdentity(host, cert) { let reason = 'Unknown reason'; if (net.isIP(host)) { - valid = ips.includes(host); + valid = ips.includes(canonicalizeIP(host)); if (!valid) reason = `IP: ${host} is not in the cert's list: ${ips.join(', ')}`; // TODO(bnoordhuis) Also check URI SANs that are IP addresses. diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index 5290af2c24c959..b6c51be1b98171 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -1281,6 +1281,28 @@ static void IsIPv6(const FunctionCallbackInfo& args) { } } + +void CanonicalizeIP(const FunctionCallbackInfo& args) { + v8::Isolate* isolate = args.GetIsolate(); + node::Utf8Value ip(isolate, args[0]); + char address_buffer[sizeof(struct in6_addr)]; + char canonical_ip[INET6_ADDRSTRLEN]; + + int af; + if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0) + af = AF_INET; + else if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0) + af = AF_INET6; + else + return; + + int err = uv_inet_ntop(af, address_buffer, canonical_ip, + sizeof(canonical_ip)); + CHECK_EQ(err, 0); + + args.GetReturnValue().Set(String::NewFromUtf8(isolate, canonical_ip)); +} + static void GetAddrInfo(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -1514,6 +1536,7 @@ static void Initialize(Local target, env->SetMethod(target, "isIP", IsIP); env->SetMethod(target, "isIPv4", IsIPv4); env->SetMethod(target, "isIPv6", IsIPv6); + env->SetMethod(target, "canonicalizeIP", CanonicalizeIP); env->SetMethod(target, "strerror", StrError); env->SetMethod(target, "getServers", GetServers); diff --git a/test/parallel/test-tls-canonical-ip.js b/test/parallel/test-tls-canonical-ip.js new file mode 100644 index 00000000000000..408948119c3501 --- /dev/null +++ b/test/parallel/test-tls-canonical-ip.js @@ -0,0 +1,31 @@ +'use strict'; +require('../common'); + +// Test conversion of IP addresses to the format returned +// for addresses in Subject Alternative Name section +// of a TLS certificate + +const assert = require('assert'); +const { canonicalizeIP } = process.binding('cares_wrap'); + +assert.strictEqual(canonicalizeIP('127.0.0.1'), '127.0.0.1'); +assert.strictEqual(canonicalizeIP('10.1.0.1'), '10.1.0.1'); +assert.strictEqual(canonicalizeIP('::1'), '::1'); +assert.strictEqual(canonicalizeIP('fe80:0:0:0:0:0:0:1'), 'fe80::1'); +assert.strictEqual(canonicalizeIP('fe80:0:0:0:0:0:0:0'), 'fe80::'); +assert.strictEqual(canonicalizeIP('fe80::0000:0010:0001'), 'fe80::10:1'); +assert.strictEqual(canonicalizeIP('0001:2222:3333:4444:5555:6666:7777:0088'), + '1:2222:3333:4444:5555:6666:7777:88'); + +assert.strictEqual(canonicalizeIP('0001:2222:3333:4444:5555:6666::'), + '1:2222:3333:4444:5555:6666::'); + +assert.strictEqual(canonicalizeIP('a002:B12:00Ba:4444:5555:6666:0:0'), + 'a002:b12:ba:4444:5555:6666::'); + +// IPv4 address represented in IPv6 +assert.strictEqual(canonicalizeIP('0:0:0:0:0:ffff:c0a8:101'), + '::ffff:192.168.1.1'); + +assert.strictEqual(canonicalizeIP('::ffff:192.168.1.1'), + '::ffff:192.168.1.1'); From e021fb73d25d387eacc10d2307241d24b45266f5 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Mon, 11 Dec 2017 04:37:47 +0100 Subject: [PATCH 02/24] doc,test: mention Duplex support for TLS Document and test the existing support for generic Duplex streams in the TLS module. PR-URL: https://github.com/nodejs/node/pull/17599 Reviewed-By: Rich Trott Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca --- doc/api/tls.md | 15 ++++++---- test/parallel/test-tls-generic-stream.js | 38 ++++++++++++++++++++++++ tools/doc/type-parser.js | 1 + 3 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 test/parallel/test-tls-generic-stream.js diff --git a/doc/api/tls.md b/doc/api/tls.md index b3c0b056680f95..d307b376ef58e2 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -465,7 +465,10 @@ connection is open. added: v0.11.4 --> -* `socket` {net.Socket} An instance of [`net.Socket`][] +* `socket` {net.Socket|stream.Duplex} + On the server side, any `Duplex` stream. On the client side, any + instance of [`net.Socket`][] (for generic `Duplex` stream support + on the client side, [`tls.connect()`][] must be used). * `options` {Object} * `isServer`: The SSL/TLS protocol is asymmetrical, TLSSockets must know if they are to behave as a server or a client. If `true` the TLS socket will be @@ -788,10 +791,12 @@ changes: * `port` {number} Port the client should connect to. * `path` {string} Creates unix socket connection to path. If this option is specified, `host` and `port` are ignored. - * `socket` {net.Socket} Establish secure connection on a given socket rather - than creating a new socket. If this option is specified, `path`, `host` and - `port` are ignored. Usually, a socket is already connected when passed to - `tls.connect()`, but it can be connected later. Note that + * `socket` {stream.Duplex} Establish secure connection on a given socket + rather than creating a new socket. Typically, this is an instance of + [`net.Socket`][], but any `Duplex` stream is allowed. + If this option is specified, `path`, `host` and `port` are ignored, + except for certificate validation. Usually, a socket is already connected + when passed to `tls.connect()`, but it can be connected later. Note that connection/disconnection/destruction of `socket` is the user's responsibility, calling `tls.connect()` will not cause `net.connect()` to be called. diff --git a/test/parallel/test-tls-generic-stream.js b/test/parallel/test-tls-generic-stream.js new file mode 100644 index 00000000000000..d4e5427acae110 --- /dev/null +++ b/test/parallel/test-tls-generic-stream.js @@ -0,0 +1,38 @@ +'use strict'; +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const fixtures = require('../common/fixtures'); +const makeDuplexPair = require('../common/duplexpair'); +const assert = require('assert'); +const { TLSSocket, connect } = require('tls'); + +const key = fixtures.readKey('agent1-key.pem'); +const cert = fixtures.readKey('agent1-cert.pem'); +const ca = fixtures.readKey('ca1-cert.pem'); + +const { clientSide, serverSide } = makeDuplexPair(); + +const clientTLS = connect({ + socket: clientSide, + ca, + host: 'agent1' // Hostname from certificate +}); +const serverTLS = new TLSSocket(serverSide, { + isServer: true, + key, + cert, + ca +}); + +assert.strictEqual(clientTLS.connecting, false); +assert.strictEqual(serverTLS.connecting, false); + +clientTLS.on('secureConnect', common.mustCall(() => { + clientTLS.write('foobar', common.mustCall(() => { + assert.strictEqual(serverTLS.read().toString(), 'foobar'); + assert.strictEqual(clientTLS._handle.writeQueueSize, 0); + })); + assert.ok(clientTLS._handle.writeQueueSize > 0); +})); diff --git a/tools/doc/type-parser.js b/tools/doc/type-parser.js index ee50d48f61d45e..bfe058a42c2cd2 100644 --- a/tools/doc/type-parser.js +++ b/tools/doc/type-parser.js @@ -26,6 +26,7 @@ const typeMap = { 'Stream': 'stream.html#stream_stream', 'stream.Writable': 'stream.html#stream_class_stream_writable', 'stream.Readable': 'stream.html#stream_class_stream_readable', + 'stream.Duplex': 'stream.html#stream_class_stream_duplex', 'ChildProcess': 'child_process.html#child_process_class_childprocess', 'cluster.Worker': 'cluster.html#cluster_class_worker', 'dgram.Socket': 'dgram.html#dgram_class_dgram_socket', From 48790382f1714991ef0aa8b615f721bf3389889d Mon Sep 17 00:00:00 2001 From: Jon Moss Date: Mon, 11 Dec 2017 17:20:39 -0500 Subject: [PATCH 03/24] tools: add number-isnan rule PR-URL: https://github.com/nodejs/node/pull/17556 Reviewed-By: Rich Trott Reviewed-By: Colin Ihrig --- test/.eslintrc.yaml | 1 + test/parallel/test-eslint-number-isnan.js | 20 ++++++++++++++++++++ test/parallel/test-readdouble.js | 4 ++-- test/parallel/test-writefloat.js | 4 ++-- tools/eslint-rules/number-isnan.js | 14 ++++++++++++++ 5 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 test/parallel/test-eslint-number-isnan.js create mode 100644 tools/eslint-rules/number-isnan.js diff --git a/test/.eslintrc.yaml b/test/.eslintrc.yaml index 6d2c0ec90d22b0..792c62a7258db8 100644 --- a/test/.eslintrc.yaml +++ b/test/.eslintrc.yaml @@ -8,6 +8,7 @@ rules: # Custom rules in tools/eslint-rules prefer-common-mustnotcall: 2 + number-isnan: error ## common module is mandatory in tests required-modules: [error, common] diff --git a/test/parallel/test-eslint-number-isnan.js b/test/parallel/test-eslint-number-isnan.js new file mode 100644 index 00000000000000..deeac48bcccb68 --- /dev/null +++ b/test/parallel/test-eslint-number-isnan.js @@ -0,0 +1,20 @@ +'use strict'; + +require('../common'); + +const RuleTester = require('../../tools/eslint').RuleTester; +const rule = require('../../tools/eslint-rules/number-isnan'); + +const message = 'Please use Number.isNaN instead of the global isNaN function'; + +new RuleTester().run('number-isnan', rule, { + valid: [ + 'Number.isNaN()' + ], + invalid: [ + { + code: 'isNaN()', + errors: [{ message }] + } + ] +}); diff --git a/test/parallel/test-readdouble.js b/test/parallel/test-readdouble.js index 00340a39e631c0..517393643f2804 100644 --- a/test/parallel/test-readdouble.js +++ b/test/parallel/test-readdouble.js @@ -51,12 +51,12 @@ function test(clazz) { buffer[5] = 0xff; buffer[6] = 0x0f; buffer[7] = 0x00; - assert.ok(isNaN(buffer.readDoubleBE(0))); + assert.ok(Number.isNaN(buffer.readDoubleBE(0))); assert.strictEqual(2.225073858507201e-308, buffer.readDoubleLE(0)); buffer[6] = 0xef; buffer[7] = 0x7f; - assert.ok(isNaN(buffer.readDoubleBE(0))); + assert.ok(Number.isNaN(buffer.readDoubleBE(0))); assert.strictEqual(1.7976931348623157e+308, buffer.readDoubleLE(0)); buffer[0] = 0; diff --git a/test/parallel/test-writefloat.js b/test/parallel/test-writefloat.js index aeb62c8c022484..3ff240d9dad176 100644 --- a/test/parallel/test-writefloat.js +++ b/test/parallel/test-writefloat.js @@ -106,8 +106,8 @@ function test(clazz) { // Darwin ia32 does the other kind of NaN. // Compiler bug. No one really cares. assert(0x7F === buffer[7] || 0xFF === buffer[7]); - assert.ok(isNaN(buffer.readFloatBE(0))); - assert.ok(isNaN(buffer.readFloatLE(4))); + assert.ok(Number.isNaN(buffer.readFloatBE(0))); + assert.ok(Number.isNaN(buffer.readFloatLE(4))); } diff --git a/tools/eslint-rules/number-isnan.js b/tools/eslint-rules/number-isnan.js new file mode 100644 index 00000000000000..885c38be8b2384 --- /dev/null +++ b/tools/eslint-rules/number-isnan.js @@ -0,0 +1,14 @@ +'use strict'; + +const astSelector = "CallExpression[callee.name='isNaN']"; +const msg = 'Please use Number.isNaN instead of the global isNaN function'; + +module.exports = function(context) { + function report(node) { + context.report(node, msg); + } + + return { + [astSelector]: report + }; +}; From 969c39eb3a21f3586b1c1e94fc07455179207b47 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Fri, 5 Jan 2018 11:42:39 -0500 Subject: [PATCH 04/24] lib: enable dot-notation eslint rule PR-URL: https://github.com/nodejs/node/pull/18007 Reviewed-By: Anna Henningsen Reviewed-By: Ruben Bridgewater Reviewed-By: Eugene Ostroukhov Reviewed-By: James M Snell Reviewed-By: Rich Trott Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig Reviewed-By: Roman Reiss Reviewed-By: Jon Moss --- lib/.eslintrc.yaml | 2 ++ lib/_debugger.js | 6 +++--- lib/internal/child_process.js | 2 +- lib/module.js | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/.eslintrc.yaml b/lib/.eslintrc.yaml index aaebadca125814..437aa575645ad6 100644 --- a/lib/.eslintrc.yaml +++ b/lib/.eslintrc.yaml @@ -1,4 +1,6 @@ rules: + dot-notation: error + # Custom rules in tools/eslint-rules require-buffer: error buffer-constructor: error diff --git a/lib/_debugger.js b/lib/_debugger.js index 64a8b70c5e2e58..dd679c52c9e421 100644 --- a/lib/_debugger.js +++ b/lib/_debugger.js @@ -742,9 +742,9 @@ function Interface(stdin, stdout, args) { useGlobal: false, ignoreUndefined: true }; - if (parseInt(process.env['NODE_NO_READLINE'], 10)) { + if (parseInt(process.env.NODE_NO_READLINE, 10)) { opts.terminal = false; - } else if (parseInt(process.env['NODE_FORCE_READLINE'], 10)) { + } else if (parseInt(process.env.NODE_FORCE_READLINE, 10)) { opts.terminal = true; // Emulate Ctrl+C if we're emulating terminal @@ -754,7 +754,7 @@ function Interface(stdin, stdout, args) { }); } } - if (parseInt(process.env['NODE_DISABLE_COLORS'], 10)) { + if (parseInt(process.env.NODE_DISABLE_COLORS, 10)) { opts.useColors = false; } diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 764cdd3cf26997..e01e19147bb6d1 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -383,7 +383,7 @@ ChildProcess.prototype.kill = function(sig) { if (sig === 0) { signal = 0; } else if (!sig) { - signal = constants['SIGTERM']; + signal = constants.SIGTERM; } else { signal = constants[sig]; } diff --git a/lib/module.js b/lib/module.js index 3b258f051bd4ca..6ff174ead61629 100644 --- a/lib/module.js +++ b/lib/module.js @@ -639,7 +639,7 @@ Module._initPaths = function() { paths.unshift(path.resolve(homeDir, '.node_modules')); } - var nodePath = process.env['NODE_PATH']; + var nodePath = process.env.NODE_PATH; if (nodePath) { paths = nodePath.split(path.delimiter).filter(function(path) { return !!path; From 16ef24bccf7bf0332c77eadaec26759972d4a206 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 4 Jan 2018 17:03:44 -0800 Subject: [PATCH 05/24] test: use smaller input file for test-zlib.js PR-URL: https://github.com/nodejs/node/pull/17988 Fixes: https://github.com/nodejs/node/issues/17986 Reviewed-By: Ruben Bridgewater Reviewed-By: Gireesh Punathil Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Gibson Fahnestock --- test/parallel/test-zlib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/parallel/test-zlib.js b/test/parallel/test-zlib.js index 1086be6daf320f..b06b773cf44a7b 100644 --- a/test/parallel/test-zlib.js +++ b/test/parallel/test-zlib.js @@ -136,7 +136,7 @@ assert.doesNotThrow(() => { }, 'windowsBits set to 8 should follow legacy zlib behavior'); { - const node = fs.createReadStream(process.execPath); + const node = fs.createReadStream(fixtures.path('person.jpg')); const raw = []; const reinflated = []; node.on('data', (chunk) => raw.push(chunk)); From 17c88c4c187f5789dc6c7bdd26c6d0b123531c1b Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Sun, 26 Nov 2017 16:43:20 -0500 Subject: [PATCH 06/24] doc: examples for fast-tracking regression fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/17379 Reviewed-By: Michaël Zasso Reviewed-By: Joyee Cheung Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- COLLABORATOR_GUIDE.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/COLLABORATOR_GUIDE.md b/COLLABORATOR_GUIDE.md index 78401264844c52..7d8d70cdac38e0 100644 --- a/COLLABORATOR_GUIDE.md +++ b/COLLABORATOR_GUIDE.md @@ -127,12 +127,14 @@ Before landing pull requests, sufficient time should be left for input from other Collaborators. In general, leave at least 48 hours during the week and 72 hours over weekends to account for international time differences and work schedules. However, certain types of pull requests -can be fast-tracked and may be landed after a shorter delay: - -* Focused changes that affect only documentation and/or the test suite. - `code-and-learn` and `good-first-issue` pull requests typically fall - into this category. -* Changes that fix regressions. +can be fast-tracked and may be landed after a shorter delay. For example: + +* Focused changes that affect only documentation and/or the test suite: + * `code-and-learn` tasks typically fall into this category. + * `good-first-issue` pull requests may also be suitable. +* Changes that fix regressions: + * Regressions that break the workflow (red CI or broken compilation). + * Regressions that happen right before a release, or reported soon after. When a pull request is deemed suitable to be fast-tracked, label it with `fast-track`. The pull request can be landed once 2 or more Collaborators From 37071b8ddae3c6c3b8cb544993deeb628cb678b4 Mon Sep 17 00:00:00 2001 From: Weijia Wang <381152119@qq.com> Date: Thu, 4 Jan 2018 11:55:56 +0800 Subject: [PATCH 07/24] path: fix path.normalize for relative paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After slicing, the `lastSegmentLength` should be calculated again, instead of assigning value `j`. PR-URL: https://github.com/nodejs/node/pull/17974 Fixes: https://github.com/nodejs/node/issues/17928 Reviewed-By: Michaël Zasso Reviewed-By: Gibson Fahnestock --- lib/path.js | 30 ++++++++++------------------ test/parallel/test-path-normalize.js | 24 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/lib/path.js b/lib/path.js index a121f5bf7e0160..3639fc47e7fef9 100644 --- a/lib/path.js +++ b/lib/path.js @@ -30,19 +30,14 @@ function normalizeStringWin32(path, allowAboveRoot) { res.charCodeAt(res.length - 1) !== 46/*.*/ || res.charCodeAt(res.length - 2) !== 46/*.*/) { if (res.length > 2) { - const start = res.length - 1; - var j = start; - for (; j >= 0; --j) { - if (res.charCodeAt(j) === 92/*\*/) - break; - } - if (j !== start) { - if (j === -1) { + const lastSlashIndex = res.lastIndexOf('\\'); + if (lastSlashIndex !== res.length - 1) { + if (lastSlashIndex === -1) { res = ''; lastSegmentLength = 0; } else { - res = res.slice(0, j); - lastSegmentLength = j; + res = res.slice(0, lastSlashIndex); + lastSegmentLength = res.length - 1 - res.lastIndexOf('\\'); } lastSlash = i; dots = 0; @@ -103,19 +98,14 @@ function normalizeStringPosix(path, allowAboveRoot) { res.charCodeAt(res.length - 1) !== 46/*.*/ || res.charCodeAt(res.length - 2) !== 46/*.*/) { if (res.length > 2) { - const start = res.length - 1; - var j = start; - for (; j >= 0; --j) { - if (res.charCodeAt(j) === 47/*/*/) - break; - } - if (j !== start) { - if (j === -1) { + const lastSlashIndex = res.lastIndexOf('/'); + if (lastSlashIndex !== res.length - 1) { + if (lastSlashIndex === -1) { res = ''; lastSegmentLength = 0; } else { - res = res.slice(0, j); - lastSegmentLength = j; + res = res.slice(0, lastSlashIndex); + lastSegmentLength = res.length - 1 - res.lastIndexOf('/'); } lastSlash = i; dots = 0; diff --git a/test/parallel/test-path-normalize.js b/test/parallel/test-path-normalize.js index 0820052446367e..0dd1b8339f4c64 100644 --- a/test/parallel/test-path-normalize.js +++ b/test/parallel/test-path-normalize.js @@ -27,6 +27,18 @@ assert.strictEqual(path.win32.normalize('..\\foo..\\..\\..\\bar'), '..\\..\\bar'); assert.strictEqual(path.win32.normalize('..\\...\\..\\.\\...\\..\\..\\bar'), '..\\..\\bar'); +assert.strictEqual(path.win32.normalize('../../../foo/../../../bar'), + '..\\..\\..\\..\\..\\bar'); +assert.strictEqual(path.win32.normalize('../../../foo/../../../bar/../../'), + '..\\..\\..\\..\\..\\..\\'); +assert.strictEqual( + path.win32.normalize('../foobar/barfoo/foo/../../../bar/../../'), + '..\\..\\' +); +assert.strictEqual( + path.win32.normalize('../.../../foobar/../../../bar/../../baz'), + '..\\..\\..\\..\\baz' +); assert.strictEqual(path.posix.normalize('./fixtures///b/../b/c.js'), 'fixtures/b/c.js'); @@ -44,3 +56,15 @@ assert.strictEqual(path.posix.normalize('bar/foo..'), 'bar/foo..'); assert.strictEqual(path.posix.normalize('../foo../../../bar'), '../../bar'); assert.strictEqual(path.posix.normalize('../.../.././.../../../bar'), '../../bar'); +assert.strictEqual(path.posix.normalize('../../../foo/../../../bar'), + '../../../../../bar'); +assert.strictEqual(path.posix.normalize('../../../foo/../../../bar/../../'), + '../../../../../../'); +assert.strictEqual( + path.posix.normalize('../foobar/barfoo/foo/../../../bar/../../'), + '../../' +); +assert.strictEqual( + path.posix.normalize('../.../../foobar/../../../bar/../../baz'), + '../../../../baz' +); From 838f7bdb6e1601c8b8737e1d3df9f332f1f94a57 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 10 Jan 2018 14:00:20 -0800 Subject: [PATCH 08/24] doc: be less tentative about undefined behavior MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the documentation for the buffer module, change instances of "the result is considered undefined behavior" to "the resulting behavior is undefined". It's less ambiguous in meaning and less awkward stylistically. PR-URL: https://github.com/nodejs/node/pull/18091 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Jeremiah Senkpiel Reviewed-By: Colin Ihrig Reviewed-By: Gireesh Punathil Reviewed-By: Daniel Bevenius Reviewed-By: Minwoo Jung Reviewed-By: Khaidi Chu Reviewed-By: Tobias Nießen --- doc/api/buffer.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/doc/api/buffer.md b/doc/api/buffer.md index 835295763ea876..9583fa15949fd2 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -1442,7 +1442,7 @@ endian format (`readDoubleBE()` returns big endian, `readDoubleLE()` returns little endian). Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Examples: @@ -1479,7 +1479,7 @@ endian format (`readFloatBE()` returns big endian, `readFloatLE()` returns little endian). Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Examples: @@ -1513,7 +1513,7 @@ added: v0.5.0 Reads a signed 8-bit integer from `buf` at the specified `offset`. Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Integers read from a `Buffer` are interpreted as two's complement signed values. @@ -1548,7 +1548,7 @@ the specified endian format (`readInt16BE()` returns big endian, `readInt16LE()` returns little endian). Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Integers read from a `Buffer` are interpreted as two's complement signed values. @@ -1583,7 +1583,7 @@ the specified endian format (`readInt32BE()` returns big endian, `readInt32LE()` returns little endian). Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Integers read from a `Buffer` are interpreted as two's complement signed values. @@ -1621,7 +1621,7 @@ and interprets the result as a two's complement signed value. Supports up to 48 bits of accuracy. Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Examples: @@ -1650,7 +1650,7 @@ added: v0.5.0 Reads an unsigned 8-bit integer from `buf` at the specified `offset`. Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Examples: @@ -1683,7 +1683,7 @@ specified endian format (`readUInt16BE()` returns big endian, `readUInt16LE()` returns little endian). Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Examples: @@ -1722,7 +1722,7 @@ specified endian format (`readUInt32BE()` returns big endian, `readUInt32LE()` returns little endian). Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Examples: @@ -1758,7 +1758,7 @@ and interprets the result as an unsigned integer. Supports up to 48 bits of accuracy. Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Examples: @@ -2083,7 +2083,7 @@ endian). `value` *should* be a valid 64-bit double. Behavior is undefined when `value` is anything other than a 64-bit double. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. Examples: @@ -2119,7 +2119,7 @@ endian). `value` *should* be a valid 32-bit float. Behavior is undefined when `value` is anything other than a 32-bit float. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. Examples: @@ -2153,7 +2153,7 @@ signed 8-bit integer. Behavior is undefined when `value` is anything other than a signed 8-bit integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. `value` is interpreted and written as a two's complement signed integer. @@ -2187,7 +2187,7 @@ endian). `value` *should* be a valid signed 16-bit integer. Behavior is undefine when `value` is anything other than a signed 16-bit integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. `value` is interpreted and written as a two's complement signed integer. @@ -2221,7 +2221,7 @@ endian). `value` *should* be a valid signed 32-bit integer. Behavior is undefine when `value` is anything other than a signed 32-bit integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. `value` is interpreted and written as a two's complement signed integer. @@ -2256,7 +2256,7 @@ Supports up to 48 bits of accuracy. Behavior is undefined when `value` is anything other than a signed integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. Examples: @@ -2290,7 +2290,7 @@ valid unsigned 8-bit integer. Behavior is undefined when `value` is anything other than an unsigned 8-bit integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. Examples: @@ -2324,7 +2324,7 @@ endian). `value` should be a valid unsigned 16-bit integer. Behavior is undefined when `value` is anything other than an unsigned 16-bit integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. Examples: @@ -2362,7 +2362,7 @@ endian). `value` should be a valid unsigned 32-bit integer. Behavior is undefined when `value` is anything other than an unsigned 32-bit integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. Examples: @@ -2400,7 +2400,7 @@ Supports up to 48 bits of accuracy. Behavior is undefined when `value` is anything other than an unsigned integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. Examples: From 1505b71dab6c4a0f9b9fc6175b4b628344195ff8 Mon Sep 17 00:00:00 2001 From: Leko Date: Fri, 12 Jan 2018 00:48:17 +0900 Subject: [PATCH 09/24] doc: add Leko to collaborators PR-URL: https://github.com/nodejs/node/pull/18117 Reviewed-By: Joyee Cheung Reviewed-By: Vse Mozhet Byt Reviewed-By: Colin Ihrig Reviewed-By: Yuta Hiroto Reviewed-By: Daijiro Wachi Reviewed-By: Richard Lau --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 43d2bad78234b3..14bc506347a419 100644 --- a/README.md +++ b/README.md @@ -408,8 +408,8 @@ For more information about the governance of the Node.js project, see **Kunal Pathak** <kunal.pathak@microsoft.com> * [lance](https://github.com/lance) - **Lance Ball** <lball@redhat.com> -* [lucamaraschi](https://github.com/lucamaraschi) - -**Luca Maraschi** <luca.maraschi@gmail.com> (he/him) +* [Leko](https://github.com/Leko) - +**Shingo Inoue** <leko.noor@gmail.com> (he/him) * [lpinca](https://github.com/lpinca) - **Luigi Pinca** <luigipinca@gmail.com> (he/him) * [lucamaraschi](https://github.com/lucamaraschi) - From 8f9362d6e83d540767354e608da450d2ee9d7f83 Mon Sep 17 00:00:00 2001 From: Jon Moss Date: Thu, 26 Oct 2017 19:53:47 -0400 Subject: [PATCH 10/24] doc: add documentation for deprecation properties PR-URL: https://github.com/nodejs/node/pull/16539 Fixes: https://github.com/nodejs/node/issues/16394 Reviewed-By: James M Snell Reviewed-By: Anatoli Papirovski Reviewed-By: Colin Ihrig --- doc/api/process.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/doc/api/process.md b/doc/api/process.md index 4d0745491de2a3..c9aebfa8d2cce4 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -1300,6 +1300,19 @@ event loop **before** additional I/O is processed. As a result, recursively setting nextTick callbacks will block any I/O from happening, just like a `while(true);` loop. +## process.noDeprecation + + +* {boolean} + +The `process.noDeprecation` property indicates whether the `--no-deprecation` +flag is set on the current Node.js process. See the documentation for +the [`warning` event][process_warning] and the +[`emitWarning` method][process_emit_warning] for more information about this +flag's behavior. + ## process.pid + +* {boolean} + +The `process.throwDeprecation` property indicates whether the +`--throw-deprecation` flag is set on the current Node.js process. See the +documentation for the [`warning` event][process_warning] and the +[`emitWarning` method][process_emit_warning] for more information about this +flag's behavior. + ## process.title + +* {boolean} + +The `process.traceDeprecation` property indicates whether the +`--trace-deprecation` flag is set on the current Node.js process. See the +documentation for the [`warning` event][process_warning] and the +[`emitWarning` method][process_emit_warning] for more information about this +flag's behavior. + ## process.umask([mask]) -* `timeout` {number} Milliseconds before a request is considered to be timed out. +* `timeout` {number} Milliseconds before a request times out. * `callback` {Function} Optional function to be called when a timeout occurs. Same as binding to the `timeout` event. Once a socket is assigned to this request and is connected diff --git a/doc/api/readline.md b/doc/api/readline.md index 06a8b86205e55c..b88c37e5bdbfa3 100644 --- a/doc/api/readline.md +++ b/doc/api/readline.md @@ -60,8 +60,8 @@ The `'close'` event is emitted when one of the following occur: The listener function is called without passing any arguments. -The `readline.Interface` instance should be considered to be "finished" once -the `'close'` event is emitted. +The `readline.Interface` instance is finished once the `'close'` event is +emitted. ### Event: 'line'