Skip to content

Commit 49e624f

Browse files
HBSPSmarco-ippolito
authored andcommitted
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: #57324 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 275ea8e commit 49e624f

File tree

3 files changed

+81
-55
lines changed

3 files changed

+81
-55
lines changed

lib/internal/util.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const {
99
Error,
1010
ErrorCaptureStackTrace,
1111
FunctionPrototypeCall,
12+
NumberParseInt,
1213
ObjectDefineProperties,
1314
ObjectDefineProperty,
1415
ObjectGetOwnPropertyDescriptor,
@@ -34,7 +35,9 @@ const {
3435
SafeSet,
3536
SafeWeakMap,
3637
SafeWeakRef,
38+
StringPrototypeIncludes,
3739
StringPrototypeReplace,
40+
StringPrototypeSlice,
3841
StringPrototypeToLowerCase,
3942
StringPrototypeToUpperCase,
4043
Symbol,
@@ -825,6 +828,59 @@ function setupCoverageHooks(dir) {
825828
return coverageDirectory;
826829
}
827830

831+
// Returns the number of ones in the binary representation of the decimal
832+
// number.
833+
function countBinaryOnes(n) {
834+
// Count the number of bits set in parallel, which is faster than looping
835+
n = n - ((n >>> 1) & 0x55555555);
836+
n = (n & 0x33333333) + ((n >>> 2) & 0x33333333);
837+
return ((n + (n >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24;
838+
}
839+
840+
function getCIDR(address, netmask, family) {
841+
let ones = 0;
842+
let split = '.';
843+
let range = 10;
844+
let groupLength = 8;
845+
let hasZeros = false;
846+
let lastPos = 0;
847+
848+
if (family === 'IPv6') {
849+
split = ':';
850+
range = 16;
851+
groupLength = 16;
852+
}
853+
854+
for (let i = 0; i < netmask.length; i++) {
855+
if (netmask[i] !== split) {
856+
if (i + 1 < netmask.length) {
857+
continue;
858+
}
859+
i++;
860+
}
861+
const part = StringPrototypeSlice(netmask, lastPos, i);
862+
lastPos = i + 1;
863+
if (part !== '') {
864+
if (hasZeros) {
865+
if (part !== '0') {
866+
return null;
867+
}
868+
} else {
869+
const binary = NumberParseInt(part, range);
870+
const binaryOnes = countBinaryOnes(binary);
871+
ones += binaryOnes;
872+
if (binaryOnes !== groupLength) {
873+
if (StringPrototypeIncludes(binary.toString(2), '01')) {
874+
return null;
875+
}
876+
hasZeros = true;
877+
}
878+
}
879+
}
880+
}
881+
882+
return `${address}/${ones}`;
883+
}
828884

829885
const handleTypes = ['TCP', 'TTY', 'UDP', 'FILE', 'PIPE', 'UNKNOWN'];
830886
function guessHandleType(fd) {
@@ -889,6 +945,7 @@ module.exports = {
889945
filterDuplicateStrings,
890946
filterOwnProperties,
891947
getConstructorOf,
948+
getCIDR,
892949
getCWDURL,
893950
getInternalGlobal,
894951
getStructuredStack,

lib/os.js

Lines changed: 1 addition & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
const {
2525
ArrayPrototypePush,
2626
Float64Array,
27-
NumberParseInt,
2827
ObjectDefineProperties,
2928
StringPrototypeEndsWith,
3029
StringPrototypeSlice,
@@ -41,6 +40,7 @@ const {
4140
},
4241
hideStackFrames,
4342
} = require('internal/errors');
43+
const { getCIDR } = require('internal/util');
4444
const { validateInt32 } = require('internal/validators');
4545

4646
const {
@@ -208,60 +208,6 @@ function endianness() {
208208
}
209209
endianness[SymbolToPrimitive] = () => kEndianness;
210210

211-
// Returns the number of ones in the binary representation of the decimal
212-
// number.
213-
function countBinaryOnes(n) {
214-
// Count the number of bits set in parallel, which is faster than looping
215-
n = n - ((n >>> 1) & 0x55555555);
216-
n = (n & 0x33333333) + ((n >>> 2) & 0x33333333);
217-
return ((n + (n >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24;
218-
}
219-
220-
function getCIDR(address, netmask, family) {
221-
let ones = 0;
222-
let split = '.';
223-
let range = 10;
224-
let groupLength = 8;
225-
let hasZeros = false;
226-
let lastPos = 0;
227-
228-
if (family === 'IPv6') {
229-
split = ':';
230-
range = 16;
231-
groupLength = 16;
232-
}
233-
234-
for (let i = 0; i < netmask.length; i++) {
235-
if (netmask[i] !== split) {
236-
if (i + 1 < netmask.length) {
237-
continue;
238-
}
239-
i++;
240-
}
241-
const part = StringPrototypeSlice(netmask, lastPos, i);
242-
lastPos = i + 1;
243-
if (part !== '') {
244-
if (hasZeros) {
245-
if (part !== '0') {
246-
return null;
247-
}
248-
} else {
249-
const binary = NumberParseInt(part, range);
250-
const binaryOnes = countBinaryOnes(binary);
251-
ones += binaryOnes;
252-
if (binaryOnes !== groupLength) {
253-
if ((binary & 1) !== 0) {
254-
return null;
255-
}
256-
hasZeros = true;
257-
}
258-
}
259-
}
260-
}
261-
262-
return `${address}/${ones}`;
263-
}
264-
265211
/**
266212
* @returns {Record<string, Array<{
267213
* address: string,
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Flags: --expose-internals
2+
'use strict';
3+
require('../common');
4+
5+
// These are tests that verify that the subnetmask is used
6+
// to create the correct CIDR address.
7+
// Tests that it returns null if the subnetmask is not in the correct format.
8+
// (ref: https://www.rfc-editor.org/rfc/rfc1878)
9+
10+
const assert = require('node:assert');
11+
const { getCIDR } = require('internal/util');
12+
13+
assert.strictEqual(getCIDR('127.0.0.1', '255.0.0.0', 'IPv4'), '127.0.0.1/8');
14+
assert.strictEqual(getCIDR('127.0.0.1', '255.255.0.0', 'IPv4'), '127.0.0.1/16');
15+
16+
// 242 = 11110010(2)
17+
assert.strictEqual(getCIDR('127.0.0.1', '242.0.0.0', 'IPv4'), null);
18+
19+
assert.strictEqual(getCIDR('::1', 'ffff:ffff:ffff:ffff::', 'IPv6'), '::1/64');
20+
assert.strictEqual(getCIDR('::1', 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', 'IPv6'), '::1/128');
21+
22+
// ff00:ffff = 11111111 00000000 : 11111111 11111111(2)
23+
assert.strictEqual(getCIDR('::1', 'ffff:ff00:ffff::', 'IPv6'), null);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy