Extracted from https://github.com/nodejs/node/pull/66282 diff --git a/src/node_sockaddr.cc b/src/node_sockaddr.cc index 3f903f548e17..7c2285de32dd 100644 --- a/src/node_sockaddr.cc +++ b/src/node_sockaddr.cc @@ -1046,8 +1046,8 @@ bool SocketAddressBlockListWrap::FastCheckString( // FastOneByteString is not NUL-terminated. Copy onto the stack // before any other work: a GC would invalidate `address`. // - // uv_ip6_addr only needs the address part (≤39 chars) plus an - // optional %zone. A zone longer than UV_IF_NAMESIZE is unknown + // uv_ip6_addr only needs the address part (< INET6_ADDRSTRLEN chars) + // plus an optional %zone. A zone longer than UV_IF_NAMESIZE is unknown // (scope_id 0), same as omitting it. Keep that behavior when the // full string does not fit so Fast API and CheckString agree. constexpr size_t kMax = INET6_ADDRSTRLEN + UV_IF_NAMESIZE; @@ -1058,14 +1058,14 @@ bool SocketAddressBlockListWrap::FastCheckString( } else if (family == AF_INET6) { // uv_ip4_addr rejects %zone. Only IPv6 may drop an overlong zone // (unknown zone → scope_id 0, same as uv_ip6_addr). - // uv_ip6_addr copies the address part into a 40-byte buffer - // (39 chars + NUL). A 40+ char prefix (mixed notation) is - // truncated and fails inet_pton — do not keep the full prefix. + // uv_ip6_addr copies the address part into an INET6_ADDRSTRLEN + // buffer and truncates a longer one to INET6_ADDRSTRLEN - 1 chars + // before inet_pton. Do the same so both paths parse the same prefix. const char* percent = static_cast(memchr(address.data, '%', address.length)); if (percent == nullptr) return false; - const size_t addr_len = static_cast(percent - address.data); - if (addr_len >= 40) return false; + size_t addr_len = static_cast(percent - address.data); + if (addr_len >= INET6_ADDRSTRLEN) addr_len = INET6_ADDRSTRLEN - 1; memcpy(buf, address.data, addr_len); buf[addr_len] = '\0'; } else { diff --git a/test/parallel/test-blocklist.js b/test/parallel/test-blocklist.js index b0fe4303bfb2..c548917b1c77 100644 --- a/test/parallel/test-blocklist.js +++ b/test/parallel/test-blocklist.js @@ -883,12 +883,17 @@ const util = require('util'); blockList.addAddress('1.1.1.1'); assert.strictEqual(blockList.check(`1.1.1.1%${'z'.repeat(200)}`), false); - // Mixed-notation IPv6 is 45 chars. uv_ip6_addr truncates the - // address part to 39 when a zone is present, so this is a miss. + // Mixed-notation IPv6 is 45 chars. uv_ip6_addr keeps up to + // INET6_ADDRSTRLEN - 1 chars of the address part when a zone is + // present, so this is a hit on libuv 1.53+. const mixed = 'ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255'; blockList.addAddress(mixed, 'ipv6'); assert.strictEqual(blockList.check(mixed, 'ipv6'), true); - assert.strictEqual(blockList.check(`${mixed}%${'z'.repeat(200)}`, 'ipv6'), false); + const isModernLibuv = ((versionString) => { + const [major, minor] = versionString.split('.', 2).map(Number); + return major >= 1 && minor >= 53; + })(process.versions.uv); + assert.strictEqual(blockList.check(`${mixed}%${'z'.repeat(200)}`, 'ipv6'), isModernLibuv); } // check() family parameter is case-insensitive.