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/README.md +4 -0
- package/decode.js +74 -48
- package/dist/decode-no-eval.cjs +76 -48
- package/dist/decode-no-eval.cjs.map +1 -1
- package/dist/index-no-eval.cjs +81 -50
- 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 +81 -50
- 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 +94 -66
- package/dist/node.cjs.map +1 -1
- package/dist/test.js +75 -48
- 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,13 @@
|
|
|
195
206
|
}
|
|
196
207
|
}
|
|
197
208
|
}
|
|
209
|
+
const nestedDecodeErrors = new WeakSet();
|
|
198
210
|
function checkedRead() {
|
|
199
211
|
try {
|
|
200
212
|
let result = read();
|
|
201
213
|
if (bundledStrings$1) {
|
|
202
|
-
if (position$1 >= bundledStrings$1.postBundlePosition)
|
|
203
|
-
|
|
204
|
-
error.incomplete = true;
|
|
205
|
-
throw error
|
|
206
|
-
}
|
|
214
|
+
if (position$1 >= bundledStrings$1.postBundlePosition)
|
|
215
|
+
throw new Error('Unexpected bundle position')
|
|
207
216
|
// bundled strings to skip past
|
|
208
217
|
position$1 = bundledStrings$1.postBundlePosition;
|
|
209
218
|
bundledStrings$1 = null;
|
|
@@ -227,7 +236,14 @@
|
|
|
227
236
|
return result
|
|
228
237
|
} catch(error) {
|
|
229
238
|
clearSource();
|
|
230
|
-
if (
|
|
239
|
+
if (nestedDecodeErrors.has(error)) {
|
|
240
|
+
// from a nested decode of embedded data (by an extension), which was complete in this source
|
|
241
|
+
if (error.incomplete)
|
|
242
|
+
error.incomplete = false;
|
|
243
|
+
} else if (error instanceof RangeError && position$1 + 8 > srcEnd ||
|
|
244
|
+
error && typeof error.message == 'string' && error.message.startsWith('Unexpected end of buffer')) {
|
|
245
|
+
// a DataView read past the end of the source; these read at most 8 bytes and precede advancing position.
|
|
246
|
+
// Any other RangeError (such as a stack overflow from deeply nested input) is fatal.
|
|
231
247
|
error.incomplete = true;
|
|
232
248
|
}
|
|
233
249
|
throw error
|
|
@@ -312,13 +328,13 @@
|
|
|
312
328
|
let i = 0;
|
|
313
329
|
if (currentDecoder.keyMap) {
|
|
314
330
|
while((key = read()) != STOP_CODE) {
|
|
315
|
-
if (i++ >=
|
|
331
|
+
if (i++ >= objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
|
|
316
332
|
object[safeKey(currentDecoder.decodeKey(key))] = read();
|
|
317
333
|
}
|
|
318
334
|
}
|
|
319
335
|
else {
|
|
320
336
|
while ((key = read()) != STOP_CODE) {
|
|
321
|
-
if (i++ >=
|
|
337
|
+
if (i++ >= objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
|
|
322
338
|
object[safeKey(key)] = read();
|
|
323
339
|
}
|
|
324
340
|
}
|
|
@@ -364,11 +380,13 @@
|
|
|
364
380
|
case 1: // negative int
|
|
365
381
|
return ~token
|
|
366
382
|
case 2: // buffer
|
|
383
|
+
if (token > srcEnd - position$1) throw endOfCBORError()
|
|
367
384
|
return readBin(token)
|
|
368
385
|
case 3: // string
|
|
369
|
-
if (srcStringEnd >= position$1) {
|
|
386
|
+
if (srcStringEnd >= position$1) { // already extracted, which only covers complete strings
|
|
370
387
|
return srcString.slice(position$1 - srcStringStart, (position$1 += token) - srcStringStart)
|
|
371
388
|
}
|
|
389
|
+
if (token > srcEnd - position$1) throw endOfCBORError()
|
|
372
390
|
if (srcStringEnd == 0 && srcEnd < 140 && token < 32) {
|
|
373
391
|
// for small blocks, avoiding the overhead of the extract call is helpful
|
|
374
392
|
let string = token < 16 ? shortStringInJS(token) : longStringInJS(token);
|
|
@@ -377,7 +395,7 @@
|
|
|
377
395
|
}
|
|
378
396
|
return readFixedString(token)
|
|
379
397
|
case 4: // array
|
|
380
|
-
if (token
|
|
398
|
+
if (token > maxArraySize) throw new Error(`Array length exceeds ${maxArraySize}`)
|
|
381
399
|
// every element occupies at least one byte, so a length beyond what remains in the source can
|
|
382
400
|
// never be satisfied; check before allocating so a tiny header can not force a huge allocation
|
|
383
401
|
if (token > srcEnd - position$1) throw endOfCBORError()
|
|
@@ -387,9 +405,9 @@
|
|
|
387
405
|
for (let i = 0; i < token; i++) array[i] = read();
|
|
388
406
|
return array
|
|
389
407
|
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
408
|
if (currentDecoder.mapsAsObjects) {
|
|
409
|
+
if (token > objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
|
|
410
|
+
if (token > (srcEnd - position$1) / 2) throw endOfCBORError() // each entry needs at least two bytes
|
|
393
411
|
let object = {};
|
|
394
412
|
if (currentDecoder.keyMap) for (let i = 0; i < token; i++) object[safeKey(currentDecoder.decodeKey(read()))] = read();
|
|
395
413
|
else for (let i = 0; i < token; i++) object[safeKey(read())] = read();
|
|
@@ -399,6 +417,8 @@
|
|
|
399
417
|
currentDecoder.mapsAsObjects = true;
|
|
400
418
|
restoreMapsAsObject = false;
|
|
401
419
|
}
|
|
420
|
+
if (token > maxMapSize) throw new Error(`Map size exceeds ${maxMapSize}`)
|
|
421
|
+
if (token > (srcEnd - position$1) / 2) throw endOfCBORError()
|
|
402
422
|
let map = new Map();
|
|
403
423
|
if (currentDecoder.keyMap) for (let i = 0; i < token; i++) map.set(currentDecoder.decodeKey(read()),read());
|
|
404
424
|
else for (let i = 0; i < token; i++) map.set(read(), read());
|
|
@@ -894,18 +914,12 @@
|
|
|
894
914
|
return (glbl[data[0]] || Error)(data[1], data[2])
|
|
895
915
|
};
|
|
896
916
|
const packedTable = (read) => {
|
|
897
|
-
if (
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
error.incomplete = true;
|
|
901
|
-
throw error
|
|
902
|
-
}
|
|
917
|
+
if (!(position$1 < srcEnd)) throw endOfCBORError()
|
|
918
|
+
if (src[position$1++] != 0x84)
|
|
919
|
+
throw new Error('Packed values structure must be followed by a 4 element array')
|
|
903
920
|
let newPackedValues = read(); // packed values
|
|
904
|
-
if (!newPackedValues || !newPackedValues.length)
|
|
905
|
-
|
|
906
|
-
error.incomplete = true;
|
|
907
|
-
throw error
|
|
908
|
-
}
|
|
921
|
+
if (!Array.isArray(newPackedValues) || !newPackedValues.length)
|
|
922
|
+
throw new Error('Packed values structure must be followed by a 4 element array')
|
|
909
923
|
packedValues = packedValues ? newPackedValues.concat(packedValues.slice(newPackedValues.length)) : newPackedValues;
|
|
910
924
|
packedValues.prefixes = read();
|
|
911
925
|
packedValues.suffixes = read();
|
|
@@ -923,10 +937,7 @@
|
|
|
923
937
|
}
|
|
924
938
|
if (typeof data == 'number')
|
|
925
939
|
return packedValues[16 + (data >= 0 ? 2 * data : (-2 * data - 1))]
|
|
926
|
-
|
|
927
|
-
if (data === undefined)
|
|
928
|
-
error.incomplete = true;
|
|
929
|
-
throw error
|
|
940
|
+
throw new Error('No support for non-integer packed references yet')
|
|
930
941
|
};
|
|
931
942
|
|
|
932
943
|
// The following code is an incomplete implementation of http://cbor.schmorp.de/stringref
|
|
@@ -996,9 +1007,19 @@
|
|
|
996
1007
|
(currentExtensions[259] = (read) => {
|
|
997
1008
|
// https://github.com/shanewholloway/js-cbor-codec/blob/master/docs/CBOR-259-spec
|
|
998
1009
|
// for decoding as a standard Map
|
|
999
|
-
|
|
1000
|
-
|
|
1010
|
+
let decoder = currentDecoder;
|
|
1011
|
+
if (decoder.mapsAsObjects) {
|
|
1012
|
+
decoder.mapsAsObjects = false;
|
|
1001
1013
|
restoreMapsAsObject = true;
|
|
1014
|
+
try {
|
|
1015
|
+
return read()
|
|
1016
|
+
} finally {
|
|
1017
|
+
// normally restored by the map header, but not if the tagged value is not a map or the read fails
|
|
1018
|
+
if (restoreMapsAsObject) {
|
|
1019
|
+
decoder.mapsAsObjects = true;
|
|
1020
|
+
restoreMapsAsObject = false;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1002
1023
|
}
|
|
1003
1024
|
return read()
|
|
1004
1025
|
}).handlesRead = true;
|
|
@@ -1118,10 +1139,12 @@
|
|
|
1118
1139
|
token = src[position$1++];
|
|
1119
1140
|
break
|
|
1120
1141
|
case 0x19:
|
|
1142
|
+
if (position$1 + 2 > srcEnd) throw endOfCBORError()
|
|
1121
1143
|
token = dataView.getUint16(position$1);
|
|
1122
1144
|
position$1 += 2;
|
|
1123
1145
|
break
|
|
1124
1146
|
case 0x1a:
|
|
1147
|
+
if (position$1 + 4 > srcEnd) throw endOfCBORError()
|
|
1125
1148
|
token = dataView.getUint32(position$1);
|
|
1126
1149
|
position$1 += 4;
|
|
1127
1150
|
break
|
|
@@ -1161,20 +1184,25 @@
|
|
|
1161
1184
|
let savedStructures = currentStructures;
|
|
1162
1185
|
let savedDecoder = currentDecoder;
|
|
1163
1186
|
let savedSequentialMode = sequentialMode;
|
|
1164
|
-
let
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1187
|
+
let savedRestoreMapsAsObject = restoreMapsAsObject;
|
|
1188
|
+
restoreMapsAsObject = false;
|
|
1189
|
+
try {
|
|
1190
|
+
return callback()
|
|
1191
|
+
} finally {
|
|
1192
|
+
srcEnd = savedSrcEnd;
|
|
1193
|
+
position$1 = savedPosition;
|
|
1194
|
+
srcStringStart = savedSrcStringStart;
|
|
1195
|
+
srcStringEnd = savedSrcStringEnd;
|
|
1196
|
+
srcString = savedSrcString;
|
|
1197
|
+
referenceMap = savedReferenceMap;
|
|
1198
|
+
bundledStrings$1 = savedBundledStrings;
|
|
1199
|
+
src = savedSrc;
|
|
1200
|
+
sequentialMode = savedSequentialMode;
|
|
1201
|
+
currentStructures = savedStructures;
|
|
1202
|
+
currentDecoder = savedDecoder;
|
|
1203
|
+
restoreMapsAsObject = savedRestoreMapsAsObject;
|
|
1204
|
+
dataView = new DataView(src.buffer, src.byteOffset, src.byteLength);
|
|
1205
|
+
}
|
|
1178
1206
|
}
|
|
1179
1207
|
function clearSource() {
|
|
1180
1208
|
src = null;
|
|
@@ -1189,7 +1217,8 @@
|
|
|
1189
1217
|
function setSizeLimits(limits) {
|
|
1190
1218
|
if (limits.maxMapSize) maxMapSize = limits.maxMapSize;
|
|
1191
1219
|
if (limits.maxArraySize) maxArraySize = limits.maxArraySize;
|
|
1192
|
-
if (limits.maxObjectSize) limits.maxObjectSize;
|
|
1220
|
+
if (limits.maxObjectSize) maxObjectSize = limits.maxObjectSize;
|
|
1221
|
+
objectSizeLimit = Math.min(maxObjectSize, maxMapSize);
|
|
1193
1222
|
}
|
|
1194
1223
|
|
|
1195
1224
|
const mult10 = new Array(147); // this is a table matching binary exponents to the multiplier to determine significant digit rounding
|
|
@@ -1391,7 +1420,7 @@
|
|
|
1391
1420
|
if (throwOnIterable)
|
|
1392
1421
|
return;
|
|
1393
1422
|
encode(value);
|
|
1394
|
-
if (bundledStrings) {
|
|
1423
|
+
if (bundledStrings && bundledStrings.position) { // position is only set once a bundle has been started
|
|
1395
1424
|
writeBundles(start, encode);
|
|
1396
1425
|
}
|
|
1397
1426
|
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 +2518,7 @@
|
|
|
2489
2518
|
}
|
|
2490
2519
|
|
|
2491
2520
|
const decoder = new Decoder(options);
|
|
2492
|
-
let incomplete;
|
|
2521
|
+
let incomplete, fatalError;
|
|
2493
2522
|
const parser = (chunk) => {
|
|
2494
2523
|
let yields;
|
|
2495
2524
|
// if there's incomplete data from previous chunk, concatinate and try again
|
|
@@ -2501,26 +2530,28 @@
|
|
|
2501
2530
|
try {
|
|
2502
2531
|
yields = decoder.decodeMultiple(chunk);
|
|
2503
2532
|
} catch (err) {
|
|
2533
|
+
yields = err.values;
|
|
2504
2534
|
if (err.incomplete) {
|
|
2505
2535
|
incomplete = chunk.slice(err.lastPosition);
|
|
2506
|
-
yields = err.values;
|
|
2507
2536
|
} else {
|
|
2508
|
-
|
|
2537
|
+
fatalError = err;
|
|
2509
2538
|
}
|
|
2510
2539
|
}
|
|
2511
|
-
return yields
|
|
2540
|
+
return yields || []
|
|
2512
2541
|
};
|
|
2513
2542
|
|
|
2514
2543
|
if (typeof bufferIterator[Symbol.iterator] === 'function') {
|
|
2515
2544
|
return (function * iter () {
|
|
2516
2545
|
for (const value of bufferIterator) {
|
|
2517
2546
|
yield * parser(value);
|
|
2547
|
+
if (fatalError) throw fatalError
|
|
2518
2548
|
}
|
|
2519
2549
|
})()
|
|
2520
2550
|
} else if (typeof bufferIterator[Symbol.asyncIterator] === 'function') {
|
|
2521
2551
|
return (async function * iter () {
|
|
2522
2552
|
for await (const value of bufferIterator) {
|
|
2523
2553
|
yield * parser(value);
|
|
2554
|
+
if (fatalError) throw fatalError
|
|
2524
2555
|
}
|
|
2525
2556
|
})()
|
|
2526
2557
|
}
|