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