cbor-x 1.5.7 → 1.5.9
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/decode.js +22 -4
- package/dist/decode-no-eval.cjs +22 -4
- package/dist/decode-no-eval.cjs.map +1 -1
- package/dist/index-no-eval.cjs +35 -17
- 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 +35 -17
- 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 +35 -17
- package/dist/node.cjs.map +1 -1
- package/dist/test.js +88 -28
- package/dist/test.js.map +1 -1
- package/encode.js +13 -13
- package/index.d.ts +6 -0
- package/package.json +9 -3
package/dist/test.js
CHANGED
|
@@ -499,7 +499,12 @@
|
|
|
499
499
|
}
|
|
500
500
|
|
|
501
501
|
function safeKey(key) {
|
|
502
|
-
|
|
502
|
+
// protect against prototype pollution
|
|
503
|
+
if (typeof key === 'string') return key === '__proto__' ? '__proto_' : key
|
|
504
|
+
if (typeof key === 'number' || typeof key === 'boolean' || typeof key === 'bigint') return key.toString();
|
|
505
|
+
if (key == null) return key + '';
|
|
506
|
+
// protect against expensive (DoS) string conversions
|
|
507
|
+
throw new Error('Invalid property name type ' + typeof key);
|
|
503
508
|
}
|
|
504
509
|
|
|
505
510
|
let readFixedString = readStringJS;
|
|
@@ -914,6 +919,7 @@
|
|
|
914
919
|
referenceMap.id = 0;
|
|
915
920
|
}
|
|
916
921
|
let id = referenceMap.id++;
|
|
922
|
+
let startingPosition = position$1;
|
|
917
923
|
let token = src[position$1];
|
|
918
924
|
let target;
|
|
919
925
|
// TODO: handle Maps, Sets, and other types that can cycle; this is complicated, because you potentially need to read
|
|
@@ -926,8 +932,20 @@
|
|
|
926
932
|
let refEntry = { target }; // a placeholder object
|
|
927
933
|
referenceMap.set(id, refEntry);
|
|
928
934
|
let targetProperties = read(); // read the next value as the target object to id
|
|
929
|
-
if (refEntry.used) // there is a cycle, so we have to assign properties to original target
|
|
935
|
+
if (refEntry.used) {// there is a cycle, so we have to assign properties to original target
|
|
936
|
+
if (Object.getPrototypeOf(target) !== Object.getPrototypeOf(targetProperties)) {
|
|
937
|
+
// this means that the returned target does not match the targetProperties, so we need rerun the read to
|
|
938
|
+
// have the correctly create instance be assigned as a reference, then we do the copy the properties back to the
|
|
939
|
+
// target
|
|
940
|
+
// reset the position so that the read can be repeated
|
|
941
|
+
position$1 = startingPosition;
|
|
942
|
+
// the returned instance is our new target for references
|
|
943
|
+
target = targetProperties;
|
|
944
|
+
referenceMap.set(id, { target });
|
|
945
|
+
targetProperties = read();
|
|
946
|
+
}
|
|
930
947
|
return Object.assign(target, targetProperties)
|
|
948
|
+
}
|
|
931
949
|
refEntry.target = targetProperties; // the placeholder wasn't used, replace with the deserialized one
|
|
932
950
|
return targetProperties // no cycle, can just use the returned read object
|
|
933
951
|
};
|
|
@@ -1009,7 +1027,7 @@
|
|
|
1009
1027
|
for (let littleEndian = 0; littleEndian < 2; littleEndian++) {
|
|
1010
1028
|
if (!littleEndian && bytesPerElement == 1)
|
|
1011
1029
|
continue
|
|
1012
|
-
let sizeShift = bytesPerElement == 2 ? 1 : bytesPerElement == 4 ? 2 : 3;
|
|
1030
|
+
let sizeShift = bytesPerElement == 2 ? 1 : bytesPerElement == 4 ? 2 : bytesPerElement == 8 ? 3 : 0;
|
|
1013
1031
|
currentExtensions[littleEndian ? tag : (tag - 4)] = (bytesPerElement == 1 || littleEndian == isLittleEndianMachine$1) ? (buffer) => {
|
|
1014
1032
|
if (!TypedArray)
|
|
1015
1033
|
throw new Error('Could not find typed array for code ' + tag)
|
|
@@ -1019,7 +1037,7 @@
|
|
|
1019
1037
|
bytesPerElement === 2 && !(buffer.byteOffset & 1) ||
|
|
1020
1038
|
bytesPerElement === 4 && !(buffer.byteOffset & 3) ||
|
|
1021
1039
|
bytesPerElement === 8 && !(buffer.byteOffset & 7))
|
|
1022
|
-
return new TypedArray(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
1040
|
+
return new TypedArray(buffer.buffer, buffer.byteOffset, buffer.byteLength >> sizeShift);
|
|
1023
1041
|
}
|
|
1024
1042
|
// we have to slice/copy here to get a new ArrayBuffer, if we are not word/byte aligned
|
|
1025
1043
|
return new TypedArray(Uint8Array.prototype.slice.call(buffer, 0).buffer)
|
|
@@ -1618,7 +1636,7 @@
|
|
|
1618
1636
|
}
|
|
1619
1637
|
let constructor = value.constructor;
|
|
1620
1638
|
if (constructor === Object) {
|
|
1621
|
-
writeObject(value
|
|
1639
|
+
writeObject(value);
|
|
1622
1640
|
} else if (constructor === Array) {
|
|
1623
1641
|
length = value.length;
|
|
1624
1642
|
if (length < 0x18) {
|
|
@@ -1713,8 +1731,8 @@
|
|
|
1713
1731
|
return encode(json)
|
|
1714
1732
|
}
|
|
1715
1733
|
|
|
1716
|
-
// no extension found, write as object
|
|
1717
|
-
writeObject(value
|
|
1734
|
+
// no extension found, write as a plain object
|
|
1735
|
+
writeObject(value);
|
|
1718
1736
|
}
|
|
1719
1737
|
}
|
|
1720
1738
|
} else if (type === 'boolean') {
|
|
@@ -1776,19 +1794,19 @@
|
|
|
1776
1794
|
}
|
|
1777
1795
|
}
|
|
1778
1796
|
} :
|
|
1779
|
-
(object
|
|
1797
|
+
(object) => {
|
|
1780
1798
|
target[position++] = 0xb9; // always use map 16, so we can preallocate and set the length afterwards
|
|
1781
1799
|
let objectOffset = position - start;
|
|
1782
1800
|
position += 2;
|
|
1783
1801
|
let size = 0;
|
|
1784
1802
|
if (encoder.keyMap) {
|
|
1785
|
-
for (let key in object) if (
|
|
1803
|
+
for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1786
1804
|
encode(encoder.encodeKey(key));
|
|
1787
1805
|
encode(object[key]);
|
|
1788
1806
|
size++;
|
|
1789
1807
|
}
|
|
1790
1808
|
} else {
|
|
1791
|
-
for (let key in object) if (
|
|
1809
|
+
for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1792
1810
|
encode(key);
|
|
1793
1811
|
encode(object[key]);
|
|
1794
1812
|
size++;
|
|
@@ -1797,7 +1815,7 @@
|
|
|
1797
1815
|
target[objectOffset++ + start] = size >> 8;
|
|
1798
1816
|
target[objectOffset + start] = size & 0xff;
|
|
1799
1817
|
} :
|
|
1800
|
-
(object,
|
|
1818
|
+
(object, skipValues) => {
|
|
1801
1819
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1802
1820
|
let newTransitions = 0;
|
|
1803
1821
|
let length = 0;
|
|
@@ -1816,7 +1834,7 @@
|
|
|
1816
1834
|
transition = nextTransition;
|
|
1817
1835
|
}
|
|
1818
1836
|
} else {
|
|
1819
|
-
for (let key in object) if (
|
|
1837
|
+
for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1820
1838
|
nextTransition = transition[key];
|
|
1821
1839
|
if (!nextTransition) {
|
|
1822
1840
|
if (transition[RECORD_SYMBOL] & 0x100000) {// this indicates it is a brancheable/extendable terminal node, so we will use this record id and extend it
|
|
@@ -1876,9 +1894,9 @@
|
|
|
1876
1894
|
writeArrayHeader(length + 2);
|
|
1877
1895
|
encode(0xe000 + recordId);
|
|
1878
1896
|
encode(keys);
|
|
1879
|
-
if (
|
|
1897
|
+
if (skipValues) return; // special exit for iterator
|
|
1880
1898
|
for (let key in object)
|
|
1881
|
-
if (
|
|
1899
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key))
|
|
1882
1900
|
encode(object[key]);
|
|
1883
1901
|
return
|
|
1884
1902
|
}
|
|
@@ -1888,9 +1906,9 @@
|
|
|
1888
1906
|
} else {
|
|
1889
1907
|
writeArrayHeader(length);
|
|
1890
1908
|
}
|
|
1891
|
-
if (
|
|
1909
|
+
if (skipValues) return; // special exit for iterator
|
|
1892
1910
|
for (let key in object)
|
|
1893
|
-
if (
|
|
1911
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key))
|
|
1894
1912
|
encode(object[key]);
|
|
1895
1913
|
};
|
|
1896
1914
|
const makeRoom = (end) => {
|
|
@@ -1928,7 +1946,7 @@
|
|
|
1928
1946
|
if (constructor === Object) {
|
|
1929
1947
|
let useRecords = encoder.useRecords !== false;
|
|
1930
1948
|
if (useRecords)
|
|
1931
|
-
writeObject(object,
|
|
1949
|
+
writeObject(object, true); // write the record identifier
|
|
1932
1950
|
else
|
|
1933
1951
|
writeEntityLength(Object.keys(object).length, 0xa0);
|
|
1934
1952
|
for (let key in object) {
|
|
@@ -2645,22 +2663,17 @@
|
|
|
2645
2663
|
assert.deepEqual(deserialized1, data1);
|
|
2646
2664
|
assert.deepEqual(deserialized2, data2);
|
|
2647
2665
|
});
|
|
2648
|
-
test('extended class encode/decode', function(){
|
|
2666
|
+
test('extended class encode/decode', function() {
|
|
2649
2667
|
function Extended() {
|
|
2650
2668
|
|
|
2651
2669
|
}
|
|
2670
|
+
|
|
2652
2671
|
Extended.prototype.getDouble = function() {
|
|
2653
2672
|
return this.value * 2
|
|
2654
2673
|
};
|
|
2655
2674
|
var instance = new Extended();
|
|
2656
2675
|
instance.value = 4;
|
|
2657
2676
|
instance.string = 'decode this: ᾜ';
|
|
2658
|
-
var data = {
|
|
2659
|
-
prop1: 'has multi-byte: ᾜ',
|
|
2660
|
-
extendedInstance: instance,
|
|
2661
|
-
prop2: 'more string',
|
|
2662
|
-
num: 3,
|
|
2663
|
-
};
|
|
2664
2677
|
let encoder = new Encoder();
|
|
2665
2678
|
addExtension({
|
|
2666
2679
|
Class: Extended,
|
|
@@ -2675,10 +2688,37 @@
|
|
|
2675
2688
|
return encoder.encode([instance.value, instance.string])
|
|
2676
2689
|
}
|
|
2677
2690
|
});
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2691
|
+
});
|
|
2692
|
+
test('extended class encode/decode with self reference in structered clone', function(){
|
|
2693
|
+
function Extended() {
|
|
2694
|
+
|
|
2695
|
+
}
|
|
2696
|
+
addExtension({
|
|
2697
|
+
Class: Extended,
|
|
2698
|
+
tag: 301,
|
|
2699
|
+
decode: function(data) {
|
|
2700
|
+
let e = new Extended();
|
|
2701
|
+
e.value = data[0];
|
|
2702
|
+
e.string = data[1];
|
|
2703
|
+
return e
|
|
2704
|
+
},
|
|
2705
|
+
encode: function(instance, encode) {
|
|
2706
|
+
return encode([instance.value, instance.string])
|
|
2707
|
+
}
|
|
2708
|
+
});
|
|
2709
|
+
var instance = new Extended();
|
|
2710
|
+
instance.value = instance;
|
|
2711
|
+
instance.string = 'hi';
|
|
2712
|
+
let data = {
|
|
2713
|
+
extended: instance
|
|
2714
|
+
};
|
|
2715
|
+
let encoder = new Encoder({
|
|
2716
|
+
structuredClone: true,
|
|
2717
|
+
});
|
|
2718
|
+
let serialized = encoder.encode(data);
|
|
2719
|
+
encoder.decode(serialized);
|
|
2720
|
+
assert(data.extended.value.value === data.extended);
|
|
2721
|
+
assert(data.extended instanceof Extended);
|
|
2682
2722
|
});
|
|
2683
2723
|
|
|
2684
2724
|
test('addExtension with map', function(){
|
|
@@ -2820,6 +2860,12 @@
|
|
|
2820
2860
|
var deserialized = decode(serialized);
|
|
2821
2861
|
assert.deepEqual(deserialized, data);
|
|
2822
2862
|
});
|
|
2863
|
+
test('object with __proto__', function(){
|
|
2864
|
+
const data = { foo: 'bar', __proto__: { isAdmin: true } };
|
|
2865
|
+
var serialized = encode(data);
|
|
2866
|
+
var deserialized = decode(serialized);
|
|
2867
|
+
assert.deepEqual(deserialized, { foo: 'bar' });
|
|
2868
|
+
});
|
|
2823
2869
|
|
|
2824
2870
|
test('big buffer', function() {
|
|
2825
2871
|
var size = 100000000;
|
|
@@ -3088,6 +3134,11 @@
|
|
|
3088
3134
|
let badInput = Buffer.from('7b2273657269616c6e6f223a2265343a30222c226970223a223139322e3136382e312e3335222c226b6579223a226770735f736563726574227d', 'hex');
|
|
3089
3135
|
assert.throws(function(){ decode(badInput); }); // should throw, not crash
|
|
3090
3136
|
});
|
|
3137
|
+
test('buffer key', function() {
|
|
3138
|
+
let encoder = new Encoder({ mapsAsObjects: false });
|
|
3139
|
+
let test = encoder.decode(Buffer.from('D87982A1446E616D654361626301', 'hex'));
|
|
3140
|
+
console.log(test);
|
|
3141
|
+
});
|
|
3091
3142
|
test('encode as iterator', function() {
|
|
3092
3143
|
let hasIterables = {
|
|
3093
3144
|
a: 1,
|
|
@@ -3180,6 +3231,15 @@
|
|
|
3180
3231
|
decode(Buffer.concat(result));
|
|
3181
3232
|
console.log(performance.now() - start, result.length);
|
|
3182
3233
|
});
|
|
3234
|
+
|
|
3235
|
+
test('little-endian typed array with aligned data', function() {
|
|
3236
|
+
// array[1] { uint32-little-endian-typed-array { bytes <00 00 00 00> } }
|
|
3237
|
+
let data = new Uint8Array([ 129, 216, 70, 68, 0, 0, 0, 0 ]);
|
|
3238
|
+
assert.deepEqual(decode(data), [new Uint32Array([0])]);
|
|
3239
|
+
|
|
3240
|
+
let value = {x: new Float32Array([1, 2, 3])};
|
|
3241
|
+
assert.deepEqual(decode(encode(value)), value);
|
|
3242
|
+
});
|
|
3183
3243
|
});
|
|
3184
3244
|
suite('CBOR performance tests', function(){
|
|
3185
3245
|
test('performance JSON.parse', function() {
|