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