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