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 <luigipinca@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
25842c5e35
commit
7102ea1559
@ -8,6 +8,7 @@ const {
|
|||||||
Error,
|
Error,
|
||||||
ErrorCaptureStackTrace,
|
ErrorCaptureStackTrace,
|
||||||
FunctionPrototypeCall,
|
FunctionPrototypeCall,
|
||||||
|
NumberParseInt,
|
||||||
ObjectDefineProperties,
|
ObjectDefineProperties,
|
||||||
ObjectDefineProperty,
|
ObjectDefineProperty,
|
||||||
ObjectFreeze,
|
ObjectFreeze,
|
||||||
@ -33,7 +34,9 @@ const {
|
|||||||
SafeSet,
|
SafeSet,
|
||||||
SafeWeakMap,
|
SafeWeakMap,
|
||||||
SafeWeakRef,
|
SafeWeakRef,
|
||||||
|
StringPrototypeIncludes,
|
||||||
StringPrototypeReplace,
|
StringPrototypeReplace,
|
||||||
|
StringPrototypeSlice,
|
||||||
StringPrototypeToLowerCase,
|
StringPrototypeToLowerCase,
|
||||||
StringPrototypeToUpperCase,
|
StringPrototypeToUpperCase,
|
||||||
Symbol,
|
Symbol,
|
||||||
@ -806,6 +809,59 @@ function setupCoverageHooks(dir) {
|
|||||||
return coverageDirectory;
|
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'];
|
const handleTypes = ['TCP', 'TTY', 'UDP', 'FILE', 'PIPE', 'UNKNOWN'];
|
||||||
function guessHandleType(fd) {
|
function guessHandleType(fd) {
|
||||||
@ -872,6 +928,7 @@ module.exports = {
|
|||||||
filterDuplicateStrings,
|
filterDuplicateStrings,
|
||||||
filterOwnProperties,
|
filterOwnProperties,
|
||||||
getConstructorOf,
|
getConstructorOf,
|
||||||
|
getCIDR,
|
||||||
getCWDURL,
|
getCWDURL,
|
||||||
getInternalGlobal,
|
getInternalGlobal,
|
||||||
getStructuredStack,
|
getStructuredStack,
|
||||||
|
56
lib/os.js
56
lib/os.js
@ -24,7 +24,6 @@
|
|||||||
const {
|
const {
|
||||||
ArrayPrototypePush,
|
ArrayPrototypePush,
|
||||||
Float64Array,
|
Float64Array,
|
||||||
NumberParseInt,
|
|
||||||
ObjectDefineProperties,
|
ObjectDefineProperties,
|
||||||
StringPrototypeSlice,
|
StringPrototypeSlice,
|
||||||
SymbolToPrimitive,
|
SymbolToPrimitive,
|
||||||
@ -40,6 +39,7 @@ const {
|
|||||||
},
|
},
|
||||||
hideStackFrames,
|
hideStackFrames,
|
||||||
} = require('internal/errors');
|
} = require('internal/errors');
|
||||||
|
const { getCIDR } = require('internal/util');
|
||||||
const { validateInt32 } = require('internal/validators');
|
const { validateInt32 } = require('internal/validators');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -202,60 +202,6 @@ function endianness() {
|
|||||||
}
|
}
|
||||||
endianness[SymbolToPrimitive] = () => kEndianness;
|
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<string, Array<{
|
* @returns {Record<string, Array<{
|
||||||
* address: string,
|
* address: string,
|
||||||
|
23
test/parallel/test-internal-util-getCIDR.js
Normal file
23
test/parallel/test-internal-util-getCIDR.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Flags: --expose-internals
|
||||||
|
'use strict';
|
||||||
|
require('../common');
|
||||||
|
|
||||||
|
// These are tests that verify that the subnetmask is used
|
||||||
|
// to create the correct CIDR address.
|
||||||
|
// Tests that it returns null if the subnetmask is not in the correct format.
|
||||||
|
// (ref: https://www.rfc-editor.org/rfc/rfc1878)
|
||||||
|
|
||||||
|
const assert = require('node:assert');
|
||||||
|
const { getCIDR } = require('internal/util');
|
||||||
|
|
||||||
|
assert.strictEqual(getCIDR('127.0.0.1', '255.0.0.0', 'IPv4'), '127.0.0.1/8');
|
||||||
|
assert.strictEqual(getCIDR('127.0.0.1', '255.255.0.0', 'IPv4'), '127.0.0.1/16');
|
||||||
|
|
||||||
|
// 242 = 11110010(2)
|
||||||
|
assert.strictEqual(getCIDR('127.0.0.1', '242.0.0.0', 'IPv4'), null);
|
||||||
|
|
||||||
|
assert.strictEqual(getCIDR('::1', 'ffff:ffff:ffff:ffff::', 'IPv6'), '::1/64');
|
||||||
|
assert.strictEqual(getCIDR('::1', 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', 'IPv6'), '::1/128');
|
||||||
|
|
||||||
|
// ff00:ffff = 11111111 00000000 : 11111111 11111111(2)
|
||||||
|
assert.strictEqual(getCIDR('::1', 'ffff:ff00:ffff::', 'IPv6'), null);
|
Loading…
x
Reference in New Issue
Block a user