msgpackr 1.11.8 → 1.11.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/test.js CHANGED
@@ -30,13 +30,6 @@
30
30
  var sequentialMode = false;
31
31
  var inlineObjectReadThreshold = 2;
32
32
  var readStruct$1, onLoadedStructures$1, onSaveState;
33
- // no-eval build
34
- try {
35
- new Function('');
36
- } catch(error) {
37
- // if eval variants are not supported, do not create inline object readers ever
38
- inlineObjectReadThreshold = Infinity;
39
- }
40
33
 
41
34
  let Unpackr$1 = class Unpackr {
42
35
  constructor(options) {
@@ -506,11 +499,18 @@
506
499
  function readObject() {
507
500
  // This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
508
501
  if (readObject.count++ > inlineObjectReadThreshold) {
509
- let readObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
510
- '({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
502
+ let optimizedReadObject;
503
+ try {
504
+ optimizedReadObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
505
+ '({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
506
+ } catch(error) {
507
+ // in CF workers, the new Function call could begin to fail at any point in time
508
+ inlineObjectReadThreshold = Infinity; // disable going forward
509
+ return readObject(); // recursively try again
510
+ }
511
511
  if (structure.highByte === 0)
512
512
  structure.read = createSecondByteReader(firstId, structure.read);
513
- return readObject() // second byte is already read, if there is one so immediately read object
513
+ return optimizedReadObject() // second byte is already read, if there is one so immediately read object
514
514
  }
515
515
  let object = {};
516
516
  for (let i = 0, l = structure.length; i < l; i++) {
@@ -617,26 +617,45 @@
617
617
  } else if ((byte1 & 0xe0) === 0xc0) {
618
618
  // 2 bytes
619
619
  const byte2 = src[position$1++] & 0x3f;
620
- units.push(((byte1 & 0x1f) << 6) | byte2);
620
+ const codePoint = ((byte1 & 0x1f) << 6) | byte2;
621
+ // Reject overlong encoding: 2-byte sequences must encode values >= 0x80
622
+ if (codePoint < 0x80) {
623
+ units.push(0xFFFD); // replacement character
624
+ } else {
625
+ units.push(codePoint);
626
+ }
621
627
  } else if ((byte1 & 0xf0) === 0xe0) {
622
628
  // 3 bytes
623
629
  const byte2 = src[position$1++] & 0x3f;
624
630
  const byte3 = src[position$1++] & 0x3f;
625
- units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3);
631
+ const codePoint = ((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3;
632
+ // Reject overlong encoding: 3-byte sequences must encode values >= 0x800
633
+ // Also reject surrogates (0xD800-0xDFFF)
634
+ if (codePoint < 0x800 || (codePoint >= 0xD800 && codePoint <= 0xDFFF)) {
635
+ units.push(0xFFFD); // replacement character
636
+ } else {
637
+ units.push(codePoint);
638
+ }
626
639
  } else if ((byte1 & 0xf8) === 0xf0) {
627
640
  // 4 bytes
628
641
  const byte2 = src[position$1++] & 0x3f;
629
642
  const byte3 = src[position$1++] & 0x3f;
630
643
  const byte4 = src[position$1++] & 0x3f;
631
644
  let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4;
632
- if (unit > 0xffff) {
645
+ // Reject overlong encoding: 4-byte sequences must encode values >= 0x10000
646
+ // Also reject values > 0x10FFFF (maximum valid Unicode)
647
+ if (unit < 0x10000 || unit > 0x10FFFF) {
648
+ units.push(0xFFFD); // replacement character
649
+ } else if (unit > 0xffff) {
633
650
  unit -= 0x10000;
634
651
  units.push(((unit >>> 10) & 0x3ff) | 0xd800);
635
652
  unit = 0xdc00 | (unit & 0x3ff);
653
+ units.push(unit);
654
+ } else {
655
+ units.push(unit);
636
656
  }
637
- units.push(unit);
638
657
  } else {
639
- units.push(byte1);
658
+ units.push(0xFFFD); // replacement character for invalid lead byte
640
659
  }
641
660
 
642
661
  if (units.length >= 0x1000) {
@@ -3275,6 +3294,15 @@
3275
3294
  var deserialized = unpack(serialized);
3276
3295
  assert.equal(deserialized, data);
3277
3296
  });
3297
+ test('overlong UTF-8 string', function () {
3298
+ const payload = Buffer.concat([
3299
+ Buffer.from([0xa2]), // msgpack fixstr, 2 bytes
3300
+ Buffer.from([0xc0, 0xaf]), // overlong "/"
3301
+ ]);
3302
+
3303
+ const result = unpack(payload);
3304
+ assert.notEqual(result, '/');
3305
+ });
3278
3306
  test('use ArrayBuffer', function () {
3279
3307
  const data = {prop: 'a test'};
3280
3308
  var serialized = pack(data);