cbor-x 1.5.9 → 1.6.3

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
@@ -15,6 +15,10 @@
15
15
  const BUNDLED_STRINGS_ID = 0xdff9;
16
16
  const PACKED_REFERENCE_TAG_ID = 6;
17
17
  const STOP_CODE = {};
18
+ let maxArraySize = 112810000; // This is the maximum array size in V8. We would potentially detect and set it higher
19
+ // for JSC, but this is pretty large and should be sufficient for most use cases
20
+ let maxMapSize = 16810000; // JavaScript has a fixed maximum map size of about 16710000, but JS itself enforces this,
21
+ // many keys in an object, so also probably a reasonable choice there.
18
22
  let strings = EMPTY_ARRAY;
19
23
  let stringPosition = 0;
20
24
  let currentDecoder = {};
@@ -263,6 +267,7 @@
263
267
  }
264
268
  token = dataView.getUint32(position$1);
265
269
  position$1 += 4;
270
+ if (majorType === 1) return -1 - token; // can't safely use negation operator here
266
271
  break
267
272
  case 0x1b:
268
273
  if (majorType == 7) {
@@ -277,8 +282,7 @@
277
282
  } else if (currentDecoder.int64AsNumber) {
278
283
  token = dataView.getUint32(position$1) * 0x100000000;
279
284
  token += dataView.getUint32(position$1 + 4);
280
- } else
281
- token = dataView.getBigUint64(position$1);
285
+ } else token = dataView.getBigUint64(position$1);
282
286
  position$1 += 8;
283
287
  break
284
288
  case 0x1f:
@@ -291,6 +295,7 @@
291
295
  let array = [];
292
296
  let value, i = 0;
293
297
  while ((value = read()) != STOP_CODE) {
298
+ if (i >= maxArraySize) throw new Error(`Array length exceeds ${maxArraySize}`)
294
299
  array[i++] = value;
295
300
  }
296
301
  return majorType == 4 ? array : majorType == 3 ? array.join('') : Buffer.concat(array)
@@ -298,8 +303,19 @@
298
303
  let key;
299
304
  if (currentDecoder.mapsAsObjects) {
300
305
  let object = {};
301
- if (currentDecoder.keyMap) while((key = read()) != STOP_CODE) object[safeKey(currentDecoder.decodeKey(key))] = read();
302
- else while ((key = read()) != STOP_CODE) object[safeKey(key)] = read();
306
+ let i = 0;
307
+ if (currentDecoder.keyMap) {
308
+ while((key = read()) != STOP_CODE) {
309
+ if (i++ >= maxMapSize) throw new Error(`Property count exceeds ${maxMapSize}`)
310
+ object[safeKey(currentDecoder.decodeKey(key))] = read();
311
+ }
312
+ }
313
+ else {
314
+ while ((key = read()) != STOP_CODE) {
315
+ if (i++ >= maxMapSize) throw new Error(`Property count exceeds ${maxMapSize}`)
316
+ object[safeKey(key)] = read();
317
+ }
318
+ }
303
319
  return object
304
320
  } else {
305
321
  if (restoreMapsAsObject) {
@@ -307,8 +323,24 @@
307
323
  restoreMapsAsObject = false;
308
324
  }
309
325
  let map = new Map();
310
- if (currentDecoder.keyMap) while((key = read()) != STOP_CODE) map.set(currentDecoder.decodeKey(key), read());
311
- else while ((key = read()) != STOP_CODE) map.set(key, read());
326
+ if (currentDecoder.keyMap) {
327
+ let i = 0;
328
+ while((key = read()) != STOP_CODE) {
329
+ if (i++ >= maxMapSize) {
330
+ throw new Error(`Map size exceeds ${maxMapSize}`);
331
+ }
332
+ map.set(currentDecoder.decodeKey(key), read());
333
+ }
334
+ }
335
+ else {
336
+ let i = 0;
337
+ while ((key = read()) != STOP_CODE) {
338
+ if (i++ >= maxMapSize) {
339
+ throw new Error(`Map size exceeds ${maxMapSize}`);
340
+ }
341
+ map.set(key, read());
342
+ }
343
+ }
312
344
  return map
313
345
  }
314
346
  case 7:
@@ -339,12 +371,14 @@
339
371
  }
340
372
  return readFixedString(token)
341
373
  case 4: // array
374
+ if (token >= maxArraySize) throw new Error(`Array length exceeds ${maxArraySize}`)
342
375
  let array = new Array(token);
343
376
  //if (currentDecoder.keyMap) for (let i = 0; i < token; i++) array[i] = currentDecoder.decodeKey(read())
344
377
  //else
345
378
  for (let i = 0; i < token; i++) array[i] = read();
346
379
  return array
347
380
  case 5: // map
381
+ if (token >= maxMapSize) throw new Error(`Map size exceeds ${maxArraySize}`)
348
382
  if (currentDecoder.mapsAsObjects) {
349
383
  let object = {};
350
384
  if (currentDecoder.keyMap) for (let i = 0; i < token; i++) object[safeKey(currentDecoder.decodeKey(read()))] = read();
@@ -446,6 +480,7 @@
446
480
  }
447
481
  const validName = /^[a-zA-Z_$][a-zA-Z\d_$]*$/;
448
482
  function createStructureReader(structure) {
483
+ if (!structure) throw new Error('Structure is required in record definition');
449
484
  function readObject() {
450
485
  // get the array size from the header
451
486
  let length = src[position$1++];
@@ -804,7 +839,7 @@
804
839
  // bigint extension
805
840
  let value = BigInt(0);
806
841
  for (let i = 0, l = buffer.byteLength; i < l; i++) {
807
- value = BigInt(buffer[i]) + value << BigInt(8);
842
+ value = BigInt(buffer[i]) + (value << BigInt(8));
808
843
  }
809
844
  return value
810
845
  };
@@ -1198,8 +1233,8 @@
1198
1233
  let structures;
1199
1234
  let referenceMap;
1200
1235
  options = options || {};
1201
- let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position, maxBytes) {
1202
- return target.utf8Write(string, position, maxBytes)
1236
+ let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position) {
1237
+ return target.utf8Write(string, position, target.byteLength - position)
1203
1238
  } : (textEncoder && textEncoder.encodeInto) ?
1204
1239
  function(string, position) {
1205
1240
  return textEncoder.encodeInto(string, target.subarray(position)).written
@@ -1580,7 +1615,7 @@
1580
1615
  targetView.setUint32(position, value);
1581
1616
  position += 4;
1582
1617
  }
1583
- } else if (!this.alwaysUseFloat && value >> 0 === value) { // negative integer
1618
+ } else if (!this.alwaysUseFloat && value >> 0 === value) { // negative integer, 31-bit or less
1584
1619
  if (value >= -0x18) {
1585
1620
  target[position++] = 0x1f - value;
1586
1621
  } else if (value >= -0x100) {
@@ -1595,6 +1630,11 @@
1595
1630
  targetView.setUint32(position, ~value);
1596
1631
  position += 4;
1597
1632
  }
1633
+ } else if (!this.alwaysUseFloat && value < 0 && value >= -0x100000000 && Math.floor(value) === value) {
1634
+ // negative integer, 32-bit or less
1635
+ target[position++] = 0x3a;
1636
+ targetView.setUint32(position, -1 - value);
1637
+ position += 4;
1598
1638
  } else {
1599
1639
  let useFloat32;
1600
1640
  if ((useFloat32 = this.useFloat32) > 0 && value < 0x100000000 && value >= -0x80000000) {
@@ -1636,6 +1676,9 @@
1636
1676
  }
1637
1677
  let constructor = value.constructor;
1638
1678
  if (constructor === Object) {
1679
+ if (this.skipFunction === true) {
1680
+ value = Object.fromEntries([...Object.keys(value).filter(x => typeof value[x] !== "function").map(x => [x, value[x]])]);
1681
+ }
1639
1682
  writeObject(value);
1640
1683
  } else if (constructor === Array) {
1641
1684
  length = value.length;
@@ -1752,7 +1795,19 @@
1752
1795
  target[position++] = 0xfb;
1753
1796
  targetView.setFloat64(position, Number(value));
1754
1797
  } else {
1755
- throw new RangeError(value + ' was too large to fit in CBOR 64-bit integer format, set largeBigIntToFloat to convert to float-64')
1798
+ if (value >= BigInt(0))
1799
+ target[position++] = 0xc2; // tag 2
1800
+ else {
1801
+ target[position++] = 0xc3; // tag 2
1802
+ value = BigInt(-1) - value;
1803
+ }
1804
+ let bytes = [];
1805
+ while (value) {
1806
+ bytes.push(Number(value & BigInt(0xff)));
1807
+ value >>= BigInt(8);
1808
+ }
1809
+ writeBuffer(new Uint8Array(bytes.reverse()), makeRoom);
1810
+ return;
1756
1811
  }
1757
1812
  }
1758
1813
  position += 8;
@@ -1799,7 +1854,7 @@
1799
1854
  let objectOffset = position - start;
1800
1855
  position += 2;
1801
1856
  let size = 0;
1802
- if (encoder.keyMap) {
1857
+ if (encoder.keyMap) {
1803
1858
  for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
1804
1859
  encode(encoder.encodeKey(key));
1805
1860
  encode(object[key]);
@@ -1971,7 +2026,7 @@
1971
2026
  yield* tryEncode(value, iterateProperties, 'element');
1972
2027
  } else encode(value);
1973
2028
  }
1974
- } else if (object[Symbol.iterator]) {
2029
+ } else if (object[Symbol.iterator] && !object.buffer) { // iterator, but exclude typed arrays
1975
2030
  target[position++] = 0x9f; // start indefinite array
1976
2031
  for (let value of object) {
1977
2032
  if (value && (typeof value === 'object' || position - start > chunkThreshold)) {
@@ -2548,6 +2603,10 @@
2548
2603
  assert.equal(deserialized, data);
2549
2604
  });
2550
2605
 
2606
+ test('string overflow', function() {
2607
+ assert.throws(() => decode$1(Buffer.from('7a10000000', 'hex')));
2608
+ });
2609
+
2551
2610
  test('encode/decode sample data', function(){
2552
2611
  var data = sampleData;
2553
2612
  var serialized = encode$1(data);
@@ -3035,7 +3094,12 @@
3035
3094
  var deserialized = decode(serialized);
3036
3095
  assert.deepEqual(deserialized, data);
3037
3096
  });
3038
-
3097
+ test('numbers are compact', function(){
3098
+ assert.equal(encode(-256).length, 2);
3099
+ let encoding = encode(-4294967296);
3100
+ assert.equal(encoding.length, 5);
3101
+ assert.equal(decode(encoding), -4294967296);
3102
+ });
3039
3103
  test('encode ArrayBuffer', function() {
3040
3104
  let ua = new Uint8Array([3, 4, 5]);
3041
3105
  let encoded = encode(ua.buffer);
@@ -3060,23 +3124,27 @@
3060
3124
  var data = {
3061
3125
  bigintSmall: 352n,
3062
3126
  bigintSmallNegative: -333335252n,
3063
- bigintBig: 2n**64n - 1n, // biggest possible
3127
+ bigintBig: 2n**64n - 1n, // biggest 64-bit possible
3064
3128
  bigintBigNegative: -(2n**63n), // largest negative
3065
3129
  mixedWithNormal: 44,
3066
3130
  };
3067
3131
  var serialized = encode(data);
3068
3132
  var deserialized = decode(serialized);
3069
3133
  assert.deepEqual(deserialized, data);
3070
- var tooBigInt = {
3071
- tooBig: 2n**66n
3134
+ var evenBiggerInt = {
3135
+ big: 2n**66n,
3136
+ bigger: 53285732853728573289573289573289573289583725892358732859532n,
3137
+ negBig: -93025879203578903275903285903285903289502n,
3072
3138
  };
3073
- assert.throws(function(){ serialized = encode(tooBigInt); });
3139
+ var serialized = encode(evenBiggerInt);
3140
+ var deserialized = decode(serialized);
3141
+ assert.deepEqual(deserialized, evenBiggerInt);
3074
3142
  let encoder = new Encoder({
3075
3143
  largeBigIntToFloat: true
3076
3144
  });
3077
- serialized = encoder.encode(tooBigInt);
3145
+ serialized = encoder.encode(evenBiggerInt);
3078
3146
  deserialized = decode(serialized);
3079
- assert.isTrue(deserialized.tooBig > 2n**65n);
3147
+ assert.isTrue(deserialized.bigger > 2n**65n);
3080
3148
  });
3081
3149
 
3082
3150
  test('buffers', function() {
@@ -3130,6 +3198,20 @@
3130
3198
  decodeMultiple(new Uint8Array([1, 2, 3, 4]), value => values.push(value));
3131
3199
  assert.deepEqual(values, [1, 2, 3, 4]);
3132
3200
  });
3201
+ test('skipFunction', () => {
3202
+ var data = {
3203
+ a: 325283295382932843n,
3204
+ f: () => {},
3205
+ };
3206
+ let encoder = new Encoder({
3207
+ int64AsNumber: true,
3208
+ skipFunction: true,
3209
+ });
3210
+ var serialized = encoder.encode(data);
3211
+ var deserialized = encoder.decode(serialized);
3212
+ assert.deepEqual(deserialized.a, 325283295382932843);
3213
+ assert.equal(Object.hasOwn(deserialized, "f"), false);
3214
+ });
3133
3215
  test('bad input', function() {
3134
3216
  let badInput = Buffer.from('7b2273657269616c6e6f223a2265343a30222c226970223a223139322e3136382e312e3335222c226b6579223a226770735f736563726574227d', 'hex');
3135
3217
  assert.throws(function(){ decode(badInput); }); // should throw, not crash