From 7102ea1559eb7e84d39bcc4057db9ea09befe090 Mon Sep 17 00:00:00 2001 From: Wiyeong Seo Date: Sun, 20 Apr 2025 00:54:48 -0500 Subject: [PATCH] os: fix netmask format check condition in getCIDR function Modified to check the format of the netmask instead of just checking that each part of the netmask is even PR-URL: https://github.com/nodejs/node/pull/57324 Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- lib/internal/util.js | 57 +++++++++++++++++++++ lib/os.js | 56 +------------------- test/parallel/test-internal-util-getCIDR.js | 23 +++++++++ 3 files changed, 81 insertions(+), 55 deletions(-) create mode 100644 test/parallel/test-internal-util-getCIDR.js diff --git a/lib/internal/util.js b/lib/internal/util.js index e7c9c3c9c0b..6177b151fee 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -8,6 +8,7 @@ const { Error, ErrorCaptureStackTrace, FunctionPrototypeCall, + NumberParseInt, ObjectDefineProperties, ObjectDefineProperty, ObjectFreeze, @@ -33,7 +34,9 @@ const { SafeSet, SafeWeakMap, SafeWeakRef, + StringPrototypeIncludes, StringPrototypeReplace, + StringPrototypeSlice, StringPrototypeToLowerCase, StringPrototypeToUpperCase, Symbol, @@ -806,6 +809,59 @@ function setupCoverageHooks(dir) { return coverageDirectory; } +// Returns the number of ones in the binary representation of the decimal +// number. +function countBinaryOnes(n) { + // Count the number of bits set in parallel, which is faster than looping + n = n - ((n >>> 1) & 0x55555555); + n = (n & 0x33333333) + ((n >>> 2) & 0x33333333); + return ((n + (n >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; +} + +function getCIDR(address, netmask, family) { + let ones = 0; + let split = '.'; + let range = 10; + let groupLength = 8; + let hasZeros = false; + let lastPos = 0; + + if (family === 'IPv6') { + split = ':'; + range = 16; + groupLength = 16; + } + + for (let i = 0; i < netmask.length; i++) { + if (netmask[i] !== split) { + if (i + 1 < netmask.length) { + continue; + } + i++; + } + const part = StringPrototypeSlice(netmask, lastPos, i); + lastPos = i + 1; + if (part !== '') { + if (hasZeros) { + if (part !== '0') { + return null; + } + } else { + const binary = NumberParseInt(part, range); + const binaryOnes = countBinaryOnes(binary); + ones += binaryOnes; + if (binaryOnes !== groupLength) { + if (StringPrototypeIncludes(binary.toString(2), '01')) { + return null; + } + hasZeros = true; + } + } + } + } + + return `${address}/${ones}`; +} const handleTypes = ['TCP', 'TTY', 'UDP', 'FILE', 'PIPE', 'UNKNOWN']; function guessHandleType(fd) { @@ -872,6 +928,7 @@ module.exports = { filterDuplicateStrings, filterOwnProperties, getConstructorOf, + getCIDR, getCWDURL, getInternalGlobal, getStructuredStack, diff --git a/lib/os.js b/lib/os.js index 4f8dda1531b..c44147f0e11 100644 --- a/lib/os.js +++ b/lib/os.js @@ -24,7 +24,6 @@ const { ArrayPrototypePush, Float64Array, - NumberParseInt, ObjectDefineProperties, StringPrototypeSlice, SymbolToPrimitive, @@ -40,6 +39,7 @@ const { }, hideStackFrames, } = require('internal/errors'); +const { getCIDR } = require('internal/util'); const { validateInt32 } = require('internal/validators'); const { @@ -202,60 +202,6 @@ function endianness() { } endianness[SymbolToPrimitive] = () => kEndianness; -// Returns the number of ones in the binary representation of the decimal -// number. -function countBinaryOnes(n) { - // Count the number of bits set in parallel, which is faster than looping - n = n - ((n >>> 1) & 0x55555555); - n = (n & 0x33333333) + ((n >>> 2) & 0x33333333); - return ((n + (n >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; -} - -function getCIDR(address, netmask, family) { - let ones = 0; - let split = '.'; - let range = 10; - let groupLength = 8; - let hasZeros = false; - let lastPos = 0; - - if (family === 'IPv6') { - split = ':'; - range = 16; - groupLength = 16; - } - - for (let i = 0; i < netmask.length; i++) { - if (netmask[i] !== split) { - if (i + 1 < netmask.length) { - continue; - } - i++; - } - const part = StringPrototypeSlice(netmask, lastPos, i); - lastPos = i + 1; - if (part !== '') { - if (hasZeros) { - if (part !== '0') { - return null; - } - } else { - const binary = NumberParseInt(part, range); - const binaryOnes = countBinaryOnes(binary); - ones += binaryOnes; - if (binaryOnes !== groupLength) { - if ((binary & 1) !== 0) { - return null; - } - hasZeros = true; - } - } - } - } - - return `${address}/${ones}`; -} - /** * @returns {Record