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/unpack.js 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--
917
- return read().toString()
917
+ return asSafeString(read())
918
918
  }
919
919
  let key = ((length << 5) ^ (length > 1 ? dataView.getUint16(position) : length > 0 ? src[position] : 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 - 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 - 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
  }