cbor-x 1.6.6 → 1.6.8
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/README.md +4 -0
- package/decode.js +81 -49
- package/dist/decode-no-eval.cjs +83 -49
- package/dist/decode-no-eval.cjs.map +1 -1
- package/dist/index-no-eval.cjs +88 -51
- package/dist/index-no-eval.cjs.map +1 -1
- package/dist/index-no-eval.min.js +1 -1
- package/dist/index-no-eval.min.js.map +1 -1
- package/dist/index.js +88 -51
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/node.cjs +101 -67
- package/dist/node.cjs.map +1 -1
- package/dist/test.js +82 -49
- package/dist/test.js.map +1 -1
- package/encode.js +1 -1
- package/iterators.js +6 -4
- package/package.json +1 -1
- package/stream.js +11 -13
package/dist/index.js
CHANGED
|
@@ -20,6 +20,11 @@
|
|
|
20
20
|
let maxArraySize = 112810000; // This is the maximum array size in V8. We would potentially detect and set it higher
|
|
21
21
|
// for JSC, but this is pretty large and should be sufficient for most use cases
|
|
22
22
|
let maxMapSize = 16810000; // JavaScript has a fixed maximum map size of about 16710000, but JS itself enforces this,
|
|
23
|
+
// so we don't need to
|
|
24
|
+
|
|
25
|
+
let maxObjectSize = 16710000; // It takes over a minute to create this many keys in an object, so this is probably a
|
|
26
|
+
// reasonable choice.
|
|
27
|
+
let objectSizeLimit = maxObjectSize; // objects are limited by both maxObjectSize and maxMapSize
|
|
23
28
|
let currentDecoder = {};
|
|
24
29
|
let currentStructures;
|
|
25
30
|
let srcString;
|
|
@@ -120,7 +125,13 @@
|
|
|
120
125
|
// re-entrant execution, save the state and restore it after we do this decode
|
|
121
126
|
return saveState(() => {
|
|
122
127
|
clearSource();
|
|
123
|
-
|
|
128
|
+
try {
|
|
129
|
+
return this ? this.decode(source, end) : Decoder.prototype.decode.call(defaultOptions, source, end)
|
|
130
|
+
} catch (error) {
|
|
131
|
+
if (error && typeof error == 'object')
|
|
132
|
+
nestedDecodeErrors.add(error);
|
|
133
|
+
throw error
|
|
134
|
+
}
|
|
124
135
|
})
|
|
125
136
|
}
|
|
126
137
|
srcEnd = end > -1 ? end : source.length;
|
|
@@ -195,15 +206,15 @@
|
|
|
195
206
|
}
|
|
196
207
|
}
|
|
197
208
|
}
|
|
209
|
+
const nestedDecodeErrors = new WeakSet();
|
|
210
|
+
let arrayAllocationBudget;
|
|
198
211
|
function checkedRead() {
|
|
199
212
|
try {
|
|
213
|
+
arrayAllocationBudget = srcEnd - position$1;
|
|
200
214
|
let result = read();
|
|
201
215
|
if (bundledStrings$1) {
|
|
202
|
-
if (position$1 >= bundledStrings$1.postBundlePosition)
|
|
203
|
-
|
|
204
|
-
error.incomplete = true;
|
|
205
|
-
throw error
|
|
206
|
-
}
|
|
216
|
+
if (position$1 >= bundledStrings$1.postBundlePosition)
|
|
217
|
+
throw new Error('Unexpected bundle position')
|
|
207
218
|
// bundled strings to skip past
|
|
208
219
|
position$1 = bundledStrings$1.postBundlePosition;
|
|
209
220
|
bundledStrings$1 = null;
|
|
@@ -227,7 +238,14 @@
|
|
|
227
238
|
return result
|
|
228
239
|
} catch(error) {
|
|
229
240
|
clearSource();
|
|
230
|
-
if (
|
|
241
|
+
if (nestedDecodeErrors.has(error)) {
|
|
242
|
+
// from a nested decode of embedded data (by an extension), which was complete in this source
|
|
243
|
+
if (error.incomplete)
|
|
244
|
+
error.incomplete = false;
|
|
245
|
+
} else if (error instanceof RangeError && position$1 + 8 > srcEnd ||
|
|
246
|
+
error && typeof error.message == 'string' && error.message.startsWith('Unexpected end of buffer')) {
|
|
247
|
+
// a DataView read past the end of the source; these read at most 8 bytes and precede advancing position.
|
|
248
|
+
// Any other RangeError (such as a stack overflow from deeply nested input) is fatal.
|
|
231
249
|
error.incomplete = true;
|
|
232
250
|
}
|
|
233
251
|
throw error
|
|
@@ -312,13 +330,13 @@
|
|
|
312
330
|
let i = 0;
|
|
313
331
|
if (currentDecoder.keyMap) {
|
|
314
332
|
while((key = read()) != STOP_CODE) {
|
|
315
|
-
if (i++ >=
|
|
333
|
+
if (i++ >= objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
|
|
316
334
|
object[safeKey(currentDecoder.decodeKey(key))] = read();
|
|
317
335
|
}
|
|
318
336
|
}
|
|
319
337
|
else {
|
|
320
338
|
while ((key = read()) != STOP_CODE) {
|
|
321
|
-
if (i++ >=
|
|
339
|
+
if (i++ >= objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
|
|
322
340
|
object[safeKey(key)] = read();
|
|
323
341
|
}
|
|
324
342
|
}
|
|
@@ -364,11 +382,13 @@
|
|
|
364
382
|
case 1: // negative int
|
|
365
383
|
return ~token
|
|
366
384
|
case 2: // buffer
|
|
385
|
+
if (token > srcEnd - position$1) throw endOfCBORError()
|
|
367
386
|
return readBin(token)
|
|
368
387
|
case 3: // string
|
|
369
|
-
if (srcStringEnd >= position$1) {
|
|
388
|
+
if (srcStringEnd >= position$1) { // already extracted, which only covers complete strings
|
|
370
389
|
return srcString.slice(position$1 - srcStringStart, (position$1 += token) - srcStringStart)
|
|
371
390
|
}
|
|
391
|
+
if (token > srcEnd - position$1) throw endOfCBORError()
|
|
372
392
|
if (srcStringEnd == 0 && srcEnd < 140 && token < 32) {
|
|
373
393
|
// for small blocks, avoiding the overhead of the extract call is helpful
|
|
374
394
|
let string = token < 16 ? shortStringInJS(token) : longStringInJS(token);
|
|
@@ -377,19 +397,21 @@
|
|
|
377
397
|
}
|
|
378
398
|
return readFixedString(token)
|
|
379
399
|
case 4: // array
|
|
380
|
-
if (token
|
|
400
|
+
if (token > maxArraySize) throw new Error(`Array length exceeds ${maxArraySize}`)
|
|
381
401
|
// every element occupies at least one byte, so a length beyond what remains in the source can
|
|
382
402
|
// never be satisfied; check before allocating so a tiny header can not force a huge allocation
|
|
383
|
-
|
|
403
|
+
// nested arrays each pass the check above yet still preallocate, so also spend from a
|
|
404
|
+
// per-decode budget of the remaining bytes; the summed lengths of any valid tree stay under it
|
|
405
|
+
if (token > srcEnd - position$1 || (arrayAllocationBudget -= token) < 0) throw endOfCBORError()
|
|
384
406
|
let array = new Array(token);
|
|
385
407
|
//if (currentDecoder.keyMap) for (let i = 0; i < token; i++) array[i] = currentDecoder.decodeKey(read())
|
|
386
408
|
//else
|
|
387
409
|
for (let i = 0; i < token; i++) array[i] = read();
|
|
388
410
|
return array
|
|
389
411
|
case 5: // map
|
|
390
|
-
if (token >= maxMapSize) throw new Error(`Map size exceeds ${maxArraySize}`)
|
|
391
|
-
if (token > (srcEnd - position$1) / 2) throw endOfCBORError() // each entry needs at least two bytes
|
|
392
412
|
if (currentDecoder.mapsAsObjects) {
|
|
413
|
+
if (token > objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
|
|
414
|
+
if (token > (srcEnd - position$1) / 2) throw endOfCBORError() // each entry needs at least two bytes
|
|
393
415
|
let object = {};
|
|
394
416
|
if (currentDecoder.keyMap) for (let i = 0; i < token; i++) object[safeKey(currentDecoder.decodeKey(read()))] = read();
|
|
395
417
|
else for (let i = 0; i < token; i++) object[safeKey(read())] = read();
|
|
@@ -399,6 +421,8 @@
|
|
|
399
421
|
currentDecoder.mapsAsObjects = true;
|
|
400
422
|
restoreMapsAsObject = false;
|
|
401
423
|
}
|
|
424
|
+
if (token > maxMapSize) throw new Error(`Map size exceeds ${maxMapSize}`)
|
|
425
|
+
if (token > (srcEnd - position$1) / 2) throw endOfCBORError()
|
|
402
426
|
let map = new Map();
|
|
403
427
|
if (currentDecoder.keyMap) for (let i = 0; i < token; i++) map.set(currentDecoder.decodeKey(read()),read());
|
|
404
428
|
else for (let i = 0; i < token; i++) map.set(read(), read());
|
|
@@ -894,18 +918,12 @@
|
|
|
894
918
|
return (glbl[data[0]] || Error)(data[1], data[2])
|
|
895
919
|
};
|
|
896
920
|
const packedTable = (read) => {
|
|
897
|
-
if (
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
error.incomplete = true;
|
|
901
|
-
throw error
|
|
902
|
-
}
|
|
921
|
+
if (!(position$1 < srcEnd)) throw endOfCBORError()
|
|
922
|
+
if (src[position$1++] != 0x84)
|
|
923
|
+
throw new Error('Packed values structure must be followed by a 4 element array')
|
|
903
924
|
let newPackedValues = read(); // packed values
|
|
904
|
-
if (!newPackedValues || !newPackedValues.length)
|
|
905
|
-
|
|
906
|
-
error.incomplete = true;
|
|
907
|
-
throw error
|
|
908
|
-
}
|
|
925
|
+
if (!Array.isArray(newPackedValues) || !newPackedValues.length)
|
|
926
|
+
throw new Error('Packed values structure must be followed by a 4 element array')
|
|
909
927
|
packedValues = packedValues ? newPackedValues.concat(packedValues.slice(newPackedValues.length)) : newPackedValues;
|
|
910
928
|
packedValues.prefixes = read();
|
|
911
929
|
packedValues.suffixes = read();
|
|
@@ -923,10 +941,7 @@
|
|
|
923
941
|
}
|
|
924
942
|
if (typeof data == 'number')
|
|
925
943
|
return packedValues[16 + (data >= 0 ? 2 * data : (-2 * data - 1))]
|
|
926
|
-
|
|
927
|
-
if (data === undefined)
|
|
928
|
-
error.incomplete = true;
|
|
929
|
-
throw error
|
|
944
|
+
throw new Error('No support for non-integer packed references yet')
|
|
930
945
|
};
|
|
931
946
|
|
|
932
947
|
// The following code is an incomplete implementation of http://cbor.schmorp.de/stringref
|
|
@@ -996,9 +1011,19 @@
|
|
|
996
1011
|
(currentExtensions[259] = (read) => {
|
|
997
1012
|
// https://github.com/shanewholloway/js-cbor-codec/blob/master/docs/CBOR-259-spec
|
|
998
1013
|
// for decoding as a standard Map
|
|
999
|
-
|
|
1000
|
-
|
|
1014
|
+
let decoder = currentDecoder;
|
|
1015
|
+
if (decoder.mapsAsObjects) {
|
|
1016
|
+
decoder.mapsAsObjects = false;
|
|
1001
1017
|
restoreMapsAsObject = true;
|
|
1018
|
+
try {
|
|
1019
|
+
return read()
|
|
1020
|
+
} finally {
|
|
1021
|
+
// normally restored by the map header, but not if the tagged value is not a map or the read fails
|
|
1022
|
+
if (restoreMapsAsObject) {
|
|
1023
|
+
decoder.mapsAsObjects = true;
|
|
1024
|
+
restoreMapsAsObject = false;
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1002
1027
|
}
|
|
1003
1028
|
return read()
|
|
1004
1029
|
}).handlesRead = true;
|
|
@@ -1118,10 +1143,12 @@
|
|
|
1118
1143
|
token = src[position$1++];
|
|
1119
1144
|
break
|
|
1120
1145
|
case 0x19:
|
|
1146
|
+
if (position$1 + 2 > srcEnd) throw endOfCBORError()
|
|
1121
1147
|
token = dataView.getUint16(position$1);
|
|
1122
1148
|
position$1 += 2;
|
|
1123
1149
|
break
|
|
1124
1150
|
case 0x1a:
|
|
1151
|
+
if (position$1 + 4 > srcEnd) throw endOfCBORError()
|
|
1125
1152
|
token = dataView.getUint32(position$1);
|
|
1126
1153
|
position$1 += 4;
|
|
1127
1154
|
break
|
|
@@ -1161,20 +1188,27 @@
|
|
|
1161
1188
|
let savedStructures = currentStructures;
|
|
1162
1189
|
let savedDecoder = currentDecoder;
|
|
1163
1190
|
let savedSequentialMode = sequentialMode;
|
|
1164
|
-
let
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1191
|
+
let savedRestoreMapsAsObject = restoreMapsAsObject;
|
|
1192
|
+
let savedArrayAllocationBudget = arrayAllocationBudget;
|
|
1193
|
+
restoreMapsAsObject = false;
|
|
1194
|
+
try {
|
|
1195
|
+
return callback()
|
|
1196
|
+
} finally {
|
|
1197
|
+
srcEnd = savedSrcEnd;
|
|
1198
|
+
position$1 = savedPosition;
|
|
1199
|
+
srcStringStart = savedSrcStringStart;
|
|
1200
|
+
srcStringEnd = savedSrcStringEnd;
|
|
1201
|
+
srcString = savedSrcString;
|
|
1202
|
+
referenceMap = savedReferenceMap;
|
|
1203
|
+
bundledStrings$1 = savedBundledStrings;
|
|
1204
|
+
src = savedSrc;
|
|
1205
|
+
sequentialMode = savedSequentialMode;
|
|
1206
|
+
currentStructures = savedStructures;
|
|
1207
|
+
currentDecoder = savedDecoder;
|
|
1208
|
+
restoreMapsAsObject = savedRestoreMapsAsObject;
|
|
1209
|
+
arrayAllocationBudget = savedArrayAllocationBudget;
|
|
1210
|
+
dataView = new DataView(src.buffer, src.byteOffset, src.byteLength);
|
|
1211
|
+
}
|
|
1178
1212
|
}
|
|
1179
1213
|
function clearSource() {
|
|
1180
1214
|
src = null;
|
|
@@ -1189,7 +1223,8 @@
|
|
|
1189
1223
|
function setSizeLimits(limits) {
|
|
1190
1224
|
if (limits.maxMapSize) maxMapSize = limits.maxMapSize;
|
|
1191
1225
|
if (limits.maxArraySize) maxArraySize = limits.maxArraySize;
|
|
1192
|
-
if (limits.maxObjectSize) limits.maxObjectSize;
|
|
1226
|
+
if (limits.maxObjectSize) maxObjectSize = limits.maxObjectSize;
|
|
1227
|
+
objectSizeLimit = Math.min(maxObjectSize, maxMapSize);
|
|
1193
1228
|
}
|
|
1194
1229
|
|
|
1195
1230
|
const mult10 = new Array(147); // this is a table matching binary exponents to the multiplier to determine significant digit rounding
|
|
@@ -1391,7 +1426,7 @@
|
|
|
1391
1426
|
if (throwOnIterable)
|
|
1392
1427
|
return;
|
|
1393
1428
|
encode(value);
|
|
1394
|
-
if (bundledStrings) {
|
|
1429
|
+
if (bundledStrings && bundledStrings.position) { // position is only set once a bundle has been started
|
|
1395
1430
|
writeBundles(start, encode);
|
|
1396
1431
|
}
|
|
1397
1432
|
encoder.offset = position; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
|
|
@@ -2489,7 +2524,7 @@
|
|
|
2489
2524
|
}
|
|
2490
2525
|
|
|
2491
2526
|
const decoder = new Decoder(options);
|
|
2492
|
-
let incomplete;
|
|
2527
|
+
let incomplete, fatalError;
|
|
2493
2528
|
const parser = (chunk) => {
|
|
2494
2529
|
let yields;
|
|
2495
2530
|
// if there's incomplete data from previous chunk, concatinate and try again
|
|
@@ -2501,26 +2536,28 @@
|
|
|
2501
2536
|
try {
|
|
2502
2537
|
yields = decoder.decodeMultiple(chunk);
|
|
2503
2538
|
} catch (err) {
|
|
2539
|
+
yields = err.values;
|
|
2504
2540
|
if (err.incomplete) {
|
|
2505
2541
|
incomplete = chunk.slice(err.lastPosition);
|
|
2506
|
-
yields = err.values;
|
|
2507
2542
|
} else {
|
|
2508
|
-
|
|
2543
|
+
fatalError = err;
|
|
2509
2544
|
}
|
|
2510
2545
|
}
|
|
2511
|
-
return yields
|
|
2546
|
+
return yields || []
|
|
2512
2547
|
};
|
|
2513
2548
|
|
|
2514
2549
|
if (typeof bufferIterator[Symbol.iterator] === 'function') {
|
|
2515
2550
|
return (function * iter () {
|
|
2516
2551
|
for (const value of bufferIterator) {
|
|
2517
2552
|
yield * parser(value);
|
|
2553
|
+
if (fatalError) throw fatalError
|
|
2518
2554
|
}
|
|
2519
2555
|
})()
|
|
2520
2556
|
} else if (typeof bufferIterator[Symbol.asyncIterator] === 'function') {
|
|
2521
2557
|
return (async function * iter () {
|
|
2522
2558
|
for await (const value of bufferIterator) {
|
|
2523
2559
|
yield * parser(value);
|
|
2560
|
+
if (fatalError) throw fatalError
|
|
2524
2561
|
}
|
|
2525
2562
|
})()
|
|
2526
2563
|
}
|