Skip to content

Commit 8cd9822

Browse files
HBSPSRafaelGSS
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 74473af commit 8cd9822

3 files changed

Lines changed: 81 additions & 55 deletions

File tree

‎lib/internal/util.js‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const {
88
Error,
99
ErrorCaptureStackTrace,
1010
FunctionPrototypeCall,
11+
NumberParseInt,
1112
ObjectDefineProperties,
1213
ObjectDefineProperty,
1314
ObjectFreeze,
@@ -33,7 +34,9 @@ const {
3334
SafeSet,
3435
SafeWeakMap,
3536
SafeWeakRef,
37+
StringPrototypeIncludes,
3638
StringPrototypeReplace,
39+
StringPrototypeSlice,
3740
StringPrototypeToLowerCase,
3841
StringPrototypeToUpperCase,
3942
Symbol,
@@ -806,6 +809,59 @@ function setupCoverageHooks(dir) {
806809
returncoverageDirectory;
807810
}
808811

812+
// Returns the number of ones in the binary representation of the decimal
813+
// number.
814+
functioncountBinaryOnes(n){
815+
// Count the number of bits set in parallel, which is faster than looping
816+
n=n-((n>>>1)&0x55555555);
817+
n=(n&0x33333333)+((n>>>2)&0x33333333);
818+
return((n+(n>>>4)&0xF0F0F0F)*0x1010101)>>>24;
819+
}
820+
821+
functiongetCIDR(address,netmask,family){
822+
letones=0;
823+
letsplit='.';
824+
letrange=10;
825+
letgroupLength=8;
826+
lethasZeros=false;
827+
letlastPos=0;
828+
829+
if(family==='IPv6'){
830+
split=':';
831+
range=16;
832+
groupLength=16;
833+
}
834+
835+
for(leti=0;i<netmask.length;i++){
836+
if(netmask[i]!==split){
837+
if(i+1<netmask.length){
838+
continue;
839+
}
840+
i++;
841+
}
842+
constpart=StringPrototypeSlice(netmask,lastPos,i);
843+
lastPos=i+1;
844+
if(part!==''){
845+
if(hasZeros){
846+
if(part!=='0'){
847+
returnnull;
848+
}
849+
}else{
850+
constbinary=NumberParseInt(part,range);
851+
constbinaryOnes=countBinaryOnes(binary);
852+
ones+=binaryOnes;
853+
if(binaryOnes!==groupLength){
854+
if(StringPrototypeIncludes(binary.toString(2),'01')){
855+
returnnull;
856+
}
857+
hasZeros=true;
858+
}
859+
}
860+
}
861+
}
862+
863+
return`${address}/${ones}`;
864+
}
809865

810866
consthandleTypes=['TCP','TTY','UDP','FILE','PIPE','UNKNOWN'];
811867
functionguessHandleType(fd){
@@ -872,6 +928,7 @@ module.exports = {
872928
filterDuplicateStrings,
873929
filterOwnProperties,
874930
getConstructorOf,
931+
getCIDR,
875932
getCWDURL,
876933
getInternalGlobal,
877934
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
StringPrototypeSlice,
3029
SymbolToPrimitive,
@@ -40,6 +39,7 @@ const {
4039
},
4140
hideStackFrames,
4241
}=require('internal/errors');
42+
const{ getCIDR }=require('internal/util');
4343
const{ validateInt32 }=require('internal/validators');
4444

4545
const{
@@ -202,60 +202,6 @@ function endianness() {
202202
}
203203
endianness[SymbolToPrimitive]=()=>kEndianness;
204204

205-
// Returns the number of ones in the binary representation of the decimal
206-
// number.
207-
functioncountBinaryOnes(n){
208-
// Count the number of bits set in parallel, which is faster than looping
209-
n=n-((n>>>1)&0x55555555);
210-
n=(n&0x33333333)+((n>>>2)&0x33333333);
211-
return((n+(n>>>4)&0xF0F0F0F)*0x1010101)>>>24;
212-
}
213-
214-
functiongetCIDR(address,netmask,family){
215-
letones=0;
216-
letsplit='.';
217-
letrange=10;
218-
letgroupLength=8;
219-
lethasZeros=false;
220-
letlastPos=0;
221-
222-
if(family==='IPv6'){
223-
split=':';
224-
range=16;
225-
groupLength=16;
226-
}
227-
228-
for(leti=0;i<netmask.length;i++){
229-
if(netmask[i]!==split){
230-
if(i+1<netmask.length){
231-
continue;
232-
}
233-
i++;
234-
}
235-
constpart=StringPrototypeSlice(netmask,lastPos,i);
236-
lastPos=i+1;
237-
if(part!==''){
238-
if(hasZeros){
239-
if(part!=='0'){
240-
returnnull;
241-
}
242-
}else{
243-
constbinary=NumberParseInt(part,range);
244-
constbinaryOnes=countBinaryOnes(binary);
245-
ones+=binaryOnes;
246-
if(binaryOnes!==groupLength){
247-
if((binary&1)!==0){
248-
returnnull;
249-
}
250-
hasZeros=true;
251-
}
252-
}
253-
}
254-
}
255-
256-
return`${address}/${ones}`;
257-
}
258-
259205
/**
260206
* @returns {Record<string, Array<{
261207
* 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+
constassert=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)