From 3a14b7e2901f449a9f50e79b1e13606dc58fce3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Ara=C3=BAjo?= Date: Thu, 23 Apr 2026 11:45:59 -0300 Subject: [PATCH 1/3] net: fix SocketAddress.parse default port handling --- lib/internal/socketaddress.js | 20 ++++++++++---------- test/parallel/test-socketaddress.js | 3 +++ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/internal/socketaddress.js b/lib/internal/socketaddress.js index 724ffd90cf77f1..ee9bec92524252 100644 --- a/lib/internal/socketaddress.js +++ b/lib/internal/socketaddress.js @@ -1,6 +1,7 @@ 'use strict'; const { + NumberParseInt, ObjectSetPrototypeOf, Symbol, } = primordials; @@ -153,18 +154,17 @@ class SocketAddress { // other pieces here that do... the destucturing, the SocketAddress // constructor, etc. So we wrap this in a try/catch to be safe. try { - const { - hostname: address, - port, - } = URLParse(`http://${input}`); + // url.port strips default HTTP ports (e.g. 80), so parse the port from + // the raw input string instead. + const { hostname: address } = URLParse(`http://${input}`); if (address.startsWith('[') && address.endsWith(']')) { - return new SocketAddress({ - address: address.slice(1, -1), - port: port | 0, - family: 'ipv6', - }); + const portStart = input.indexOf(']:'); + const port = portStart !== -1 ? NumberParseInt(input.slice(portStart + 2), 10) || 0 : 0; + return new SocketAddress({ address: address.slice(1, -1), port, family: 'ipv6' }); } - return new SocketAddress({ address, port: port | 0 }); + const lastColon = input.lastIndexOf(':'); + const port = lastColon !== -1 ? NumberParseInt(input.slice(lastColon + 1), 10) || 0 : 0; + return new SocketAddress({ address, port }); } catch { // Ignore errors here. Return undefined if the input cannot // be successfully parsed or is not a proper socket address. diff --git a/test/parallel/test-socketaddress.js b/test/parallel/test-socketaddress.js index cf29795a48fcfa..f84ac3965b5f77 100644 --- a/test/parallel/test-socketaddress.js +++ b/test/parallel/test-socketaddress.js @@ -148,6 +148,9 @@ describe('net.SocketAddress...', () => { { input: '0x.0x.0', address: '0.0.0.0', port: 0, family: 'ipv4' }, { input: '[1:0::]', address: '1::', port: 0, family: 'ipv6' }, { input: '[1::8]:123', address: '1::8', port: 123, family: 'ipv6' }, + { input: '127.0.0.1:80', address: '127.0.0.1', port: 80, family: 'ipv4' }, + { input: '127.0.0.1:443', address: '127.0.0.1', port: 443, family: 'ipv4' }, + { input: '[::1]:80', address: '::1', port: 80, family: 'ipv6' }, ]; good.forEach((i) => { From b969a359f621ec9c971b6aa50242175bd65b0d47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Ara=C3=BAjo?= Date: Thu, 23 Apr 2026 11:51:21 -0300 Subject: [PATCH 2/3] net: refactor logic branches --- lib/internal/socketaddress.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/internal/socketaddress.js b/lib/internal/socketaddress.js index ee9bec92524252..116d5ba20dee36 100644 --- a/lib/internal/socketaddress.js +++ b/lib/internal/socketaddress.js @@ -157,14 +157,19 @@ class SocketAddress { // url.port strips default HTTP ports (e.g. 80), so parse the port from // the raw input string instead. const { hostname: address } = URLParse(`http://${input}`); - if (address.startsWith('[') && address.endsWith(']')) { - const portStart = input.indexOf(']:'); - const port = portStart !== -1 ? NumberParseInt(input.slice(portStart + 2), 10) || 0 : 0; - return new SocketAddress({ address: address.slice(1, -1), port, family: 'ipv6' }); - } - const lastColon = input.lastIndexOf(':'); - const port = lastColon !== -1 ? NumberParseInt(input.slice(lastColon + 1), 10) || 0 : 0; - return new SocketAddress({ address, port }); + + const isIPv6 = address.startsWith('[') && address.endsWith(']'); + + // For IPv6, indexOf(']:') + 1 points at ':' (or 0 if absent, treated as no port). + // For IPv4, lastIndexOf(':') points at ':' (or -1 if absent). + const sepIdx = isIPv6 ? input.indexOf(']:') + 1 : input.lastIndexOf(':'); + const port = sepIdx > 0 ? NumberParseInt(input.slice(sepIdx + 1), 10) || 0 : 0; + + return new SocketAddress({ + address: isIPv6 ? address.slice(1, -1) : address, + port, + family: isIPv6 ? 'ipv6' : 'ipv4', + }); } catch { // Ignore errors here. Return undefined if the input cannot // be successfully parsed or is not a proper socket address. From b274a644838ade08c9e7d583f27f11fcd41c738b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Ara=C3=BAjo?= Date: Thu, 23 Apr 2026 11:53:53 -0300 Subject: [PATCH 3/3] net: add more ipv6 cases --- test/parallel/test-socketaddress.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/parallel/test-socketaddress.js b/test/parallel/test-socketaddress.js index f84ac3965b5f77..e1f98bea01a8b2 100644 --- a/test/parallel/test-socketaddress.js +++ b/test/parallel/test-socketaddress.js @@ -151,6 +151,7 @@ describe('net.SocketAddress...', () => { { input: '127.0.0.1:80', address: '127.0.0.1', port: 80, family: 'ipv4' }, { input: '127.0.0.1:443', address: '127.0.0.1', port: 443, family: 'ipv4' }, { input: '[::1]:80', address: '::1', port: 80, family: 'ipv6' }, + { input: '[::1]:443', address: '::1', port: 443, family: 'ipv6' }, ]; good.forEach((i) => {