@marcuspuchalla/nachos 0.1.3 → 0.1.4
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/CHANGELOG.md +23 -0
- package/dist/{chunk-5A5T56JB.js → chunk-5IWW5H47.js} +378 -207
- package/dist/chunk-5IWW5H47.js.map +1 -0
- package/dist/{chunk-PTWN7K3Y.cjs → chunk-RVG2BY32.cjs} +378 -207
- package/dist/chunk-RVG2BY32.cjs.map +1 -0
- package/dist/{chunk-R62CQQNI.cjs → chunk-S4RXO6IB.cjs} +195 -165
- package/dist/chunk-S4RXO6IB.cjs.map +1 -0
- package/dist/{chunk-2MTLSQ7E.js → chunk-UMAX5MX5.js} +195 -165
- package/dist/chunk-UMAX5MX5.js.map +1 -0
- package/dist/encoder/index.cjs +13 -13
- package/dist/encoder/index.d.cts +2 -2
- package/dist/encoder/index.d.ts +2 -2
- package/dist/encoder/index.js +1 -1
- package/dist/index.cjs +32 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -19
- package/dist/index.d.ts +28 -19
- package/dist/index.js +16 -16
- package/dist/index.js.map +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/parser/index.cjs +14 -14
- package/dist/parser/index.d.cts +3 -1
- package/dist/parser/index.d.ts +3 -1
- package/dist/parser/index.js +1 -1
- package/dist/{useCborSimpleEncoder-TVxzNJ_9.d.ts → useCborSimpleEncoder-BoKEmjP9.d.ts} +0 -2
- package/dist/{useCborSimpleEncoder-ButVU988.d.cts → useCborSimpleEncoder-C_OHxoB8.d.cts} +0 -2
- package/dist/{useCborTag-Cs1CZuXZ.d.cts → useCborTag-BD6Sqp7p.d.ts} +9 -4
- package/dist/{useCborTag-xV2Pz2VY.d.ts → useCborTag-QpZR-Er2.d.cts} +9 -4
- package/package.json +1 -1
- package/src/__tests__/public-api.test.ts +153 -0
- package/src/__tests__/roundtrip.test.ts +5 -6
- package/src/encoder/__tests__/cbor-collection-encoder.test.ts +103 -5
- package/src/encoder/__tests__/cbor-encoder-errors.test.ts +40 -5
- package/src/encoder/__tests__/cbor-simple-encoder.test.ts +126 -0
- package/src/encoder/composables/useCborCollectionEncoder.ts +28 -25
- package/src/encoder/composables/useCborEncoder.ts +21 -0
- package/src/encoder/composables/useCborSimpleEncoder.ts +34 -7
- package/src/encoder/types.ts +0 -2
- package/src/index.ts +29 -20
- package/src/parser/__tests__/buffer-native-parsing.test.ts +338 -0
- package/src/parser/__tests__/cbor-map-duplicate-keys.test.ts +97 -7
- package/src/parser/__tests__/cbor-security-dos-protection.test.ts +164 -31
- package/src/parser/__tests__/cbor-standard-tags.test.ts +75 -7
- package/src/parser/__tests__/cbor-tag-reparse-fix.test.ts +268 -0
- package/src/parser/composables/useCborCollection.ts +45 -42
- package/src/parser/composables/useCborFloat.ts +2 -1
- package/src/parser/composables/useCborInteger.ts +24 -10
- package/src/parser/composables/useCborParser.ts +387 -197
- package/src/parser/composables/useCborTag.ts +45 -37
- package/src/parser/utils.ts +11 -0
- package/dist/chunk-2MTLSQ7E.js.map +0 -1
- package/dist/chunk-5A5T56JB.js.map +0 -1
- package/dist/chunk-PTWN7K3Y.cjs.map +0 -1
- package/dist/chunk-R62CQQNI.cjs.map +0 -1
|
@@ -2,6 +2,15 @@ import { useCborByteString, useCborTextString, DEFAULT_LIMITS, INDEFINITE_SYMBOL
|
|
|
2
2
|
|
|
3
3
|
// src/parser/utils.ts
|
|
4
4
|
var hexToBytes = (hex) => {
|
|
5
|
+
if (hex.length === 0) {
|
|
6
|
+
return new Uint8Array(0);
|
|
7
|
+
}
|
|
8
|
+
if (hex.length % 2 !== 0) {
|
|
9
|
+
throw new Error("Hex string must have even length");
|
|
10
|
+
}
|
|
11
|
+
if (!/^[0-9a-fA-F]+$/.test(hex)) {
|
|
12
|
+
throw new Error(`Invalid hex character in: ${hex}`);
|
|
13
|
+
}
|
|
5
14
|
const bytes = hex.match(/.{1,2}/g);
|
|
6
15
|
if (!bytes) return new Uint8Array(0);
|
|
7
16
|
return new Uint8Array(bytes.map((byte) => parseInt(byte, 16)));
|
|
@@ -233,9 +242,8 @@ function hasDuplicates(items) {
|
|
|
233
242
|
|
|
234
243
|
// src/parser/composables/useCborInteger.ts
|
|
235
244
|
function useCborInteger() {
|
|
236
|
-
const
|
|
237
|
-
const
|
|
238
|
-
const initialByte = readByte(buffer, 0);
|
|
245
|
+
const parseIntegerFromBuffer = (buffer, offset, options) => {
|
|
246
|
+
const initialByte = readByte(buffer, offset);
|
|
239
247
|
const { majorType, additionalInfo } = extractCborHeader(initialByte);
|
|
240
248
|
let rawValue;
|
|
241
249
|
let bytesRead;
|
|
@@ -243,16 +251,16 @@ function useCborInteger() {
|
|
|
243
251
|
rawValue = additionalInfo;
|
|
244
252
|
bytesRead = 1;
|
|
245
253
|
} else if (additionalInfo === 24) {
|
|
246
|
-
rawValue = readByte(buffer, 1);
|
|
254
|
+
rawValue = readByte(buffer, offset + 1);
|
|
247
255
|
bytesRead = 2;
|
|
248
256
|
} else if (additionalInfo === 25) {
|
|
249
|
-
rawValue = readUint(buffer, 1, 2);
|
|
257
|
+
rawValue = readUint(buffer, offset + 1, 2);
|
|
250
258
|
bytesRead = 3;
|
|
251
259
|
} else if (additionalInfo === 26) {
|
|
252
|
-
rawValue = readUint(buffer, 1, 4);
|
|
260
|
+
rawValue = readUint(buffer, offset + 1, 4);
|
|
253
261
|
bytesRead = 5;
|
|
254
262
|
} else if (additionalInfo === 27) {
|
|
255
|
-
const bigValue = readBigUint(buffer, 1, 8);
|
|
263
|
+
const bigValue = readBigUint(buffer, offset + 1, 8);
|
|
256
264
|
if (bigValue <= BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
257
265
|
rawValue = Number(bigValue);
|
|
258
266
|
} else {
|
|
@@ -292,8 +300,13 @@ function useCborInteger() {
|
|
|
292
300
|
bytesRead
|
|
293
301
|
};
|
|
294
302
|
};
|
|
303
|
+
const parseInteger = (hexString, options) => {
|
|
304
|
+
const buffer = hexToBytes(hexString);
|
|
305
|
+
return parseIntegerFromBuffer(buffer, 0, options);
|
|
306
|
+
};
|
|
295
307
|
return {
|
|
296
|
-
parseInteger
|
|
308
|
+
parseInteger,
|
|
309
|
+
parseIntegerFromBuffer
|
|
297
310
|
};
|
|
298
311
|
}
|
|
299
312
|
|
|
@@ -702,29 +715,34 @@ function useCborFloat() {
|
|
|
702
715
|
return {
|
|
703
716
|
parse,
|
|
704
717
|
parseFloat,
|
|
705
|
-
parseSimple
|
|
718
|
+
parseSimple,
|
|
719
|
+
parseFromBuffer
|
|
706
720
|
};
|
|
707
721
|
}
|
|
708
722
|
|
|
709
723
|
// src/parser/composables/useCborTag.ts
|
|
710
724
|
function useCborTag() {
|
|
711
|
-
const {
|
|
725
|
+
const { parseIntegerFromBuffer } = useCborInteger();
|
|
712
726
|
const { parseByteString, parseTextString } = useCborString();
|
|
713
|
-
const {
|
|
727
|
+
const { parseFromBuffer: parseFloatOrSimpleFromBuffer } = useCborFloat();
|
|
728
|
+
let parseStartTime = 0;
|
|
714
729
|
const parseItem = (buffer, offset, options, tagDepth = 0, collectionDepth = 0) => {
|
|
730
|
+
if (parseStartTime > 0 && options?.limits?.maxParseTime) {
|
|
731
|
+
const elapsed = Date.now() - parseStartTime;
|
|
732
|
+
if (elapsed > options.limits.maxParseTime) {
|
|
733
|
+
throw new Error(`Parse timeout: exceeded ${options.limits.maxParseTime}ms limit`);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
715
736
|
if (offset >= buffer.length) {
|
|
716
737
|
throw new Error(`Unexpected end of buffer at offset ${offset}`);
|
|
717
738
|
}
|
|
718
739
|
const initialByte = readByte(buffer, offset);
|
|
719
|
-
const { majorType
|
|
740
|
+
const { majorType } = extractCborHeader(initialByte);
|
|
720
741
|
switch (majorType) {
|
|
721
742
|
case 0:
|
|
722
743
|
// Unsigned integer
|
|
723
|
-
case 1:
|
|
724
|
-
|
|
725
|
-
const result = parseInteger(intHex, options);
|
|
726
|
-
return { value: result.value, bytesRead: result.bytesRead };
|
|
727
|
-
}
|
|
744
|
+
case 1:
|
|
745
|
+
return parseIntegerFromBuffer(buffer, offset, options);
|
|
728
746
|
case 2:
|
|
729
747
|
return parseByteString(buffer, offset, options);
|
|
730
748
|
case 3:
|
|
@@ -735,16 +753,8 @@ function useCborTag() {
|
|
|
735
753
|
return parseMapInternal(buffer, offset, options, collectionDepth);
|
|
736
754
|
case 6:
|
|
737
755
|
return parseTagFromBuffer(buffer, offset, options, tagDepth);
|
|
738
|
-
case 7:
|
|
739
|
-
|
|
740
|
-
if (additionalInfo >= 25 && additionalInfo <= 27) {
|
|
741
|
-
const result = parseFloat(simpleHex, options);
|
|
742
|
-
return { value: result.value, bytesRead: result.bytesRead };
|
|
743
|
-
} else {
|
|
744
|
-
const result = parseSimple(simpleHex, options);
|
|
745
|
-
return { value: result.value, bytesRead: result.bytesRead };
|
|
746
|
-
}
|
|
747
|
-
}
|
|
756
|
+
case 7:
|
|
757
|
+
return parseFloatOrSimpleFromBuffer(buffer, offset, options);
|
|
748
758
|
default:
|
|
749
759
|
throw new Error(`Unknown major type: ${majorType}`);
|
|
750
760
|
}
|
|
@@ -1008,11 +1018,11 @@ function useCborTag() {
|
|
|
1008
1018
|
if (value.length !== 2) {
|
|
1009
1019
|
throw new Error(`Tag 4 (decimal fraction) array must have exactly 2 elements [exponent, mantissa], got ${value.length}`);
|
|
1010
1020
|
}
|
|
1011
|
-
if (typeof value[0] !== "number" && typeof value[0] !== "bigint") {
|
|
1012
|
-
throw new Error(`Tag 4 (decimal fraction) exponent must be an integer, got ${
|
|
1021
|
+
if (typeof value[0] !== "number" && typeof value[0] !== "bigint" || typeof value[0] === "number" && !Number.isInteger(value[0])) {
|
|
1022
|
+
throw new Error(`Tag 4 (decimal fraction) exponent must be an integer, got ${value[0]}`);
|
|
1013
1023
|
}
|
|
1014
|
-
if (typeof value[1] !== "number" && typeof value[1] !== "bigint") {
|
|
1015
|
-
throw new Error(`Tag 4 (decimal fraction) mantissa must be an integer, got ${
|
|
1024
|
+
if (typeof value[1] !== "number" && typeof value[1] !== "bigint" || typeof value[1] === "number" && !Number.isInteger(value[1])) {
|
|
1025
|
+
throw new Error(`Tag 4 (decimal fraction) mantissa must be an integer, got ${value[1]}`);
|
|
1016
1026
|
}
|
|
1017
1027
|
break;
|
|
1018
1028
|
case 5:
|
|
@@ -1023,11 +1033,11 @@ function useCborTag() {
|
|
|
1023
1033
|
if (value.length !== 2) {
|
|
1024
1034
|
throw new Error(`Tag 5 (bigfloat) array must have exactly 2 elements [exponent, mantissa], got ${value.length}`);
|
|
1025
1035
|
}
|
|
1026
|
-
if (typeof value[0] !== "number" && typeof value[0] !== "bigint") {
|
|
1027
|
-
throw new Error(`Tag 5 (bigfloat) exponent must be an integer, got ${
|
|
1036
|
+
if (typeof value[0] !== "number" && typeof value[0] !== "bigint" || typeof value[0] === "number" && !Number.isInteger(value[0])) {
|
|
1037
|
+
throw new Error(`Tag 5 (bigfloat) exponent must be an integer, got ${value[0]}`);
|
|
1028
1038
|
}
|
|
1029
|
-
if (typeof value[1] !== "number" && typeof value[1] !== "bigint") {
|
|
1030
|
-
throw new Error(`Tag 5 (bigfloat) mantissa must be an integer, got ${
|
|
1039
|
+
if (typeof value[1] !== "number" && typeof value[1] !== "bigint" || typeof value[1] === "number" && !Number.isInteger(value[1])) {
|
|
1040
|
+
throw new Error(`Tag 5 (bigfloat) mantissa must be an integer, got ${value[1]}`);
|
|
1031
1041
|
}
|
|
1032
1042
|
break;
|
|
1033
1043
|
case 32:
|
|
@@ -1231,12 +1241,25 @@ function useCborTag() {
|
|
|
1231
1241
|
const parseTag = (hexString, options) => {
|
|
1232
1242
|
const cleanHex = hexString.replace(/\s+/g, "");
|
|
1233
1243
|
const buffer = hexToBytes(cleanHex);
|
|
1234
|
-
|
|
1244
|
+
const isTopLevel = parseStartTime === 0;
|
|
1245
|
+
if (isTopLevel && options?.limits?.maxParseTime) {
|
|
1246
|
+
parseStartTime = Date.now();
|
|
1247
|
+
}
|
|
1248
|
+
try {
|
|
1249
|
+
return parseTagFromBuffer(buffer, 0, options);
|
|
1250
|
+
} finally {
|
|
1251
|
+
if (isTopLevel) {
|
|
1252
|
+
parseStartTime = 0;
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1235
1255
|
};
|
|
1236
1256
|
const parse = parseTag;
|
|
1237
1257
|
return {
|
|
1238
1258
|
parseTag,
|
|
1239
|
-
parse
|
|
1259
|
+
parse,
|
|
1260
|
+
parseTagFromBuffer,
|
|
1261
|
+
validateTagSemantics,
|
|
1262
|
+
decodePlutusConstructor
|
|
1240
1263
|
};
|
|
1241
1264
|
}
|
|
1242
1265
|
|
|
@@ -1295,17 +1318,18 @@ var logger = {
|
|
|
1295
1318
|
|
|
1296
1319
|
// src/parser/composables/useCborCollection.ts
|
|
1297
1320
|
function useCborCollection() {
|
|
1298
|
-
const {
|
|
1321
|
+
const { parseIntegerFromBuffer } = useCborInteger();
|
|
1299
1322
|
const { parseByteString, parseTextString } = useCborString();
|
|
1300
|
-
const {
|
|
1301
|
-
const {
|
|
1302
|
-
|
|
1303
|
-
if (key instanceof Uint8Array) {
|
|
1304
|
-
return bytesToHex(key);
|
|
1305
|
-
}
|
|
1306
|
-
return String(key);
|
|
1307
|
-
};
|
|
1323
|
+
const { parseFromBuffer: parseFloatOrSimpleFromBuffer } = useCborFloat();
|
|
1324
|
+
const { parseTagFromBuffer } = useCborTag();
|
|
1325
|
+
let parseStartTime = 0;
|
|
1308
1326
|
const parseItem = (buffer, offset, options, depth = 0) => {
|
|
1327
|
+
if (parseStartTime > 0 && options?.limits?.maxParseTime) {
|
|
1328
|
+
const elapsed = Date.now() - parseStartTime;
|
|
1329
|
+
if (elapsed > options.limits.maxParseTime) {
|
|
1330
|
+
throw new Error(`Parse timeout: exceeded ${options.limits.maxParseTime}ms limit`);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1309
1333
|
if (offset >= buffer.length) {
|
|
1310
1334
|
throw new Error(`Unexpected end of buffer at offset ${offset}`);
|
|
1311
1335
|
}
|
|
@@ -1314,11 +1338,8 @@ function useCborCollection() {
|
|
|
1314
1338
|
switch (majorType) {
|
|
1315
1339
|
case 0:
|
|
1316
1340
|
// Unsigned integer
|
|
1317
|
-
case 1:
|
|
1318
|
-
|
|
1319
|
-
const result = parseInteger(intHex, options);
|
|
1320
|
-
return { value: result.value, bytesRead: result.bytesRead };
|
|
1321
|
-
}
|
|
1341
|
+
case 1:
|
|
1342
|
+
return parseIntegerFromBuffer(buffer, offset, options);
|
|
1322
1343
|
case 2:
|
|
1323
1344
|
return parseByteString(buffer, offset, options);
|
|
1324
1345
|
case 3:
|
|
@@ -1327,16 +1348,10 @@ function useCborCollection() {
|
|
|
1327
1348
|
return parseArrayFromBuffer(buffer, offset, options, depth);
|
|
1328
1349
|
case 5:
|
|
1329
1350
|
return parseMapFromBuffer(buffer, offset, options, depth);
|
|
1330
|
-
case 6:
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
return
|
|
1334
|
-
}
|
|
1335
|
-
case 7: {
|
|
1336
|
-
const floatHex = Array.from(buffer.slice(offset)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1337
|
-
const result = parseFloatOrSimple(floatHex, options);
|
|
1338
|
-
return { value: result.value, bytesRead: result.bytesRead };
|
|
1339
|
-
}
|
|
1351
|
+
case 6:
|
|
1352
|
+
return parseTagFromBuffer(buffer, offset, options);
|
|
1353
|
+
case 7:
|
|
1354
|
+
return parseFloatOrSimpleFromBuffer(buffer, offset, options);
|
|
1340
1355
|
default:
|
|
1341
1356
|
throw new Error(`Unknown major type: ${majorType}`);
|
|
1342
1357
|
}
|
|
@@ -1478,7 +1493,7 @@ function useCborCollection() {
|
|
|
1478
1493
|
}
|
|
1479
1494
|
const valueResult = parseItem(buffer, currentOffset, options, depth + 1);
|
|
1480
1495
|
currentOffset += valueResult.bytesRead;
|
|
1481
|
-
const keyString =
|
|
1496
|
+
const keyString = serializeValueForComparison(keyResult.value);
|
|
1482
1497
|
if (seenKeys.has(keyString)) {
|
|
1483
1498
|
const mode = options?.dupMapKeyMode || "allow";
|
|
1484
1499
|
if (mode === "reject") {
|
|
@@ -1516,7 +1531,7 @@ function useCborCollection() {
|
|
|
1516
1531
|
}
|
|
1517
1532
|
const valueResult = parseItem(buffer, currentOffset, options, depth + 1);
|
|
1518
1533
|
currentOffset += valueResult.bytesRead;
|
|
1519
|
-
const keyString =
|
|
1534
|
+
const keyString = serializeValueForComparison(keyResult.value);
|
|
1520
1535
|
if (seenKeys.has(keyString)) {
|
|
1521
1536
|
const mode = options?.dupMapKeyMode || "allow";
|
|
1522
1537
|
if (mode === "reject") {
|
|
@@ -1556,12 +1571,26 @@ function useCborCollection() {
|
|
|
1556
1571
|
const parseArray = (hexString, options) => {
|
|
1557
1572
|
const cleanHex = hexString.replace(/\s+/g, "");
|
|
1558
1573
|
const buffer = hexToBytes(cleanHex);
|
|
1559
|
-
|
|
1574
|
+
if (options?.limits?.maxParseTime) {
|
|
1575
|
+
parseStartTime = Date.now();
|
|
1576
|
+
}
|
|
1577
|
+
try {
|
|
1578
|
+
return parseArrayFromBuffer(buffer, 0, options, 0);
|
|
1579
|
+
} finally {
|
|
1580
|
+
parseStartTime = 0;
|
|
1581
|
+
}
|
|
1560
1582
|
};
|
|
1561
1583
|
const parseMap = (hexString, options) => {
|
|
1562
1584
|
const cleanHex = hexString.replace(/\s+/g, "");
|
|
1563
1585
|
const buffer = hexToBytes(cleanHex);
|
|
1564
|
-
|
|
1586
|
+
if (options?.limits?.maxParseTime) {
|
|
1587
|
+
parseStartTime = Date.now();
|
|
1588
|
+
}
|
|
1589
|
+
try {
|
|
1590
|
+
return parseMapFromBuffer(buffer, 0, options, 0);
|
|
1591
|
+
} finally {
|
|
1592
|
+
parseStartTime = 0;
|
|
1593
|
+
}
|
|
1565
1594
|
};
|
|
1566
1595
|
return {
|
|
1567
1596
|
parseArray,
|
|
@@ -1605,13 +1634,23 @@ function useCborParser() {
|
|
|
1605
1634
|
throw new Error(`Parse timeout: exceeded ${ctx.options.limits.maxParseTime}ms limit (elapsed: ${elapsed}ms)`);
|
|
1606
1635
|
}
|
|
1607
1636
|
};
|
|
1608
|
-
const { parseInteger } = useCborInteger();
|
|
1609
|
-
const { parseString } = useCborString();
|
|
1637
|
+
const { parseInteger, parseIntegerFromBuffer: integerFromBuffer } = useCborInteger();
|
|
1638
|
+
const { parseString, parseByteString: byteStringFromBuffer, parseTextString: textStringFromBuffer } = useCborString();
|
|
1610
1639
|
const { parseArray, parseMap } = useCborCollection();
|
|
1611
|
-
const { parseTag } = useCborTag();
|
|
1612
|
-
const { parse: parseFloatOrSimple } = useCborFloat();
|
|
1613
|
-
const parse = (
|
|
1614
|
-
const
|
|
1640
|
+
const { parseTag, validateTagSemantics, decodePlutusConstructor } = useCborTag();
|
|
1641
|
+
const { parse: parseFloatOrSimple, parseFromBuffer: floatOrSimpleFromBuffer } = useCborFloat();
|
|
1642
|
+
const parse = (input, options) => {
|
|
1643
|
+
const mergedOptions = mergeOptions(options);
|
|
1644
|
+
if (input instanceof Uint8Array) {
|
|
1645
|
+
if (input.length === 0) {
|
|
1646
|
+
throw new Error("Empty input");
|
|
1647
|
+
}
|
|
1648
|
+
if (mergedOptions.limits?.maxInputSize && input.length > mergedOptions.limits.maxInputSize) {
|
|
1649
|
+
throw new Error(`Input size ${input.length} bytes exceeds limit of ${mergedOptions.limits.maxInputSize} bytes`);
|
|
1650
|
+
}
|
|
1651
|
+
return dispatchFromBuffer(input, 0, mergedOptions);
|
|
1652
|
+
}
|
|
1653
|
+
const cleanHex = input.replace(/\s+/g, "");
|
|
1615
1654
|
if (!cleanHex || cleanHex.length === 0) {
|
|
1616
1655
|
throw new Error("Empty hex string");
|
|
1617
1656
|
}
|
|
@@ -1621,7 +1660,6 @@ function useCborParser() {
|
|
|
1621
1660
|
if (!/^[0-9a-fA-F]+$/.test(cleanHex)) {
|
|
1622
1661
|
throw new Error(`Invalid hex character in: ${cleanHex}`);
|
|
1623
1662
|
}
|
|
1624
|
-
const mergedOptions = mergeOptions(options);
|
|
1625
1663
|
const inputSize = cleanHex.length / 2;
|
|
1626
1664
|
if (mergedOptions.limits?.maxInputSize && inputSize > mergedOptions.limits.maxInputSize) {
|
|
1627
1665
|
throw new Error(`Input size ${inputSize} bytes exceeds limit of ${mergedOptions.limits.maxInputSize} bytes`);
|
|
@@ -1650,26 +1688,40 @@ function useCborParser() {
|
|
|
1650
1688
|
throw new Error(`Unknown major type: ${majorType}`);
|
|
1651
1689
|
}
|
|
1652
1690
|
};
|
|
1653
|
-
const parseWithSourceMap = (
|
|
1654
|
-
const cleanHex = hexString.replace(/\s+/g, "");
|
|
1655
|
-
if (!cleanHex || cleanHex.length === 0) {
|
|
1656
|
-
throw new Error("Empty hex string");
|
|
1657
|
-
}
|
|
1658
|
-
if (cleanHex.length % 2 !== 0) {
|
|
1659
|
-
throw new Error("Hex string must have even length");
|
|
1660
|
-
}
|
|
1661
|
-
if (!/^[0-9a-fA-F]+$/.test(cleanHex)) {
|
|
1662
|
-
throw new Error(`Invalid hex character in: ${cleanHex}`);
|
|
1663
|
-
}
|
|
1691
|
+
const parseWithSourceMap = (input, options) => {
|
|
1664
1692
|
const mergedOptions = mergeOptions(options);
|
|
1665
|
-
|
|
1666
|
-
if (
|
|
1667
|
-
|
|
1693
|
+
let buffer;
|
|
1694
|
+
if (input instanceof Uint8Array) {
|
|
1695
|
+
if (input.length === 0) {
|
|
1696
|
+
throw new Error("Empty input");
|
|
1697
|
+
}
|
|
1698
|
+
if (mergedOptions.limits?.maxInputSize && input.length > mergedOptions.limits.maxInputSize) {
|
|
1699
|
+
throw new Error(`Input size ${input.length} bytes exceeds limit of ${mergedOptions.limits.maxInputSize} bytes`);
|
|
1700
|
+
}
|
|
1701
|
+
buffer = input;
|
|
1702
|
+
} else {
|
|
1703
|
+
const cleanHex = input.replace(/\s+/g, "");
|
|
1704
|
+
if (!cleanHex || cleanHex.length === 0) {
|
|
1705
|
+
throw new Error("Empty hex string");
|
|
1706
|
+
}
|
|
1707
|
+
if (cleanHex.length % 2 !== 0) {
|
|
1708
|
+
throw new Error("Hex string must have even length");
|
|
1709
|
+
}
|
|
1710
|
+
if (!/^[0-9a-fA-F]+$/.test(cleanHex)) {
|
|
1711
|
+
throw new Error(`Invalid hex character in: ${cleanHex}`);
|
|
1712
|
+
}
|
|
1713
|
+
const inputSize = cleanHex.length / 2;
|
|
1714
|
+
if (mergedOptions.limits?.maxInputSize && inputSize > mergedOptions.limits.maxInputSize) {
|
|
1715
|
+
throw new Error(`Input size ${inputSize} bytes exceeds limit of ${mergedOptions.limits.maxInputSize} bytes`);
|
|
1716
|
+
}
|
|
1717
|
+
buffer = hexToBytes(cleanHex);
|
|
1668
1718
|
}
|
|
1669
|
-
const buffer = hexToBytes(cleanHex);
|
|
1670
1719
|
const sourceMap = [];
|
|
1671
1720
|
const ctx = {
|
|
1672
1721
|
buffer,
|
|
1722
|
+
offset: 0,
|
|
1723
|
+
sourceMap,
|
|
1724
|
+
currentDepth: 0,
|
|
1673
1725
|
startTime: Date.now(),
|
|
1674
1726
|
bytesAllocated: 0,
|
|
1675
1727
|
options: mergedOptions
|
|
@@ -1812,19 +1864,57 @@ function useCborParser() {
|
|
|
1812
1864
|
}
|
|
1813
1865
|
return result;
|
|
1814
1866
|
};
|
|
1867
|
+
const dispatchFromBuffer = (buffer, offset, options) => {
|
|
1868
|
+
const initialByte = readByte(buffer, offset);
|
|
1869
|
+
const { majorType } = extractCborHeader(initialByte);
|
|
1870
|
+
switch (majorType) {
|
|
1871
|
+
case 0:
|
|
1872
|
+
// Unsigned integer
|
|
1873
|
+
case 1:
|
|
1874
|
+
return integerFromBuffer(buffer, offset, options);
|
|
1875
|
+
case 2:
|
|
1876
|
+
return byteStringFromBuffer(buffer, offset, options);
|
|
1877
|
+
case 3:
|
|
1878
|
+
return textStringFromBuffer(buffer, offset, options);
|
|
1879
|
+
case 4: {
|
|
1880
|
+
const hexString = Array.from(buffer.slice(offset)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1881
|
+
return parseArray(hexString, options);
|
|
1882
|
+
}
|
|
1883
|
+
case 5: {
|
|
1884
|
+
const hexString = Array.from(buffer.slice(offset)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1885
|
+
return parseMap(hexString, options);
|
|
1886
|
+
}
|
|
1887
|
+
case 6: {
|
|
1888
|
+
const hexString = Array.from(buffer.slice(offset)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1889
|
+
return parseTag(hexString, options);
|
|
1890
|
+
}
|
|
1891
|
+
case 7:
|
|
1892
|
+
return floatOrSimpleFromBuffer(buffer, offset, options);
|
|
1893
|
+
default:
|
|
1894
|
+
throw new Error(`Unknown major type: ${majorType}`);
|
|
1895
|
+
}
|
|
1896
|
+
};
|
|
1815
1897
|
const parseIntegerFromBuffer = (buffer, offset, options) => {
|
|
1816
|
-
|
|
1817
|
-
return parseInteger(hexString, options);
|
|
1898
|
+
return integerFromBuffer(buffer, offset, options);
|
|
1818
1899
|
};
|
|
1819
1900
|
const parseStringFromBuffer = (buffer, offset, options) => {
|
|
1820
|
-
const
|
|
1821
|
-
|
|
1901
|
+
const initialByte = readByte(buffer, offset);
|
|
1902
|
+
const { majorType } = extractCborHeader(initialByte);
|
|
1903
|
+
if (majorType === 2) {
|
|
1904
|
+
return byteStringFromBuffer(buffer, offset, options);
|
|
1905
|
+
}
|
|
1906
|
+
return textStringFromBuffer(buffer, offset, options);
|
|
1822
1907
|
};
|
|
1823
1908
|
const parseFloatFromBuffer = (buffer, offset, options) => {
|
|
1824
|
-
|
|
1825
|
-
return parseFloatOrSimple(hexString, options);
|
|
1909
|
+
return floatOrSimpleFromBuffer(buffer, offset, options);
|
|
1826
1910
|
};
|
|
1827
1911
|
const parseArrayWithMap = (ctx, offset, path, sourceMap) => {
|
|
1912
|
+
const previousDepth = ctx.currentDepth ?? 0;
|
|
1913
|
+
const maxDepth = ctx.options?.limits?.maxDepth;
|
|
1914
|
+
if (maxDepth !== void 0 && previousDepth >= maxDepth) {
|
|
1915
|
+
throw new Error(`Maximum nesting depth ${maxDepth} exceeded`);
|
|
1916
|
+
}
|
|
1917
|
+
ctx.currentDepth = previousDepth + 1;
|
|
1828
1918
|
const startOffset = offset;
|
|
1829
1919
|
const initialByte = readByte(ctx.buffer, offset);
|
|
1830
1920
|
const { additionalInfo } = extractCborHeader(initialByte);
|
|
@@ -1851,6 +1941,10 @@ function useCborParser() {
|
|
|
1851
1941
|
length = Number(bigLength);
|
|
1852
1942
|
currentOffset += 8;
|
|
1853
1943
|
} else if (additionalInfo === 31) {
|
|
1944
|
+
const isIndefiniteAllowed = ctx.options?.allowIndefinite ?? !(ctx.options?.validateCanonical || ctx.options?.strict);
|
|
1945
|
+
if (!isIndefiniteAllowed) {
|
|
1946
|
+
throw new Error("Indefinite-length encoding is not allowed (strict/canonical mode)");
|
|
1947
|
+
}
|
|
1854
1948
|
isIndefinite = true;
|
|
1855
1949
|
length = 0;
|
|
1856
1950
|
} else {
|
|
@@ -1867,49 +1961,70 @@ function useCborParser() {
|
|
|
1867
1961
|
isHeader: true,
|
|
1868
1962
|
headerEnd
|
|
1869
1963
|
});
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
currentOffset
|
|
1877
|
-
|
|
1964
|
+
try {
|
|
1965
|
+
const childPaths = [];
|
|
1966
|
+
if (isIndefinite) {
|
|
1967
|
+
let index = 0;
|
|
1968
|
+
let foundBreak = false;
|
|
1969
|
+
while (currentOffset < ctx.buffer.length) {
|
|
1970
|
+
const nextByte = readByte(ctx.buffer, currentOffset);
|
|
1971
|
+
if (nextByte === 255) {
|
|
1972
|
+
currentOffset++;
|
|
1973
|
+
foundBreak = true;
|
|
1974
|
+
break;
|
|
1975
|
+
}
|
|
1976
|
+
if (ctx.options?.limits?.maxArrayLength && index >= ctx.options.limits.maxArrayLength) {
|
|
1977
|
+
throw new Error(`Array length exceeds limit of ${ctx.options.limits.maxArrayLength}`);
|
|
1978
|
+
}
|
|
1979
|
+
const elementPath = `${path}[${index}]`;
|
|
1980
|
+
childPaths.push(elementPath);
|
|
1981
|
+
const elementResult = parseValueWithMap(ctx, currentOffset, elementPath, sourceMap);
|
|
1982
|
+
items.push(elementResult.value);
|
|
1983
|
+
currentOffset += elementResult.bytesRead;
|
|
1984
|
+
const elementEntry = sourceMap.find((e) => e.path === elementPath);
|
|
1985
|
+
if (elementEntry) {
|
|
1986
|
+
elementEntry.parent = path;
|
|
1987
|
+
}
|
|
1988
|
+
index++;
|
|
1878
1989
|
}
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
const elementResult = parseValueWithMap(ctx, currentOffset, elementPath, sourceMap);
|
|
1882
|
-
items.push(elementResult.value);
|
|
1883
|
-
currentOffset += elementResult.bytesRead;
|
|
1884
|
-
const elementEntry = sourceMap.find((e) => e.path === elementPath);
|
|
1885
|
-
if (elementEntry) {
|
|
1886
|
-
elementEntry.parent = path;
|
|
1990
|
+
if (!foundBreak) {
|
|
1991
|
+
throw new Error("Indefinite-length array missing break code (0xFF)");
|
|
1887
1992
|
}
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
elementEntry
|
|
1993
|
+
} else {
|
|
1994
|
+
if (ctx.options?.limits?.maxArrayLength && length > ctx.options.limits.maxArrayLength) {
|
|
1995
|
+
throw new Error(`Array length ${length} exceeds limit of ${ctx.options.limits.maxArrayLength}`);
|
|
1996
|
+
}
|
|
1997
|
+
for (let i = 0; i < length; i++) {
|
|
1998
|
+
const elementPath = `${path}[${i}]`;
|
|
1999
|
+
childPaths.push(elementPath);
|
|
2000
|
+
const elementResult = parseValueWithMap(ctx, currentOffset, elementPath, sourceMap);
|
|
2001
|
+
items.push(elementResult.value);
|
|
2002
|
+
currentOffset += elementResult.bytesRead;
|
|
2003
|
+
const elementEntry = sourceMap.find((e) => e.path === elementPath);
|
|
2004
|
+
if (elementEntry) {
|
|
2005
|
+
elementEntry.parent = path;
|
|
2006
|
+
}
|
|
1900
2007
|
}
|
|
1901
2008
|
}
|
|
2009
|
+
const bytesRead = currentOffset - offset;
|
|
2010
|
+
if (childPaths.length > 0 && sourceMap[arrayEntryIndex]) {
|
|
2011
|
+
sourceMap[arrayEntryIndex].children = childPaths;
|
|
2012
|
+
}
|
|
2013
|
+
return {
|
|
2014
|
+
value: items,
|
|
2015
|
+
bytesRead
|
|
2016
|
+
};
|
|
2017
|
+
} finally {
|
|
2018
|
+
ctx.currentDepth = previousDepth;
|
|
1902
2019
|
}
|
|
1903
|
-
const bytesRead = currentOffset - offset;
|
|
1904
|
-
if (childPaths.length > 0 && sourceMap[arrayEntryIndex]) {
|
|
1905
|
-
sourceMap[arrayEntryIndex].children = childPaths;
|
|
1906
|
-
}
|
|
1907
|
-
return {
|
|
1908
|
-
value: items,
|
|
1909
|
-
bytesRead
|
|
1910
|
-
};
|
|
1911
2020
|
};
|
|
1912
2021
|
const parseMapWithMap = (ctx, offset, path, sourceMap) => {
|
|
2022
|
+
const previousDepth = ctx.currentDepth ?? 0;
|
|
2023
|
+
const maxDepth = ctx.options?.limits?.maxDepth;
|
|
2024
|
+
if (maxDepth !== void 0 && previousDepth >= maxDepth) {
|
|
2025
|
+
throw new Error(`Maximum nesting depth ${maxDepth} exceeded`);
|
|
2026
|
+
}
|
|
2027
|
+
ctx.currentDepth = previousDepth + 1;
|
|
1913
2028
|
const startOffset = offset;
|
|
1914
2029
|
const initialByte = readByte(ctx.buffer, offset);
|
|
1915
2030
|
const { additionalInfo } = extractCborHeader(initialByte);
|
|
@@ -1936,6 +2051,10 @@ function useCborParser() {
|
|
|
1936
2051
|
length = Number(bigLength);
|
|
1937
2052
|
currentOffset += 8;
|
|
1938
2053
|
} else if (additionalInfo === 31) {
|
|
2054
|
+
const isIndefiniteAllowed = ctx.options?.allowIndefinite ?? !(ctx.options?.validateCanonical || ctx.options?.strict);
|
|
2055
|
+
if (!isIndefiniteAllowed) {
|
|
2056
|
+
throw new Error("Indefinite-length encoding is not allowed (strict/canonical mode)");
|
|
2057
|
+
}
|
|
1939
2058
|
isIndefinite = true;
|
|
1940
2059
|
length = 0;
|
|
1941
2060
|
} else {
|
|
@@ -1952,72 +2071,91 @@ function useCborParser() {
|
|
|
1952
2071
|
isHeader: true,
|
|
1953
2072
|
headerEnd
|
|
1954
2073
|
});
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
2074
|
+
try {
|
|
2075
|
+
const childPaths = [];
|
|
2076
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
2077
|
+
if (isIndefinite) {
|
|
2078
|
+
let count = 0;
|
|
2079
|
+
let foundBreak = false;
|
|
2080
|
+
while (currentOffset < ctx.buffer.length) {
|
|
2081
|
+
const nextByte = readByte(ctx.buffer, currentOffset);
|
|
2082
|
+
if (nextByte === 255) {
|
|
2083
|
+
currentOffset++;
|
|
2084
|
+
foundBreak = true;
|
|
2085
|
+
break;
|
|
2086
|
+
}
|
|
2087
|
+
if (ctx.options?.limits?.maxMapSize && count >= ctx.options.limits.maxMapSize) {
|
|
2088
|
+
throw new Error(`Map size exceeds limit of ${ctx.options.limits.maxMapSize}`);
|
|
2089
|
+
}
|
|
2090
|
+
const keyPath = `${path}${path ? "." : ""}#key`;
|
|
2091
|
+
const keyResult = parseValueWithMap(ctx, currentOffset, keyPath, sourceMap);
|
|
2092
|
+
currentOffset += keyResult.bytesRead;
|
|
2093
|
+
const keyForDupCheck = serializeValueForComparison(keyResult.value);
|
|
2094
|
+
const keyString = keyResult.value instanceof Uint8Array ? Array.from(keyResult.value).map((b) => b.toString(16).padStart(2, "0")).join("") : String(keyResult.value);
|
|
2095
|
+
if (seenKeys.has(keyForDupCheck)) {
|
|
2096
|
+
const mode = ctx.options?.dupMapKeyMode || "allow";
|
|
2097
|
+
if (mode === "reject") {
|
|
2098
|
+
throw new Error(`Duplicate map key detected: ${keyString} at offset ${currentOffset}`);
|
|
2099
|
+
} else if (mode === "warn") {
|
|
2100
|
+
logger.warn(`Duplicate map key detected: ${keyString} at offset ${currentOffset}`);
|
|
2101
|
+
}
|
|
1974
2102
|
}
|
|
2103
|
+
seenKeys.add(keyForDupCheck);
|
|
2104
|
+
const valuePath = path ? `${path}.${keyString}` : `.${keyString}`;
|
|
2105
|
+
childPaths.push(valuePath);
|
|
2106
|
+
const valueResult = parseValueWithMap(ctx, currentOffset, valuePath, sourceMap);
|
|
2107
|
+
map.set(keyResult.value, valueResult.value);
|
|
2108
|
+
currentOffset += valueResult.bytesRead;
|
|
2109
|
+
const valueEntry = sourceMap.find((e) => e.path === valuePath);
|
|
2110
|
+
if (valueEntry) {
|
|
2111
|
+
valueEntry.parent = path;
|
|
2112
|
+
}
|
|
2113
|
+
count++;
|
|
1975
2114
|
}
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
childPaths.push(valuePath);
|
|
1979
|
-
const valueResult = parseValueWithMap(ctx, currentOffset, valuePath, sourceMap);
|
|
1980
|
-
map.set(keyResult.value, valueResult.value);
|
|
1981
|
-
currentOffset += valueResult.bytesRead;
|
|
1982
|
-
const valueEntry = sourceMap.find((e) => e.path === valuePath);
|
|
1983
|
-
if (valueEntry) {
|
|
1984
|
-
valueEntry.parent = path;
|
|
2115
|
+
if (!foundBreak) {
|
|
2116
|
+
throw new Error("Indefinite-length map missing break code (0xFF)");
|
|
1985
2117
|
}
|
|
1986
|
-
}
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
const
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
2118
|
+
} else {
|
|
2119
|
+
if (ctx.options?.limits?.maxMapSize && length > ctx.options.limits.maxMapSize) {
|
|
2120
|
+
throw new Error(`Map size ${length} exceeds limit of ${ctx.options.limits.maxMapSize}`);
|
|
2121
|
+
}
|
|
2122
|
+
for (let i = 0; i < length; i++) {
|
|
2123
|
+
const keyPath = `${path}${path ? "." : ""}#key${i}`;
|
|
2124
|
+
const keyResult = parseValueWithMap(ctx, currentOffset, keyPath, sourceMap);
|
|
2125
|
+
currentOffset += keyResult.bytesRead;
|
|
2126
|
+
const keyForDupCheck = serializeValueForComparison(keyResult.value);
|
|
2127
|
+
const keyString = keyResult.value instanceof Uint8Array ? Array.from(keyResult.value).map((b) => b.toString(16).padStart(2, "0")).join("") : String(keyResult.value);
|
|
2128
|
+
if (seenKeys.has(keyForDupCheck)) {
|
|
2129
|
+
const mode = ctx.options?.dupMapKeyMode || "allow";
|
|
2130
|
+
if (mode === "reject") {
|
|
2131
|
+
throw new Error(`Duplicate map key detected: ${keyString} at offset ${currentOffset}`);
|
|
2132
|
+
} else if (mode === "warn") {
|
|
2133
|
+
logger.warn(`Duplicate map key detected: ${keyString} at offset ${currentOffset}`);
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
seenKeys.add(keyForDupCheck);
|
|
2137
|
+
const valuePath = path ? `${path}.${keyString}` : `.${keyString}`;
|
|
2138
|
+
childPaths.push(valuePath);
|
|
2139
|
+
const valueResult = parseValueWithMap(ctx, currentOffset, valuePath, sourceMap);
|
|
2140
|
+
map.set(keyResult.value, valueResult.value);
|
|
2141
|
+
currentOffset += valueResult.bytesRead;
|
|
2142
|
+
const valueEntry = sourceMap.find((e) => e.path === valuePath);
|
|
2143
|
+
if (valueEntry) {
|
|
2144
|
+
valueEntry.parent = path;
|
|
1999
2145
|
}
|
|
2000
|
-
}
|
|
2001
|
-
seenKeys.add(keyString);
|
|
2002
|
-
const valuePath = path ? `${path}.${keyString}` : `.${keyString}`;
|
|
2003
|
-
childPaths.push(valuePath);
|
|
2004
|
-
const valueResult = parseValueWithMap(ctx, currentOffset, valuePath, sourceMap);
|
|
2005
|
-
map.set(keyResult.value, valueResult.value);
|
|
2006
|
-
currentOffset += valueResult.bytesRead;
|
|
2007
|
-
const valueEntry = sourceMap.find((e) => e.path === valuePath);
|
|
2008
|
-
if (valueEntry) {
|
|
2009
|
-
valueEntry.parent = path;
|
|
2010
2146
|
}
|
|
2011
2147
|
}
|
|
2148
|
+
const bytesRead = currentOffset - offset;
|
|
2149
|
+
if (sourceMap[mapEntryIndex]) {
|
|
2150
|
+
sourceMap[mapEntryIndex].children = childPaths;
|
|
2151
|
+
}
|
|
2152
|
+
return {
|
|
2153
|
+
value: map,
|
|
2154
|
+
bytesRead
|
|
2155
|
+
};
|
|
2156
|
+
} finally {
|
|
2157
|
+
ctx.currentDepth = previousDepth;
|
|
2012
2158
|
}
|
|
2013
|
-
const bytesRead = currentOffset - offset;
|
|
2014
|
-
if (sourceMap[mapEntryIndex]) {
|
|
2015
|
-
sourceMap[mapEntryIndex].children = childPaths;
|
|
2016
|
-
}
|
|
2017
|
-
return {
|
|
2018
|
-
value: map,
|
|
2019
|
-
bytesRead
|
|
2020
|
-
};
|
|
2021
2159
|
};
|
|
2022
2160
|
const parseTagNumberHelper = (buffer, offset, ai) => {
|
|
2023
2161
|
if (ai < 24) {
|
|
@@ -2076,10 +2214,29 @@ function useCborParser() {
|
|
|
2076
2214
|
if (valueEntry) {
|
|
2077
2215
|
valueEntry.parent = path;
|
|
2078
2216
|
}
|
|
2079
|
-
|
|
2080
|
-
|
|
2217
|
+
let finalValue = valueResult.value;
|
|
2218
|
+
if ((tagNumber === 2 || tagNumber === 3) && finalValue instanceof Uint8Array) {
|
|
2219
|
+
const maxBignumBytes = ctx.options?.limits?.maxBignumBytes ?? DEFAULT_LIMITS.maxBignumBytes;
|
|
2220
|
+
if (finalValue.length > maxBignumBytes) {
|
|
2221
|
+
throw new Error(
|
|
2222
|
+
`Bignum (tag ${tagNumber}) size ${finalValue.length} bytes exceeds limit of ${maxBignumBytes} bytes`
|
|
2223
|
+
);
|
|
2224
|
+
}
|
|
2225
|
+
let bigintValue = 0n;
|
|
2226
|
+
for (let i = 0; i < finalValue.length; i++) {
|
|
2227
|
+
bigintValue = bigintValue << 8n | BigInt(finalValue[i]);
|
|
2228
|
+
}
|
|
2229
|
+
finalValue = tagNumber === 2 ? bigintValue : -1n - bigintValue;
|
|
2230
|
+
}
|
|
2231
|
+
validateTagSemantics(tagNumber, finalValue, ctx.options);
|
|
2232
|
+
const plutusConstr = decodePlutusConstructor(tagNumber, finalValue);
|
|
2233
|
+
const taggedValue = {
|
|
2234
|
+
tag: tagNumber,
|
|
2235
|
+
value: finalValue,
|
|
2236
|
+
...plutusConstr && { plutus: plutusConstr }
|
|
2237
|
+
};
|
|
2081
2238
|
return {
|
|
2082
|
-
value:
|
|
2239
|
+
value: taggedValue,
|
|
2083
2240
|
bytesRead: currentOffset - startOffset
|
|
2084
2241
|
};
|
|
2085
2242
|
};
|
|
@@ -2094,28 +2251,42 @@ function useCborParser() {
|
|
|
2094
2251
|
if (ai < 20) return `Simple Value ${ai}`;
|
|
2095
2252
|
return "Simple Value";
|
|
2096
2253
|
};
|
|
2097
|
-
const parseSequence = (
|
|
2098
|
-
const cleanHex = hexString.replace(/\s+/g, "");
|
|
2099
|
-
if (!cleanHex || cleanHex.length === 0) {
|
|
2100
|
-
return [];
|
|
2101
|
-
}
|
|
2102
|
-
if (cleanHex.length % 2 !== 0) {
|
|
2103
|
-
throw new Error("Hex string must have even length");
|
|
2104
|
-
}
|
|
2105
|
-
if (!/^[0-9a-fA-F]+$/.test(cleanHex)) {
|
|
2106
|
-
throw new Error(`Invalid hex character in: ${cleanHex}`);
|
|
2107
|
-
}
|
|
2254
|
+
const parseSequence = (input, options) => {
|
|
2108
2255
|
const mergedOptions = mergeOptions(options);
|
|
2109
|
-
|
|
2256
|
+
let buffer;
|
|
2257
|
+
if (input instanceof Uint8Array) {
|
|
2258
|
+
if (input.length === 0) {
|
|
2259
|
+
return [];
|
|
2260
|
+
}
|
|
2261
|
+
buffer = input;
|
|
2262
|
+
} else {
|
|
2263
|
+
const cleanHex = input.replace(/\s+/g, "");
|
|
2264
|
+
if (!cleanHex || cleanHex.length === 0) {
|
|
2265
|
+
return [];
|
|
2266
|
+
}
|
|
2267
|
+
if (cleanHex.length % 2 !== 0) {
|
|
2268
|
+
throw new Error("Hex string must have even length");
|
|
2269
|
+
}
|
|
2270
|
+
if (!/^[0-9a-fA-F]+$/.test(cleanHex)) {
|
|
2271
|
+
throw new Error(`Invalid hex character in: ${cleanHex}`);
|
|
2272
|
+
}
|
|
2273
|
+
buffer = hexToBytes(cleanHex);
|
|
2274
|
+
}
|
|
2110
2275
|
const results = [];
|
|
2111
2276
|
let offset = 0;
|
|
2277
|
+
const sequenceStartTime = mergedOptions.limits?.maxParseTime ? Date.now() : 0;
|
|
2112
2278
|
while (offset < buffer.length) {
|
|
2279
|
+
if (sequenceStartTime > 0 && mergedOptions.limits?.maxParseTime) {
|
|
2280
|
+
const elapsed = Date.now() - sequenceStartTime;
|
|
2281
|
+
if (elapsed > mergedOptions.limits.maxParseTime) {
|
|
2282
|
+
throw new Error(`Parse timeout: exceeded ${mergedOptions.limits.maxParseTime}ms limit`);
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2113
2285
|
const byte = readByte(buffer, offset);
|
|
2114
2286
|
if (byte === 255) {
|
|
2115
2287
|
throw new Error(`Unexpected break code (0xff) at offset ${offset} - not inside indefinite-length item`);
|
|
2116
2288
|
}
|
|
2117
|
-
const
|
|
2118
|
-
const result = parse(remainingHex, mergedOptions);
|
|
2289
|
+
const result = dispatchFromBuffer(buffer, offset, mergedOptions);
|
|
2119
2290
|
results.push(result.value);
|
|
2120
2291
|
offset += result.bytesRead;
|
|
2121
2292
|
}
|
|
@@ -2164,5 +2335,5 @@ function useCborParser() {
|
|
|
2164
2335
|
}
|
|
2165
2336
|
|
|
2166
2337
|
export { bytesToHex, extractCborHeader, hexToBytes, readBigUint, readByte, readUint, useCborCollection, useCborFloat, useCborInteger, useCborParser, useCborString, useCborTag, validateUtf8Strict };
|
|
2167
|
-
//# sourceMappingURL=chunk-
|
|
2168
|
-
//# sourceMappingURL=chunk-
|
|
2338
|
+
//# sourceMappingURL=chunk-5IWW5H47.js.map
|
|
2339
|
+
//# sourceMappingURL=chunk-5IWW5H47.js.map
|