Repository: whitequark/ipaddr.js
Pull request #134 (2020-01-23 14:03:14)

Add support for classfull IPv4
Address issue https://github.com/whitequark/ipaddr.js/issues/133

whitequark: Looks like there's a three octet form too, see [here](https://linux.die.net/man/3/inet_ntoa).
Taiki-San: Indeed, Internet is a weird place...
I feel like we probably could compact the three (four if we count the three octet form) codepath in one or two, but I'm not sure it's worth the time to avoid code duplication. Any strong feeling one way or another?
whitequark: Just duplicate it.
Taiki-San: Ok, just pushed support for 3 octet IPv4

Patch:
diff --git a/lib/ipaddr.js b/lib/ipaddr.js
index 814becb..f28708c 100644
--- a/lib/ipaddr.js
+++ b/lib/ipaddr.js
@@ -6,6 +6,8 @@
     const ipv4Part = '(0?\\d+|0x[a-f0-9]+)';
     const ipv4Regexes = {
         fourOctet: new RegExp(`^${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}$`, 'i'),
+        threeOctet: new RegExp(`^${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}$`, 'i'),
+        twoOctet: new RegExp(`^${ipv4Part}\\.${ipv4Part}$`, 'i'),
         longValue: new RegExp(`^${ipv4Part}$`, 'i')
     };
 
@@ -348,6 +350,40 @@
 
                 return results;
             })()).reverse();
+        } else if ((match = string.match(ipv4Regexes.twoOctet))) {
+            return (function () {
+                const ref = match.slice(1, 4);
+                const results = [];
+
+                value = parseIntAuto(ref[1]);
+                if (value > 0xffffff || value < 0) {
+                    throw new Error('ipaddr: address outside defined range');
+                }
+
+                results.push(parseIntAuto(ref[0]));
+                results.push((value >> 16) & 0xff);
+                results.push((value >>  8) & 0xff);
+                results.push( value        & 0xff);
+
+                return results;
+            })();
+        } else if ((match = string.match(ipv4Regexes.threeOctet))) {
+            return (function () {
+                const ref = match.slice(1, 5);
+                const results = [];
+
+                value = parseIntAuto(ref[2]);
+                if (value > 0xffff || value < 0) {
+                    throw new Error('ipaddr: address outside defined range');
+                }
+
+                results.push(parseIntAuto(ref[0]));
+                results.push(parseIntAuto(ref[1]));
+                results.push((value >> 8) & 0xff);
+                results.push( value       & 0xff);
+
+                return results;
+            })();
         } else {
             return null;
         }


Test patch:
diff --git a/test/ipaddr.test.js b/test/ipaddr.test.js
index 73be07f..18fad7c 100644
--- a/test/ipaddr.test.js
+++ b/test/ipaddr.test.js
@@ -69,6 +69,8 @@ describe('ipaddr', () => {
         assert.deepEqual(ipaddr.IPv4.parse('0xc0a80101').octets, [192, 168, 1, 1]);
         assert.deepEqual(ipaddr.IPv4.parse('030052000401').octets, [192, 168, 1, 1]);
         assert.deepEqual(ipaddr.IPv4.parse('3232235777').octets, [192, 168, 1, 1]);
+        assert.deepEqual(ipaddr.IPv4.parse('127.42.258').octets, [127, 42, 1, 2]);
+        assert.deepEqual(ipaddr.IPv4.parse('127.66051').octets, [127, 1, 2, 3]);
         done();
     })
 
@@ -76,6 +78,13 @@ describe('ipaddr', () => {
         assert.throws(() => {
             ipaddr.IPv4.parse('10.0.0.wtf');
         });
+        assert.throws(() => {
+            ipaddr.IPv4.parse('8.0x1ffffff');
+        });
+        assert.throws(() => {
+            ipaddr.IPv4.parse('8.8.0x1ffff');
+        });
+
         done();
     })