cbor-x 1.6.6 → 1.6.7

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
@@ -19,7 +19,11 @@
19
19
  let maxArraySize = 112810000; // This is the maximum array size in V8. We would potentially detect and set it higher
20
20
  // for JSC, but this is pretty large and should be sufficient for most use cases
21
21
  let maxMapSize = 16810000; // JavaScript has a fixed maximum map size of about 16710000, but JS itself enforces this,
22
- // many keys in an object, so also probably a reasonable choice there.
22
+ // so we don't need to
23
+
24
+ let maxObjectSize = 16710000; // It takes over a minute to create this many keys in an object, so this is probably a
25
+ // reasonable choice.
26
+ let objectSizeLimit = maxObjectSize; // objects are limited by both maxObjectSize and maxMapSize
23
27
  let strings = EMPTY_ARRAY;
24
28
  let stringPosition = 0;
25
29
  let currentDecoder = {};
@@ -122,7 +126,13 @@
122
126
  // re-entrant execution, save the state and restore it after we do this decode
123
127
  return saveState(() => {
124
128
  clearSource();
125
- return this ? this.decode(source, end) : Decoder.prototype.decode.call(defaultOptions, source, end)
129
+ try {
130
+ return this ? this.decode(source, end) : Decoder.prototype.decode.call(defaultOptions, source, end)
131
+ } catch (error) {
132
+ if (error && typeof error == 'object')
133
+ nestedDecodeErrors.add(error);
134
+ throw error
135
+ }
126
136
  })
127
137
  }
128
138
  srcEnd = end > -1 ? end : source.length;
@@ -199,15 +209,13 @@
199
209
  }
200
210
  }
201
211
  }
212
+ const nestedDecodeErrors = new WeakSet();
202
213
  function checkedRead() {
203
214
  try {
204
215
  let result = read();
205
216
  if (bundledStrings$1) {
206
- if (position$1 >= bundledStrings$1.postBundlePosition) {
207
- let error = new Error('Unexpected bundle position');
208
- error.incomplete = true;
209
- throw error
210
- }
217
+ if (position$1 >= bundledStrings$1.postBundlePosition)
218
+ throw new Error('Unexpected bundle position')
211
219
  // bundled strings to skip past
212
220
  position$1 = bundledStrings$1.postBundlePosition;
213
221
  bundledStrings$1 = null;
@@ -231,7 +239,14 @@
231
239
  return result
232
240
  } catch(error) {
233
241
  clearSource();
234
- if (error instanceof RangeError || error.message.startsWith('Unexpected end of buffer')) {
242
+ if (nestedDecodeErrors.has(error)) {
243
+ // from a nested decode of embedded data (by an extension), which was complete in this source
244
+ if (error.incomplete)
245
+ error.incomplete = false;
246
+ } else if (error instanceof RangeError && position$1 + 8 > srcEnd ||
247
+ error && typeof error.message == 'string' && error.message.startsWith('Unexpected end of buffer')) {
248
+ // a DataView read past the end of the source; these read at most 8 bytes and precede advancing position.
249
+ // Any other RangeError (such as a stack overflow from deeply nested input) is fatal.
235
250
  error.incomplete = true;
236
251
  }
237
252
  throw error
@@ -316,13 +331,13 @@
316
331
  let i = 0;
317
332
  if (currentDecoder.keyMap) {
318
333
  while((key = read()) != STOP_CODE) {
319
- if (i++ >= maxMapSize) throw new Error(`Property count exceeds ${maxMapSize}`)
334
+ if (i++ >= objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
320
335
  object[safeKey(currentDecoder.decodeKey(key))] = read();
321
336
  }
322
337
  }
323
338
  else {
324
339
  while ((key = read()) != STOP_CODE) {
325
- if (i++ >= maxMapSize) throw new Error(`Property count exceeds ${maxMapSize}`)
340
+ if (i++ >= objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
326
341
  object[safeKey(key)] = read();
327
342
  }
328
343
  }
@@ -368,11 +383,13 @@
368
383
  case 1: // negative int
369
384
  return ~token
370
385
  case 2: // buffer
386
+ if (token > srcEnd - position$1) throw endOfCBORError()
371
387
  return readBin(token)
372
388
  case 3: // string
373
- if (srcStringEnd >= position$1) {
389
+ if (srcStringEnd >= position$1) { // already extracted, which only covers complete strings
374
390
  return srcString.slice(position$1 - srcStringStart, (position$1 += token) - srcStringStart)
375
391
  }
392
+ if (token > srcEnd - position$1) throw endOfCBORError()
376
393
  if (srcStringEnd == 0 && srcEnd < 140 && token < 32) {
377
394
  // for small blocks, avoiding the overhead of the extract call is helpful
378
395
  let string = token < 16 ? shortStringInJS(token) : longStringInJS(token);
@@ -381,7 +398,7 @@
381
398
  }
382
399
  return readFixedString(token)
383
400
  case 4: // array
384
- if (token >= maxArraySize) throw new Error(`Array length exceeds ${maxArraySize}`)
401
+ if (token > maxArraySize) throw new Error(`Array length exceeds ${maxArraySize}`)
385
402
  // every element occupies at least one byte, so a length beyond what remains in the source can
386
403
  // never be satisfied; check before allocating so a tiny header can not force a huge allocation
387
404
  if (token > srcEnd - position$1) throw endOfCBORError()
@@ -391,9 +408,9 @@
391
408
  for (let i = 0; i < token; i++) array[i] = read();
392
409
  return array
393
410
  case 5: // map
394
- if (token >= maxMapSize) throw new Error(`Map size exceeds ${maxArraySize}`)
395
- if (token > (srcEnd - position$1) / 2) throw endOfCBORError() // each entry needs at least two bytes
396
411
  if (currentDecoder.mapsAsObjects) {
412
+ if (token > objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
413
+ if (token > (srcEnd - position$1) / 2) throw endOfCBORError() // each entry needs at least two bytes
397
414
  let object = {};
398
415
  if (currentDecoder.keyMap) for (let i = 0; i < token; i++) object[safeKey(currentDecoder.decodeKey(read()))] = read();
399
416
  else for (let i = 0; i < token; i++) object[safeKey(read())] = read();
@@ -403,6 +420,8 @@
403
420
  currentDecoder.mapsAsObjects = true;
404
421
  restoreMapsAsObject = false;
405
422
  }
423
+ if (token > maxMapSize) throw new Error(`Map size exceeds ${maxMapSize}`)
424
+ if (token > (srcEnd - position$1) / 2) throw endOfCBORError()
406
425
  let map = new Map();
407
426
  if (currentDecoder.keyMap) for (let i = 0; i < token; i++) map.set(currentDecoder.decodeKey(read()),read());
408
427
  else for (let i = 0; i < token; i++) map.set(read(), read());
@@ -930,18 +949,12 @@
930
949
  return (glbl[data[0]] || Error)(data[1], data[2])
931
950
  };
932
951
  const packedTable = (read) => {
933
- if (src[position$1++] != 0x84) {
934
- let error = new Error('Packed values structure must be followed by a 4 element array');
935
- if (src.length < position$1)
936
- error.incomplete = true;
937
- throw error
938
- }
952
+ if (!(position$1 < srcEnd)) throw endOfCBORError()
953
+ if (src[position$1++] != 0x84)
954
+ throw new Error('Packed values structure must be followed by a 4 element array')
939
955
  let newPackedValues = read(); // packed values
940
- if (!newPackedValues || !newPackedValues.length) {
941
- let error = new Error('Packed values structure must be followed by a 4 element array');
942
- error.incomplete = true;
943
- throw error
944
- }
956
+ if (!Array.isArray(newPackedValues) || !newPackedValues.length)
957
+ throw new Error('Packed values structure must be followed by a 4 element array')
945
958
  packedValues = packedValues ? newPackedValues.concat(packedValues.slice(newPackedValues.length)) : newPackedValues;
946
959
  packedValues.prefixes = read();
947
960
  packedValues.suffixes = read();
@@ -959,10 +972,7 @@
959
972
  }
960
973
  if (typeof data == 'number')
961
974
  return packedValues[16 + (data >= 0 ? 2 * data : (-2 * data - 1))]
962
- let error = new Error('No support for non-integer packed references yet');
963
- if (data === undefined)
964
- error.incomplete = true;
965
- throw error
975
+ throw new Error('No support for non-integer packed references yet')
966
976
  };
967
977
 
968
978
  // The following code is an incomplete implementation of http://cbor.schmorp.de/stringref
@@ -1032,9 +1042,19 @@
1032
1042
  (currentExtensions[259] = (read) => {
1033
1043
  // https://github.com/shanewholloway/js-cbor-codec/blob/master/docs/CBOR-259-spec
1034
1044
  // for decoding as a standard Map
1035
- if (currentDecoder.mapsAsObjects) {
1036
- currentDecoder.mapsAsObjects = false;
1045
+ let decoder = currentDecoder;
1046
+ if (decoder.mapsAsObjects) {
1047
+ decoder.mapsAsObjects = false;
1037
1048
  restoreMapsAsObject = true;
1049
+ try {
1050
+ return read()
1051
+ } finally {
1052
+ // normally restored by the map header, but not if the tagged value is not a map or the read fails
1053
+ if (restoreMapsAsObject) {
1054
+ decoder.mapsAsObjects = true;
1055
+ restoreMapsAsObject = false;
1056
+ }
1057
+ }
1038
1058
  }
1039
1059
  return read()
1040
1060
  }).handlesRead = true;
@@ -1154,10 +1174,12 @@
1154
1174
  token = src[position$1++];
1155
1175
  break
1156
1176
  case 0x19:
1177
+ if (position$1 + 2 > srcEnd) throw endOfCBORError()
1157
1178
  token = dataView.getUint16(position$1);
1158
1179
  position$1 += 2;
1159
1180
  break
1160
1181
  case 0x1a:
1182
+ if (position$1 + 4 > srcEnd) throw endOfCBORError()
1161
1183
  token = dataView.getUint32(position$1);
1162
1184
  position$1 += 4;
1163
1185
  break
@@ -1199,22 +1221,27 @@
1199
1221
  let savedStructures = currentStructures;
1200
1222
  let savedDecoder = currentDecoder;
1201
1223
  let savedSequentialMode = sequentialMode;
1202
- let value = callback();
1203
- srcEnd = savedSrcEnd;
1204
- position$1 = savedPosition;
1205
- stringPosition = savedStringPosition;
1206
- srcStringStart = savedSrcStringStart;
1207
- srcStringEnd = savedSrcStringEnd;
1208
- srcString = savedSrcString;
1209
- strings = savedStrings;
1210
- referenceMap = savedReferenceMap;
1211
- bundledStrings$1 = savedBundledStrings;
1212
- src = savedSrc;
1213
- sequentialMode = savedSequentialMode;
1214
- currentStructures = savedStructures;
1215
- currentDecoder = savedDecoder;
1216
- dataView = new DataView(src.buffer, src.byteOffset, src.byteLength);
1217
- return value
1224
+ let savedRestoreMapsAsObject = restoreMapsAsObject;
1225
+ restoreMapsAsObject = false;
1226
+ try {
1227
+ return callback()
1228
+ } finally {
1229
+ srcEnd = savedSrcEnd;
1230
+ position$1 = savedPosition;
1231
+ stringPosition = savedStringPosition;
1232
+ srcStringStart = savedSrcStringStart;
1233
+ srcStringEnd = savedSrcStringEnd;
1234
+ srcString = savedSrcString;
1235
+ strings = savedStrings;
1236
+ referenceMap = savedReferenceMap;
1237
+ bundledStrings$1 = savedBundledStrings;
1238
+ src = savedSrc;
1239
+ sequentialMode = savedSequentialMode;
1240
+ currentStructures = savedStructures;
1241
+ currentDecoder = savedDecoder;
1242
+ restoreMapsAsObject = savedRestoreMapsAsObject;
1243
+ dataView = new DataView(src.buffer, src.byteOffset, src.byteLength);
1244
+ }
1218
1245
  }
1219
1246
  function clearSource() {
1220
1247
  src = null;
@@ -1420,7 +1447,7 @@
1420
1447
  if (throwOnIterable)
1421
1448
  return;
1422
1449
  encode(value);
1423
- if (bundledStrings) {
1450
+ if (bundledStrings && bundledStrings.position) { // position is only set once a bundle has been started
1424
1451
  writeBundles(start, encode);
1425
1452
  }
1426
1453
  encoder.offset = position; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially