msgpackr 1.10.0 → 1.10.2

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/node.cjs CHANGED
@@ -914,7 +914,7 @@ function readKey() {
914
914
  return readFixedString(length)
915
915
  } else { // not cacheable, go back and do a standard read
916
916
  position$1--;
917
- return read().toString()
917
+ return asSafeString(read())
918
918
  }
919
919
  let key = ((length << 5) ^ (length > 1 ? dataView.getUint16(position$1) : length > 0 ? src[position$1] : 0)) & 0xfff;
920
920
  let entry = keyCache[key];
@@ -966,9 +966,17 @@ function readKey() {
966
966
  return entry.string = readFixedString(length)
967
967
  }
968
968
 
969
+ function asSafeString(property) {
970
+ // protect against expensive (DoS) string conversions
971
+ if (typeof property === 'string') return property;
972
+ if (typeof property === 'number' || typeof property === 'boolean' || typeof property === 'bigint') return property.toString();
973
+ if (property == null) return property + '';
974
+ throw new Error('Invalid property type for record', typeof property);
975
+ }
969
976
  // the registration of the record definition extension (as "r")
970
977
  const recordDefinition = (id, highByte) => {
971
- let structure = read().map(property => property.toString()); // ensure that all keys are strings and that the array is mutable
978
+ let structure = read().map(asSafeString); // ensure that all keys are strings and
979
+ // that the array is mutable
972
980
  let firstByte = id;
973
981
  if (highByte !== undefined) {
974
982
  id = id < 32 ? -((highByte << 5) + id) : ((highByte << 5) + id);
@@ -1002,11 +1010,12 @@ currentExtensions[0x42] = (data) => {
1002
1010
  let errors = { Error, TypeError, ReferenceError };
1003
1011
  currentExtensions[0x65] = () => {
1004
1012
  let data = read();
1005
- return (errors[data[0]] || Error)(data[1])
1013
+ return (errors[data[0]] || Error)(data[1], { cause: data[2] })
1006
1014
  };
1007
1015
 
1008
1016
  currentExtensions[0x69] = (data) => {
1009
1017
  // id extension (for structured clones)
1018
+ if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled')
1010
1019
  let id = dataView.getUint32(position$1 - 4);
1011
1020
  if (!referenceMap)
1012
1021
  referenceMap = new Map();
@@ -1030,6 +1039,7 @@ currentExtensions[0x69] = (data) => {
1030
1039
 
1031
1040
  currentExtensions[0x70] = (data) => {
1032
1041
  // pointer extension (for structured clones)
1042
+ if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled')
1033
1043
  let id = dataView.getUint32(position$1 - 4);
1034
1044
  let refEntry = referenceMap.get(id);
1035
1045
  refEntry.used = true;
@@ -1044,8 +1054,15 @@ let glbl = typeof globalThis === 'object' ? globalThis : window;
1044
1054
  currentExtensions[0x74] = (data) => {
1045
1055
  let typeCode = data[0];
1046
1056
  let typedArrayName = typedArrays[typeCode];
1047
- if (!typedArrayName)
1057
+ if (!typedArrayName) {
1058
+ if (typeCode === 16) {
1059
+ let ab = new ArrayBuffer(data.length - 1);
1060
+ let u8 = new Uint8Array(ab);
1061
+ u8.set(data.subarray(1));
1062
+ return ab;
1063
+ }
1048
1064
  throw new Error('Could not find typed array for code ' + typeCode)
1065
+ }
1049
1066
  // we have to always slice/copy here to get a new ArrayBuffer that is word/byte aligned
1050
1067
  return new glbl[typedArrayName](Uint8Array.prototype.slice.call(data, 1).buffer)
1051
1068
  };
@@ -1352,10 +1369,14 @@ class Packr extends Unpackr {
1352
1369
  return packr.pack(value, encodeOptions)
1353
1370
  }
1354
1371
  packr.lastNamedStructuresLength = sharedLength;
1372
+ // don't keep large buffers around
1373
+ if (target.length > 0x40000000) target = null;
1355
1374
  return returnBuffer
1356
1375
  }
1357
1376
  }
1358
1377
  }
1378
+ // don't keep large buffers around, they take too much memory and cause problems (limit at 1GB)
1379
+ if (target.length > 0x40000000) target = null;
1359
1380
  if (encodeOptions & RESET_BUFFER_MODE)
1360
1381
  position = start;
1361
1382
  }
@@ -1578,7 +1599,7 @@ class Packr extends Unpackr {
1578
1599
  }
1579
1600
  let constructor = value.constructor;
1580
1601
  if (constructor === Object) {
1581
- writeObject(value, true);
1602
+ writeObject(value);
1582
1603
  } else if (constructor === Array) {
1583
1604
  packArray(value);
1584
1605
  } else if (constructor === Map) {
@@ -1674,8 +1695,8 @@ class Packr extends Unpackr {
1674
1695
  if (type === 'function')
1675
1696
  return pack(this.writeFunction && this.writeFunction(value));
1676
1697
 
1677
- // no extension found, write as object
1678
- writeObject(value, !value.hasOwnProperty); // if it doesn't have hasOwnProperty, don't do hasOwnProperty checks
1698
+ // no extension found, write as plain object
1699
+ writeObject(value);
1679
1700
  }
1680
1701
  }
1681
1702
  }
@@ -1762,13 +1783,13 @@ class Packr extends Unpackr {
1762
1783
  }
1763
1784
  }
1764
1785
  } :
1765
- (object, safePrototype) => {
1786
+ (object) => {
1766
1787
  target[position++] = 0xde; // always using map 16, so we can preallocate and set the length afterwards
1767
1788
  let objectOffset = position - start;
1768
1789
  position += 2;
1769
1790
  let size = 0;
1770
1791
  for (let key in object) {
1771
- if (safePrototype || object.hasOwnProperty(key)) {
1792
+ if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
1772
1793
  pack(key);
1773
1794
  pack(object[key]);
1774
1795
  size++;
@@ -1780,12 +1801,12 @@ class Packr extends Unpackr {
1780
1801
 
1781
1802
  const writeRecord = this.useRecords === false ? writePlainObject :
1782
1803
  (options.progressiveRecords && !useTwoByteRecords) ? // this is about 2% faster for highly stable structures, since it only requires one for-in loop (but much more expensive when new structure needs to be written)
1783
- (object, safePrototype) => {
1804
+ (object) => {
1784
1805
  let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
1785
1806
  let objectOffset = position++ - start;
1786
1807
  let wroteKeys;
1787
1808
  for (let key in object) {
1788
- if (safePrototype || object.hasOwnProperty(key)) {
1809
+ if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
1789
1810
  nextTransition = transition[key];
1790
1811
  if (nextTransition)
1791
1812
  transition = nextTransition;
@@ -1824,10 +1845,10 @@ class Packr extends Unpackr {
1824
1845
  insertNewRecord(transition, Object.keys(object), objectOffset, 0);
1825
1846
  }
1826
1847
  } :
1827
- (object, safePrototype) => {
1848
+ (object) => {
1828
1849
  let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
1829
1850
  let newTransitions = 0;
1830
- for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
1851
+ for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
1831
1852
  nextTransition = transition[key];
1832
1853
  if (!nextTransition) {
1833
1854
  nextTransition = transition[key] = Object.create(null);
@@ -1847,7 +1868,7 @@ class Packr extends Unpackr {
1847
1868
  }
1848
1869
  // now write the values
1849
1870
  for (let key in object)
1850
- if (safePrototype || object.hasOwnProperty(key)) {
1871
+ if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
1851
1872
  pack(object[key]);
1852
1873
  }
1853
1874
  };
@@ -1855,8 +1876,8 @@ class Packr extends Unpackr {
1855
1876
  // craete reference to useRecords if useRecords is a function
1856
1877
  const checkUseRecords = typeof this.useRecords == 'function' && this.useRecords;
1857
1878
 
1858
- const writeObject = checkUseRecords ? (object, safePrototype) => {
1859
- checkUseRecords(object) ? writeRecord(object,safePrototype) : writePlainObject(object,safePrototype);
1879
+ const writeObject = checkUseRecords ? (object) => {
1880
+ checkUseRecords(object) ? writeRecord(object) : writePlainObject(object);
1860
1881
  } : writeRecord;
1861
1882
 
1862
1883
  const makeRoom = (end) => {
@@ -1961,7 +1982,7 @@ class Packr extends Unpackr {
1961
1982
  target[insertionOffset + start] = keysTarget[0];
1962
1983
  }
1963
1984
  };
1964
- const writeStruct = (object, safePrototype) => {
1985
+ const writeStruct = (object) => {
1965
1986
  let newPosition = writeStructSlots(object, target, start, position, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
1966
1987
  if (notifySharedUpdate)
1967
1988
  return hasSharedUpdate = true;
@@ -1975,7 +1996,7 @@ class Packr extends Unpackr {
1975
1996
  return position;
1976
1997
  }, this);
1977
1998
  if (newPosition === 0) // bail and go to a msgpack object
1978
- return writeObject(object, true);
1999
+ return writeObject(object);
1979
2000
  position = newPosition;
1980
2001
  };
1981
2002
  }
@@ -2053,7 +2074,7 @@ extensions = [{
2053
2074
  target[position++] = 0x65; // 'e' for error
2054
2075
  target[position++] = 0;
2055
2076
  }
2056
- pack([ error.name, error.message ]);
2077
+ pack([ error.name, error.message, error.cause ]);
2057
2078
  }
2058
2079
  }, {
2059
2080
  pack(regex, allocateForWrite, pack) {
@@ -2106,6 +2127,7 @@ function writeExtBuffer(typedArray, type, allocateForWrite, encode) {
2106
2127
  }
2107
2128
  target[position++] = 0x74; // "t" for typed array
2108
2129
  target[position++] = type;
2130
+ if (!typedArray.buffer) typedArray = new Uint8Array(typedArray);
2109
2131
  target.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength), position);
2110
2132
  }
2111
2133
  function writeBuffer(buffer, allocateForWrite) {