throw simpler errors on some invalid inputs
authorJustin Wind <justin.wind+git@gmail.com>
Sat, 26 Mar 2022 21:59:30 +0000 (14:59 -0700)
committerJustin Wind <justin.wind+git@gmail.com>
Sat, 26 Mar 2022 21:59:30 +0000 (14:59 -0700)
lib/common.js
lib/mystery-box.js
test/lib/common.js
test/lib/mystery-box.js

index fb3ec979524e668bfc5b85dded22a42c56117f41..a47226f6e76fe355416380f3a77db24450481783 100644 (file)
@@ -25,6 +25,9 @@ const fileScope = (filename) => {
  * @returns {String}
  */
 const base64ToBase64URL = (input) => {
+  if (!input) {
+    return input;
+  }
   return input
     .replace(/=/g, '')
     .replace(/\+/g, '-')
@@ -38,6 +41,9 @@ const base64ToBase64URL = (input) => {
  * @returns {String}
  */
 const base64URLToBase64 = (input) => {
+  if (!input) {
+    return input;
+  }
   return base64RePad(input)
     .replace(/-/g, '+')
     .replace(/_/, '/');
index be12245538fd966172e88b5f7266dd0a4d949a45..6198cc816484b406804cf4a4cdd3c84685bce60e 100644 (file)
@@ -208,6 +208,10 @@ class MysteryBox {
       end: 0,
     };
 
+    if (!box) {
+      throw new RangeError('nothing to unpack');
+    }
+
     const raw = Buffer.from(common.base64URLToBase64(box), 'base64');
     let offset = 0;
 
@@ -219,6 +223,11 @@ class MysteryBox {
     const v = this.versionParameters[version];
     offset += v.versionBytes;
 
+    const minBytes = v.versionBytes + v.flagsBytes + v.ivBytes + v.saltBytes + v.tagBytes;
+    if (raw.length < minBytes) {
+      throw new RangeError('not enough to unpack');
+    }
+
     const flags = raw.slice(offset, offset + v.flagsBytes).readUInt8(0);
     offset += v.flagsBytes;
 
index 9b4615fa9c0bc4d72e0bd7f77b5a5c113cb04090..f5df10c779e1054b0881d701e382f4164f53ab1d 100644 (file)
@@ -26,6 +26,10 @@ describe('Common', function () {
       const result = common.base64ToBase64URL(b64);
       assert.strictEqual(result, expected);
     });
+    it('covers empty', function () {
+      const result = common.base64ToBase64URL(undefined);
+      assert.strictEqual(result, undefined);
+    });
   }); // base64ToBase64URL
 
   describe('base64URLToBase64', function () {
@@ -35,6 +39,10 @@ describe('Common', function () {
       const result = common.base64URLToBase64(b64url);
       assert.strictEqual(result, expected);
     });
+    it('covers empty', function () {
+      const result = common.base64URLToBase64(undefined);
+      assert.strictEqual(result, undefined);
+    });
   }); // base64URLToBase64
 
   describe('base64RePad', function () {
index 8d228e6e25d4a5044b99bb889036f7be38a93d48..a6e69b91f25ae0553dee526649e9ae51e103ef14 100644 (file)
@@ -161,6 +161,26 @@ describe('MysteryBox', function () {
       const decryptedResult = await mb.unpack(encryptedResult);
       assert.deepStrictEqual(decryptedResult, object);
     });
+
+    it('handles undefined', async function () {
+      try {
+        await mb.unpack();
+        assert.fail(noExpectedException);
+      } catch (e) {
+        assert(e instanceof RangeError, noExpectedException);
+      }
+    });
+
+    it('handles incomplete', async function () {
+      const encryptedResult = await mb.pack({ foo: 'bar' });
+      try {
+        await mb.unpack(encryptedResult.slice(0, 6));
+        assert.fail(noExpectedException);
+      } catch (e) {
+        assert(e instanceof RangeError, noExpectedException);
+      }
+    });
+
   }); // pack, unpack
 
 }); // MysteryBox
\ No newline at end of file