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/unpack.js CHANGED
@@ -29,13 +29,6 @@ var sequentialMode = false
29
29
  var inlineObjectReadThreshold = 2
30
30
  var readStruct, onLoadedStructures, onSaveState
31
31
  var BlockedFunction // we use search and replace to change the next call to BlockedFunction to avoid CSP issues for
32
- // no-eval build
33
- try {
34
- new Function('')
35
- } catch(error) {
36
- // if eval variants are not supported, do not create inline object readers ever
37
- inlineObjectReadThreshold = Infinity
38
- }
39
32
 
40
33
  export class Unpackr {
41
34
  constructor(options) {
@@ -508,11 +501,18 @@ function createStructureReader(structure, firstId) {
508
501
  function readObject() {
509
502
  // This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
510
503
  if (readObject.count++ > inlineObjectReadThreshold) {
511
- let readObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
512
- '({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read)
504
+ let optimizedReadObject
505
+ try {
506
+ optimizedReadObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
507
+ '({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read)
508
+ } catch(error) {
509
+ // in CF workers, the new Function call could begin to fail at any point in time
510
+ inlineObjectReadThreshold = Infinity // disable going forward
511
+ return readObject(); // recursively try again
512
+ }
513
513
  if (structure.highByte === 0)
514
514
  structure.read = createSecondByteReader(firstId, structure.read)
515
- return readObject() // second byte is already read, if there is one so immediately read object
515
+ return optimizedReadObject() // second byte is already read, if there is one so immediately read object
516
516
  }
517
517
  let object = {}
518
518
  for (let i = 0, l = structure.length; i < l; i++) {
@@ -621,26 +621,45 @@ function readStringJS(length) {
621
621
  } else if ((byte1 & 0xe0) === 0xc0) {
622
622
  // 2 bytes
623
623
  const byte2 = src[position++] & 0x3f
624
- units.push(((byte1 & 0x1f) << 6) | byte2)
624
+ const codePoint = ((byte1 & 0x1f) << 6) | byte2
625
+ // Reject overlong encoding: 2-byte sequences must encode values >= 0x80
626
+ if (codePoint < 0x80) {
627
+ units.push(0xFFFD) // replacement character
628
+ } else {
629
+ units.push(codePoint)
630
+ }
625
631
  } else if ((byte1 & 0xf0) === 0xe0) {
626
632
  // 3 bytes
627
633
  const byte2 = src[position++] & 0x3f
628
634
  const byte3 = src[position++] & 0x3f
629
- units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3)
635
+ const codePoint = ((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3
636
+ // Reject overlong encoding: 3-byte sequences must encode values >= 0x800
637
+ // Also reject surrogates (0xD800-0xDFFF)
638
+ if (codePoint < 0x800 || (codePoint >= 0xD800 && codePoint <= 0xDFFF)) {
639
+ units.push(0xFFFD) // replacement character
640
+ } else {
641
+ units.push(codePoint)
642
+ }
630
643
  } else if ((byte1 & 0xf8) === 0xf0) {
631
644
  // 4 bytes
632
645
  const byte2 = src[position++] & 0x3f
633
646
  const byte3 = src[position++] & 0x3f
634
647
  const byte4 = src[position++] & 0x3f
635
648
  let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4
636
- if (unit > 0xffff) {
649
+ // Reject overlong encoding: 4-byte sequences must encode values >= 0x10000
650
+ // Also reject values > 0x10FFFF (maximum valid Unicode)
651
+ if (unit < 0x10000 || unit > 0x10FFFF) {
652
+ units.push(0xFFFD) // replacement character
653
+ } else if (unit > 0xffff) {
637
654
  unit -= 0x10000
638
655
  units.push(((unit >>> 10) & 0x3ff) | 0xd800)
639
656
  unit = 0xdc00 | (unit & 0x3ff)
657
+ units.push(unit)
658
+ } else {
659
+ units.push(unit)
640
660
  }
641
- units.push(unit)
642
661
  } else {
643
- units.push(byte1)
662
+ units.push(0xFFFD) // replacement character for invalid lead byte
644
663
  }
645
664
 
646
665
  if (units.length >= 0x1000) {