cbor-x 1.5.7 → 1.5.9

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.
@@ -498,7 +498,12 @@
498
498
  }
499
499
 
500
500
  function safeKey(key) {
501
- return key === '__proto__' ? '__proto_' : key
501
+ // protect against prototype pollution
502
+ if (typeof key === 'string') return key === '__proto__' ? '__proto_' : key
503
+ if (typeof key === 'number' || typeof key === 'boolean' || typeof key === 'bigint') return key.toString();
504
+ if (key == null) return key + '';
505
+ // protect against expensive (DoS) string conversions
506
+ throw new Error('Invalid property name type ' + typeof key);
502
507
  }
503
508
 
504
509
  let readFixedString = readStringJS;
@@ -881,6 +886,7 @@
881
886
  referenceMap.id = 0;
882
887
  }
883
888
  let id = referenceMap.id++;
889
+ let startingPosition = position$1;
884
890
  let token = src[position$1];
885
891
  let target;
886
892
  // TODO: handle Maps, Sets, and other types that can cycle; this is complicated, because you potentially need to read
@@ -893,8 +899,20 @@
893
899
  let refEntry = { target }; // a placeholder object
894
900
  referenceMap.set(id, refEntry);
895
901
  let targetProperties = read(); // read the next value as the target object to id
896
- if (refEntry.used) // there is a cycle, so we have to assign properties to original target
902
+ if (refEntry.used) {// there is a cycle, so we have to assign properties to original target
903
+ if (Object.getPrototypeOf(target) !== Object.getPrototypeOf(targetProperties)) {
904
+ // this means that the returned target does not match the targetProperties, so we need rerun the read to
905
+ // have the correctly create instance be assigned as a reference, then we do the copy the properties back to the
906
+ // target
907
+ // reset the position so that the read can be repeated
908
+ position$1 = startingPosition;
909
+ // the returned instance is our new target for references
910
+ target = targetProperties;
911
+ referenceMap.set(id, { target });
912
+ targetProperties = read();
913
+ }
897
914
  return Object.assign(target, targetProperties)
915
+ }
898
916
  refEntry.target = targetProperties; // the placeholder wasn't used, replace with the deserialized one
899
917
  return targetProperties // no cycle, can just use the returned read object
900
918
  };
@@ -976,7 +994,7 @@
976
994
  for (let littleEndian = 0; littleEndian < 2; littleEndian++) {
977
995
  if (!littleEndian && bytesPerElement == 1)
978
996
  continue
979
- let sizeShift = bytesPerElement == 2 ? 1 : bytesPerElement == 4 ? 2 : 3;
997
+ let sizeShift = bytesPerElement == 2 ? 1 : bytesPerElement == 4 ? 2 : bytesPerElement == 8 ? 3 : 0;
980
998
  currentExtensions[littleEndian ? tag : (tag - 4)] = (bytesPerElement == 1 || littleEndian == isLittleEndianMachine$1) ? (buffer) => {
981
999
  if (!TypedArray)
982
1000
  throw new Error('Could not find typed array for code ' + tag)
@@ -986,7 +1004,7 @@
986
1004
  bytesPerElement === 2 && !(buffer.byteOffset & 1) ||
987
1005
  bytesPerElement === 4 && !(buffer.byteOffset & 3) ||
988
1006
  bytesPerElement === 8 && !(buffer.byteOffset & 7))
989
- return new TypedArray(buffer.buffer, buffer.byteOffset, buffer.byteLength);
1007
+ return new TypedArray(buffer.buffer, buffer.byteOffset, buffer.byteLength >> sizeShift);
990
1008
  }
991
1009
  // we have to slice/copy here to get a new ArrayBuffer, if we are not word/byte aligned
992
1010
  return new TypedArray(Uint8Array.prototype.slice.call(buffer, 0).buffer)
@@ -1586,7 +1604,7 @@
1586
1604
  }
1587
1605
  let constructor = value.constructor;
1588
1606
  if (constructor === Object) {
1589
- writeObject(value, true);
1607
+ writeObject(value);
1590
1608
  } else if (constructor === Array) {
1591
1609
  length = value.length;
1592
1610
  if (length < 0x18) {
@@ -1681,8 +1699,8 @@
1681
1699
  return encode(json)
1682
1700
  }
1683
1701
 
1684
- // no extension found, write as object
1685
- writeObject(value, !value.hasOwnProperty); // if it doesn't have hasOwnProperty, don't do hasOwnProperty checks
1702
+ // no extension found, write as a plain object
1703
+ writeObject(value);
1686
1704
  }
1687
1705
  }
1688
1706
  } else if (type === 'boolean') {
@@ -1744,19 +1762,19 @@
1744
1762
  }
1745
1763
  }
1746
1764
  } :
1747
- (object, safePrototype) => {
1765
+ (object) => {
1748
1766
  target[position++] = 0xb9; // always use map 16, so we can preallocate and set the length afterwards
1749
1767
  let objectOffset = position - start;
1750
1768
  position += 2;
1751
1769
  let size = 0;
1752
1770
  if (encoder.keyMap) {
1753
- for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
1771
+ for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
1754
1772
  encode(encoder.encodeKey(key));
1755
1773
  encode(object[key]);
1756
1774
  size++;
1757
1775
  }
1758
1776
  } else {
1759
- for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
1777
+ for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
1760
1778
  encode(key);
1761
1779
  encode(object[key]);
1762
1780
  size++;
@@ -1765,7 +1783,7 @@
1765
1783
  target[objectOffset++ + start] = size >> 8;
1766
1784
  target[objectOffset + start] = size & 0xff;
1767
1785
  } :
1768
- (object, safePrototype) => {
1786
+ (object, skipValues) => {
1769
1787
  let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
1770
1788
  let newTransitions = 0;
1771
1789
  let length = 0;
@@ -1784,7 +1802,7 @@
1784
1802
  transition = nextTransition;
1785
1803
  }
1786
1804
  } else {
1787
- for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
1805
+ for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
1788
1806
  nextTransition = transition[key];
1789
1807
  if (!nextTransition) {
1790
1808
  if (transition[RECORD_SYMBOL] & 0x100000) {// this indicates it is a brancheable/extendable terminal node, so we will use this record id and extend it
@@ -1844,9 +1862,9 @@
1844
1862
  writeArrayHeader(length + 2);
1845
1863
  encode(0xe000 + recordId);
1846
1864
  encode(keys);
1847
- if (safePrototype === null) return; // special exit for iterator
1865
+ if (skipValues) return; // special exit for iterator
1848
1866
  for (let key in object)
1849
- if (safePrototype || object.hasOwnProperty(key))
1867
+ if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key))
1850
1868
  encode(object[key]);
1851
1869
  return
1852
1870
  }
@@ -1856,9 +1874,9 @@
1856
1874
  } else {
1857
1875
  writeArrayHeader(length);
1858
1876
  }
1859
- if (safePrototype === null) return; // special exit for iterator
1877
+ if (skipValues) return; // special exit for iterator
1860
1878
  for (let key in object)
1861
- if (safePrototype || object.hasOwnProperty(key))
1879
+ if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key))
1862
1880
  encode(object[key]);
1863
1881
  };
1864
1882
  const makeRoom = (end) => {
@@ -1896,7 +1914,7 @@
1896
1914
  if (constructor === Object) {
1897
1915
  let useRecords = encoder.useRecords !== false;
1898
1916
  if (useRecords)
1899
- writeObject(object, null); // write the record identifier
1917
+ writeObject(object, true); // write the record identifier
1900
1918
  else
1901
1919
  writeEntityLength(Object.keys(object).length, 0xa0);
1902
1920
  for (let key in object) {