From 1d6ca80c7e8be42a74852047289e6151b467cffb Mon Sep 17 00:00:00 2001 From: Michael Dokolin Date: Wed, 25 Aug 2021 17:01:24 +0200 Subject: [PATCH] [Data] Fix CIDR mask to avoid using big integers (#109789) (#110045) --- .../search/aggs/buckets/lib/cidr_mask.ts | 41 +++++++++---------- .../search/aggs/utils/ip_address.test.ts | 15 ------- .../common/search/aggs/utils/ip_address.ts | 12 ------ 3 files changed, 19 insertions(+), 49 deletions(-) diff --git a/src/plugins/data/common/search/aggs/buckets/lib/cidr_mask.ts b/src/plugins/data/common/search/aggs/buckets/lib/cidr_mask.ts index 93ccbffaeb89..482885861c65 100644 --- a/src/plugins/data/common/search/aggs/buckets/lib/cidr_mask.ts +++ b/src/plugins/data/common/search/aggs/buckets/lib/cidr_mask.ts @@ -10,44 +10,41 @@ import ipaddr from 'ipaddr.js'; import { IpAddress } from '../../utils'; export class CidrMask { + private static getNetmask(size: number, prefix: number) { + return new Array(size).fill(255).map((byte, index) => { + const bytePrefix = 8 - Math.min(Math.max(prefix - index * 8, 0), 8); + + // eslint-disable-next-line no-bitwise + return (byte >> bytePrefix) << bytePrefix; + }); + } + private address: number[]; - private netmask: number; + private netmask: number[]; + private prefix: number; constructor(cidr: string) { try { - const [address, netmask] = ipaddr.parseCIDR(cidr); + const [address, prefix] = ipaddr.parseCIDR(cidr); this.address = address.toByteArray(); - this.netmask = netmask; + this.netmask = CidrMask.getNetmask(this.address.length, prefix); + this.prefix = prefix; } catch { throw Error('Invalid CIDR mask: ' + cidr); } } private getBroadcastAddress() { - /* eslint-disable no-bitwise */ - const netmask = (1n << BigInt(this.address.length * 8 - this.netmask)) - 1n; - const broadcast = this.address.map((byte, index) => { - const offset = BigInt(this.address.length - index - 1) * 8n; - const mask = Number((netmask >> offset) & 255n); - - return byte | mask; - }); - /* eslint-enable no-bitwise */ + // eslint-disable-next-line no-bitwise + const broadcast = this.address.map((byte, index) => byte | (this.netmask[index] ^ 255)); return new IpAddress(broadcast).toString(); } private getNetworkAddress() { - /* eslint-disable no-bitwise */ - const netmask = (1n << BigInt(this.address.length * 8 - this.netmask)) - 1n; - const network = this.address.map((byte, index) => { - const offset = BigInt(this.address.length - index - 1) * 8n; - const mask = Number((netmask >> offset) & 255n) ^ 255; - - return byte & mask; - }); - /* eslint-enable no-bitwise */ + // eslint-disable-next-line no-bitwise + const network = this.address.map((byte, index) => byte & this.netmask[index]); return new IpAddress(network).toString(); } @@ -60,6 +57,6 @@ export class CidrMask { } toString() { - return `${new IpAddress(this.address)}/${this.netmask}`; + return `${new IpAddress(this.address)}/${this.prefix}`; } } diff --git a/src/plugins/data/common/search/aggs/utils/ip_address.test.ts b/src/plugins/data/common/search/aggs/utils/ip_address.test.ts index 966408cf6fe2..0d51714f114b 100644 --- a/src/plugins/data/common/search/aggs/utils/ip_address.test.ts +++ b/src/plugins/data/common/search/aggs/utils/ip_address.test.ts @@ -37,21 +37,6 @@ describe('IpAddress', () => { }); }); - describe('valueOf', () => { - it.each` - address | expected - ${'0.0.0.0'} | ${'0'} - ${'0.0.0.1'} | ${'1'} - ${'126.45.211.34'} | ${'2116932386'} - ${'ffff::'} | ${'340277174624079928635746076935438991360'} - `( - 'should return $expected as a decimal representation of $address', - ({ address, expected }) => { - expect(new IpAddress(address).valueOf().toString()).toBe(expected); - } - ); - }); - describe('toString()', () => { it.each` address | expected diff --git a/src/plugins/data/common/search/aggs/utils/ip_address.ts b/src/plugins/data/common/search/aggs/utils/ip_address.ts index 2fffbc468046..ba7972588c54 100644 --- a/src/plugins/data/common/search/aggs/utils/ip_address.ts +++ b/src/plugins/data/common/search/aggs/utils/ip_address.ts @@ -32,16 +32,4 @@ export class IpAddress { return this.value.toString(); } - - valueOf(): number | bigint { - const value = this.value - .toByteArray() - .reduce((result, octet) => result * 256n + BigInt(octet), 0n); - - if (value > Number.MAX_SAFE_INTEGER) { - return value; - } - - return Number(value); - } }