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/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
|
-
//
|
|
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
|
-
|
|
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,15 @@
|
|
|
199
209
|
}
|
|
200
210
|
}
|
|
201
211
|
}
|
|
212
|
+
const nestedDecodeErrors = new WeakSet();
|
|
213
|
+
let arrayAllocationBudget;
|
|
202
214
|
function checkedRead() {
|
|
203
215
|
try {
|
|
216
|
+
arrayAllocationBudget = srcEnd - position$1;
|
|
204
217
|
let result = read();
|
|
205
218
|
if (bundledStrings$1) {
|
|
206
|
-
if (position$1 >= bundledStrings$1.postBundlePosition)
|
|
207
|
-
|
|
208
|
-
error.incomplete = true;
|
|
209
|
-
throw error
|
|
210
|
-
}
|
|
219
|
+
if (position$1 >= bundledStrings$1.postBundlePosition)
|
|
220
|
+
throw new Error('Unexpected bundle position')
|
|
211
221
|
// bundled strings to skip past
|
|
212
222
|
position$1 = bundledStrings$1.postBundlePosition;
|
|
213
223
|
bundledStrings$1 = null;
|
|
@@ -231,7 +241,14 @@
|
|
|
231
241
|
return result
|
|
232
242
|
} catch(error) {
|
|
233
243
|
clearSource();
|
|
234
|
-
if (
|
|
244
|
+
if (nestedDecodeErrors.has(error)) {
|
|
245
|
+
// from a nested decode of embedded data (by an extension), which was complete in this source
|
|
246
|
+
if (error.incomplete)
|
|
247
|
+
error.incomplete = false;
|
|
248
|
+
} else if (error instanceof RangeError && position$1 + 8 > srcEnd ||
|
|
249
|
+
error && typeof error.message == 'string' && error.message.startsWith('Unexpected end of buffer')) {
|
|
250
|
+
// a DataView read past the end of the source; these read at most 8 bytes and precede advancing position.
|
|
251
|
+
// Any other RangeError (such as a stack overflow from deeply nested input) is fatal.
|
|
235
252
|
error.incomplete = true;
|
|
236
253
|
}
|
|
237
254
|
throw error
|
|
@@ -316,13 +333,13 @@
|
|
|
316
333
|
let i = 0;
|
|
317
334
|
if (currentDecoder.keyMap) {
|
|
318
335
|
while((key = read()) != STOP_CODE) {
|
|
319
|
-
if (i++ >=
|
|
336
|
+
if (i++ >= objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
|
|
320
337
|
object[safeKey(currentDecoder.decodeKey(key))] = read();
|
|
321
338
|
}
|
|
322
339
|
}
|
|
323
340
|
else {
|
|
324
341
|
while ((key = read()) != STOP_CODE) {
|
|
325
|
-
if (i++ >=
|
|
342
|
+
if (i++ >= objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
|
|
326
343
|
object[safeKey(key)] = read();
|
|
327
344
|
}
|
|
328
345
|
}
|
|
@@ -368,11 +385,13 @@
|
|
|
368
385
|
case 1: // negative int
|
|
369
386
|
return ~token
|
|
370
387
|
case 2: // buffer
|
|
388
|
+
if (token > srcEnd - position$1) throw endOfCBORError()
|
|
371
389
|
return readBin(token)
|
|
372
390
|
case 3: // string
|
|
373
|
-
if (srcStringEnd >= position$1) {
|
|
391
|
+
if (srcStringEnd >= position$1) { // already extracted, which only covers complete strings
|
|
374
392
|
return srcString.slice(position$1 - srcStringStart, (position$1 += token) - srcStringStart)
|
|
375
393
|
}
|
|
394
|
+
if (token > srcEnd - position$1) throw endOfCBORError()
|
|
376
395
|
if (srcStringEnd == 0 && srcEnd < 140 && token < 32) {
|
|
377
396
|
// for small blocks, avoiding the overhead of the extract call is helpful
|
|
378
397
|
let string = token < 16 ? shortStringInJS(token) : longStringInJS(token);
|
|
@@ -381,19 +400,21 @@
|
|
|
381
400
|
}
|
|
382
401
|
return readFixedString(token)
|
|
383
402
|
case 4: // array
|
|
384
|
-
if (token
|
|
403
|
+
if (token > maxArraySize) throw new Error(`Array length exceeds ${maxArraySize}`)
|
|
385
404
|
// every element occupies at least one byte, so a length beyond what remains in the source can
|
|
386
405
|
// never be satisfied; check before allocating so a tiny header can not force a huge allocation
|
|
387
|
-
|
|
406
|
+
// nested arrays each pass the check above yet still preallocate, so also spend from a
|
|
407
|
+
// per-decode budget of the remaining bytes; the summed lengths of any valid tree stay under it
|
|
408
|
+
if (token > srcEnd - position$1 || (arrayAllocationBudget -= token) < 0) throw endOfCBORError()
|
|
388
409
|
let array = new Array(token);
|
|
389
410
|
//if (currentDecoder.keyMap) for (let i = 0; i < token; i++) array[i] = currentDecoder.decodeKey(read())
|
|
390
411
|
//else
|
|
391
412
|
for (let i = 0; i < token; i++) array[i] = read();
|
|
392
413
|
return array
|
|
393
414
|
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
415
|
if (currentDecoder.mapsAsObjects) {
|
|
416
|
+
if (token > objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
|
|
417
|
+
if (token > (srcEnd - position$1) / 2) throw endOfCBORError() // each entry needs at least two bytes
|
|
397
418
|
let object = {};
|
|
398
419
|
if (currentDecoder.keyMap) for (let i = 0; i < token; i++) object[safeKey(currentDecoder.decodeKey(read()))] = read();
|
|
399
420
|
else for (let i = 0; i < token; i++) object[safeKey(read())] = read();
|
|
@@ -403,6 +424,8 @@
|
|
|
403
424
|
currentDecoder.mapsAsObjects = true;
|
|
404
425
|
restoreMapsAsObject = false;
|
|
405
426
|
}
|
|
427
|
+
if (token > maxMapSize) throw new Error(`Map size exceeds ${maxMapSize}`)
|
|
428
|
+
if (token > (srcEnd - position$1) / 2) throw endOfCBORError()
|
|
406
429
|
let map = new Map();
|
|
407
430
|
if (currentDecoder.keyMap) for (let i = 0; i < token; i++) map.set(currentDecoder.decodeKey(read()),read());
|
|
408
431
|
else for (let i = 0; i < token; i++) map.set(read(), read());
|
|
@@ -930,18 +953,12 @@
|
|
|
930
953
|
return (glbl[data[0]] || Error)(data[1], data[2])
|
|
931
954
|
};
|
|
932
955
|
const packedTable = (read) => {
|
|
933
|
-
if (
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
error.incomplete = true;
|
|
937
|
-
throw error
|
|
938
|
-
}
|
|
956
|
+
if (!(position$1 < srcEnd)) throw endOfCBORError()
|
|
957
|
+
if (src[position$1++] != 0x84)
|
|
958
|
+
throw new Error('Packed values structure must be followed by a 4 element array')
|
|
939
959
|
let newPackedValues = read(); // packed values
|
|
940
|
-
if (!newPackedValues || !newPackedValues.length)
|
|
941
|
-
|
|
942
|
-
error.incomplete = true;
|
|
943
|
-
throw error
|
|
944
|
-
}
|
|
960
|
+
if (!Array.isArray(newPackedValues) || !newPackedValues.length)
|
|
961
|
+
throw new Error('Packed values structure must be followed by a 4 element array')
|
|
945
962
|
packedValues = packedValues ? newPackedValues.concat(packedValues.slice(newPackedValues.length)) : newPackedValues;
|
|
946
963
|
packedValues.prefixes = read();
|
|
947
964
|
packedValues.suffixes = read();
|
|
@@ -959,10 +976,7 @@
|
|
|
959
976
|
}
|
|
960
977
|
if (typeof data == 'number')
|
|
961
978
|
return packedValues[16 + (data >= 0 ? 2 * data : (-2 * data - 1))]
|
|
962
|
-
|
|
963
|
-
if (data === undefined)
|
|
964
|
-
error.incomplete = true;
|
|
965
|
-
throw error
|
|
979
|
+
throw new Error('No support for non-integer packed references yet')
|
|
966
980
|
};
|
|
967
981
|
|
|
968
982
|
// The following code is an incomplete implementation of http://cbor.schmorp.de/stringref
|
|
@@ -1032,9 +1046,19 @@
|
|
|
1032
1046
|
(currentExtensions[259] = (read) => {
|
|
1033
1047
|
// https://github.com/shanewholloway/js-cbor-codec/blob/master/docs/CBOR-259-spec
|
|
1034
1048
|
// for decoding as a standard Map
|
|
1035
|
-
|
|
1036
|
-
|
|
1049
|
+
let decoder = currentDecoder;
|
|
1050
|
+
if (decoder.mapsAsObjects) {
|
|
1051
|
+
decoder.mapsAsObjects = false;
|
|
1037
1052
|
restoreMapsAsObject = true;
|
|
1053
|
+
try {
|
|
1054
|
+
return read()
|
|
1055
|
+
} finally {
|
|
1056
|
+
// normally restored by the map header, but not if the tagged value is not a map or the read fails
|
|
1057
|
+
if (restoreMapsAsObject) {
|
|
1058
|
+
decoder.mapsAsObjects = true;
|
|
1059
|
+
restoreMapsAsObject = false;
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1038
1062
|
}
|
|
1039
1063
|
return read()
|
|
1040
1064
|
}).handlesRead = true;
|
|
@@ -1154,10 +1178,12 @@
|
|
|
1154
1178
|
token = src[position$1++];
|
|
1155
1179
|
break
|
|
1156
1180
|
case 0x19:
|
|
1181
|
+
if (position$1 + 2 > srcEnd) throw endOfCBORError()
|
|
1157
1182
|
token = dataView.getUint16(position$1);
|
|
1158
1183
|
position$1 += 2;
|
|
1159
1184
|
break
|
|
1160
1185
|
case 0x1a:
|
|
1186
|
+
if (position$1 + 4 > srcEnd) throw endOfCBORError()
|
|
1161
1187
|
token = dataView.getUint32(position$1);
|
|
1162
1188
|
position$1 += 4;
|
|
1163
1189
|
break
|
|
@@ -1199,22 +1225,29 @@
|
|
|
1199
1225
|
let savedStructures = currentStructures;
|
|
1200
1226
|
let savedDecoder = currentDecoder;
|
|
1201
1227
|
let savedSequentialMode = sequentialMode;
|
|
1202
|
-
let
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1228
|
+
let savedRestoreMapsAsObject = restoreMapsAsObject;
|
|
1229
|
+
let savedArrayAllocationBudget = arrayAllocationBudget;
|
|
1230
|
+
restoreMapsAsObject = false;
|
|
1231
|
+
try {
|
|
1232
|
+
return callback()
|
|
1233
|
+
} finally {
|
|
1234
|
+
srcEnd = savedSrcEnd;
|
|
1235
|
+
position$1 = savedPosition;
|
|
1236
|
+
stringPosition = savedStringPosition;
|
|
1237
|
+
srcStringStart = savedSrcStringStart;
|
|
1238
|
+
srcStringEnd = savedSrcStringEnd;
|
|
1239
|
+
srcString = savedSrcString;
|
|
1240
|
+
strings = savedStrings;
|
|
1241
|
+
referenceMap = savedReferenceMap;
|
|
1242
|
+
bundledStrings$1 = savedBundledStrings;
|
|
1243
|
+
src = savedSrc;
|
|
1244
|
+
sequentialMode = savedSequentialMode;
|
|
1245
|
+
currentStructures = savedStructures;
|
|
1246
|
+
currentDecoder = savedDecoder;
|
|
1247
|
+
restoreMapsAsObject = savedRestoreMapsAsObject;
|
|
1248
|
+
arrayAllocationBudget = savedArrayAllocationBudget;
|
|
1249
|
+
dataView = new DataView(src.buffer, src.byteOffset, src.byteLength);
|
|
1250
|
+
}
|
|
1218
1251
|
}
|
|
1219
1252
|
function clearSource() {
|
|
1220
1253
|
src = null;
|
|
@@ -1420,7 +1453,7 @@
|
|
|
1420
1453
|
if (throwOnIterable)
|
|
1421
1454
|
return;
|
|
1422
1455
|
encode(value);
|
|
1423
|
-
if (bundledStrings) {
|
|
1456
|
+
if (bundledStrings && bundledStrings.position) { // position is only set once a bundle has been started
|
|
1424
1457
|
writeBundles(start, encode);
|
|
1425
1458
|
}
|
|
1426
1459
|
encoder.offset = position; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
|