diff --git a/lib/ipaddr.js b/lib/ipaddr.js index da06924..4e210ed 100644 --- a/lib/ipaddr.js +++ b/lib/ipaddr.js @@ -108,6 +108,16 @@ function matchCIDR (first, second, partSize, cidrBits) { throw new Error('ipaddr: cannot match CIDR for objects with different lengths'); } + const maxCidrBits = first.length * partSize; + + if ( + !Number.isInteger(cidrBits) || + cidrBits < 0 || + cidrBits > maxCidrBits + ) { + throw new Error('ipaddr: invalid CIDR prefix length'); + } + let part = 0; let shift; diff --git a/test/ipaddr.test.js b/test/ipaddr.test.js index ae12d1b..092ccb1 100644 --- a/test/ipaddr.test.js +++ b/test/ipaddr.test.js @@ -106,6 +106,19 @@ describe('ipaddr', () => { equal(addr.match(addr, 32), true); }) + it('rejects invalid IPv4 CIDR prefix lengths in match', () => { + const address = IPv4.parse('8.8.8.8'); + const network = IPv4.parse('192.168.1.0'); + + throws(() => address.match(network, -1)); + throws(() => address.match(network, -0.5)); + throws(() => address.match(network, NaN)); + throws(() => address.match(network, Infinity)); + throws(() => address.match(network, -Infinity)); + throws(() => address.match(network, 24.9)); + throws(() => address.match(network, 33)); + }) + it('parses CIDR reversible', () => { equal(parseCIDR('1.2.3.4/24').toString(), '1.2.3.4/24'); equal(parseCIDR('::1%zone/24').toString(), '::1%zone/24'); @@ -179,6 +192,19 @@ describe('ipaddr', () => { }); }) + it('rejects invalid IPv6 CIDR prefix lengths in match', () => { + const address = IPv6.parse('2001:db8::1'); + const network = IPv6.parse('2001:db8::'); + + throws(() => address.match(network, -1)); + throws(() => address.match(network, -0.5)); + throws(() => address.match(network, NaN)); + throws(() => address.match(network, Infinity)); + throws(() => address.match(network, -Infinity)); + throws(() => address.match(network, 64.9)); + throws(() => address.match(network, 129)); + }) + it('can construct IPv6 from 8bit parts', () => { doesNotThrow(() => { new IPv6([0x20, 0x01, 0xd, 0xb8, 0xf5, 0x3a, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); @@ -566,6 +592,15 @@ describe('ipaddr', () => { equal(subnetMatch(new IPv6([0x2001, 1, 2, 3, 0, 0, 0, 1]), rangelist, false), 'dual64'); }) + it('subnetMatch rejects invalid CIDR prefix lengths', () => { + const address = IPv4.parse('8.8.8.8'); + const network = IPv4.parse('192.168.1.0'); + + throws(() => subnetMatch(address, { internal: [network, -1] }, 'external')); + throws(() => subnetMatch(address, { internal: [network, NaN] }, 'external')); + throws(() => subnetMatch(address, { internal: [network, Infinity] }, 'external')); + }) + it('is able to determine IP address type from byte array input', () => { equal(fromByteArray([0x7f, 0, 0, 1]).kind(), 'ipv4'); equal(fromByteArray([0x20, 0x01, 0xd, 0xb8, 0xf5, 0x3a, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]).kind(), 'ipv6');