@marcuspuchalla/nachos 0.1.4 → 0.2.0
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 +52 -0
- package/dist/{chunk-RVG2BY32.cjs → chunk-3Z45RBZP.cjs} +96 -42
- package/dist/chunk-3Z45RBZP.cjs.map +1 -0
- package/dist/{chunk-UMAX5MX5.js → chunk-EDXZTSIA.js} +33 -5
- package/dist/chunk-EDXZTSIA.js.map +1 -0
- package/dist/{chunk-S4RXO6IB.cjs → chunk-HMUA5KLG.cjs} +48 -20
- package/dist/chunk-HMUA5KLG.cjs.map +1 -0
- package/dist/{chunk-ZDZ2B5PE.js → chunk-JESIF5IF.js} +7 -3
- package/dist/chunk-JESIF5IF.js.map +1 -0
- package/dist/{chunk-5IWW5H47.js → chunk-LWNWC2O7.js} +68 -14
- package/dist/chunk-LWNWC2O7.js.map +1 -0
- package/dist/{chunk-PD72MVTX.cjs → chunk-P6A2OOIY.cjs} +7 -3
- package/dist/chunk-P6A2OOIY.cjs.map +1 -0
- package/dist/encoder/index.cjs +14 -14
- package/dist/encoder/index.d.cts +5 -4
- package/dist/encoder/index.d.ts +5 -4
- package/dist/encoder/index.js +2 -2
- package/dist/index.cjs +46 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -5
- package/dist/index.d.ts +15 -5
- package/dist/index.js +25 -5
- 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 +21 -21
- package/dist/parser/index.d.cts +2 -2
- package/dist/parser/index.d.ts +2 -2
- package/dist/parser/index.js +2 -2
- package/dist/{types-DvNlfbKB.d.cts → types-eG2qalpr.d.cts} +27 -1
- package/dist/{types-DvNlfbKB.d.ts → types-eG2qalpr.d.ts} +27 -1
- package/dist/{useCborSimpleEncoder-BoKEmjP9.d.ts → useCborSimpleEncoder-CamvS-_N.d.ts} +7 -1
- package/dist/{useCborSimpleEncoder-C_OHxoB8.d.cts → useCborSimpleEncoder-DXgPx62d.d.cts} +7 -1
- package/dist/{useCborTag-QpZR-Er2.d.cts → useCborTag-D4d7xG3-.d.cts} +1 -1
- package/dist/{useCborTag-BD6Sqp7p.d.ts → useCborTag-TYst1KR6.d.ts} +1 -1
- package/package.json +1 -1
- package/src/__tests__/audit-fixes.test.ts +141 -0
- package/src/encoder/composables/useCborCollectionEncoder.ts +3 -2
- package/src/encoder/composables/useCborEncoder.ts +19 -0
- package/src/encoder/composables/useCborSimpleEncoder.ts +6 -2
- package/src/encoder/types.ts +9 -2
- package/src/encoder/utils.ts +33 -1
- package/src/index.ts +10 -0
- package/src/parser/__tests__/utils-errors.test.ts +11 -3
- package/src/parser/composables/useCborCollection.ts +7 -4
- package/src/parser/composables/useCborDiagnostic.ts +28 -0
- package/src/parser/composables/useCborParser.ts +63 -13
- package/src/parser/composables/useCborTag.ts +8 -1
- package/src/parser/types.ts +32 -1
- package/src/parser/utils.ts +41 -0
- package/dist/chunk-5IWW5H47.js.map +0 -1
- package/dist/chunk-PD72MVTX.cjs.map +0 -1
- package/dist/chunk-RVG2BY32.cjs.map +0 -1
- package/dist/chunk-S4RXO6IB.cjs.map +0 -1
- package/dist/chunk-UMAX5MX5.js.map +0 -1
- package/dist/chunk-ZDZ2B5PE.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,58 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.2.0] - 2026-06-14 - RFC 8949 audit remediation
|
|
9
|
+
|
|
10
|
+
Resolves the findings of the June 2026 RFC 8949 conformance & security audit.
|
|
11
|
+
All fixes verified empirically against the build and locked in by
|
|
12
|
+
`src/__tests__/audit-fixes.test.ts`.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
#### Security
|
|
17
|
+
- **(H1) Source-map parse path stack overflow** - `decodeWithSourceMap()` now
|
|
18
|
+
enforces `maxTagDepth` (RUSTSEC-2019-0025). Deeply nested tags previously
|
|
19
|
+
overflowed the call stack with an uncatchable `RangeError`; they now raise a
|
|
20
|
+
clean `Error`, matching `decode()`.
|
|
21
|
+
- **(M2) Encoder depth bypass via tags** - `maxDepth` is now tracked across the
|
|
22
|
+
tagged-value boundary, so deeply nested `{tag,value}` chains can no longer
|
|
23
|
+
bypass the limit and overflow the stack.
|
|
24
|
+
- **(L3) `readUint` precision** - refuses values above `MAX_SAFE_INTEGER`
|
|
25
|
+
instead of silently losing precision; callers must use `readBigUint`.
|
|
26
|
+
|
|
27
|
+
#### Correctness / Conformance
|
|
28
|
+
- **(H2) Map key ordering is now explicit** - canonical mode defaults to
|
|
29
|
+
**length-first** ordering (Cardano CIP-21 / RFC 7049 §3.9) and accepts a new
|
|
30
|
+
`mapKeyOrder: 'length-first' | 'bytewise'` option. `'bytewise'` selects
|
|
31
|
+
RFC 8949 §4.2.1 core deterministic ordering. Applies to both encoding and
|
|
32
|
+
`validateCanonical` decoding.
|
|
33
|
+
- **(M1) Trailing-data well-formedness** - new `allowTrailingData` option
|
|
34
|
+
(default `true`; auto-`false` in `strict` mode) makes `decode()` reject
|
|
35
|
+
bytes left over after the top-level item. Use `parseSequence` for multiple items.
|
|
36
|
+
- **(M4) Shortest-form tag numbers** - `validateCanonical` now rejects
|
|
37
|
+
non-shortest tag number encodings (e.g. `d80100` instead of `c100`).
|
|
38
|
+
- **(M5) Float16 subnormal encoding** - `canBeFloat16` lower bound corrected
|
|
39
|
+
from 2⁻¹⁴ (min normal) to 2⁻²⁴ (min subnormal). The encoder no longer emits
|
|
40
|
+
float32 for representable subnormals, so its output again passes its own
|
|
41
|
+
canonical validator.
|
|
42
|
+
|
|
43
|
+
#### Behavior
|
|
44
|
+
- **(M3) Duplicate map keys** - default `dupMapKeyMode` changed from `'allow'`
|
|
45
|
+
to `'warn'` so duplicates are never silently collapsed in the `Map` view.
|
|
46
|
+
Byte-perfect round-trips are still preserved via `ALL_ENTRIES_SYMBOL`.
|
|
47
|
+
|
|
48
|
+
### Performance
|
|
49
|
+
- **(L1) Source-map sequences** - `parseSequenceWithSourceMap` uses a zero-copy
|
|
50
|
+
`subarray` view per item instead of re-hex-encoding the buffer tail (O(N²) → O(N)).
|
|
51
|
+
|
|
52
|
+
### Added
|
|
53
|
+
- `MapKeyOrder` type, `mapKeyOrder` option (parser + encoder), `allowTrailingData`
|
|
54
|
+
option, and `compareBytesLexicographic` / `compareMapKeys` utilities.
|
|
55
|
+
- Diagnostic notation (L5) now renders `CborByteString`/`CborTextString` wrappers,
|
|
56
|
+
unassigned simple values (`simple(N)`), and auto-detects indefinite-length
|
|
57
|
+
arrays/maps/strings.
|
|
58
|
+
- 24 new audit-regression tests.
|
|
59
|
+
|
|
8
60
|
## [0.1.4] - 2026-02-22
|
|
9
61
|
|
|
10
62
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkP6A2OOIY_cjs = require('./chunk-P6A2OOIY.cjs');
|
|
4
4
|
|
|
5
5
|
// src/parser/utils.ts
|
|
6
6
|
var hexToBytes = (hex) => {
|
|
@@ -41,6 +41,9 @@ var readUint = (buffer, offset, length) => {
|
|
|
41
41
|
for (let i = 0; i < length; i++) {
|
|
42
42
|
result = result * 256 + readByte(buffer, offset + i);
|
|
43
43
|
}
|
|
44
|
+
if (result > Number.MAX_SAFE_INTEGER) {
|
|
45
|
+
throw new Error(`Value at offset ${offset} (${length} bytes) exceeds MAX_SAFE_INTEGER; use readBigUint`);
|
|
46
|
+
}
|
|
44
47
|
return result;
|
|
45
48
|
};
|
|
46
49
|
var readBigUint = (buffer, offset, length) => {
|
|
@@ -207,6 +210,23 @@ function compareBytes(a, b) {
|
|
|
207
210
|
}
|
|
208
211
|
return 0;
|
|
209
212
|
}
|
|
213
|
+
function compareBytesLexicographic(a, b) {
|
|
214
|
+
if (!a || !b) {
|
|
215
|
+
throw new Error("compareBytesLexicographic: arguments cannot be null or undefined");
|
|
216
|
+
}
|
|
217
|
+
const min = Math.min(a.length, b.length);
|
|
218
|
+
for (let i = 0; i < min; i++) {
|
|
219
|
+
const byteA = a[i];
|
|
220
|
+
const byteB = b[i];
|
|
221
|
+
if (byteA !== byteB) {
|
|
222
|
+
return byteA - byteB;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return a.length - b.length;
|
|
226
|
+
}
|
|
227
|
+
function compareMapKeys(a, b, order = "length-first") {
|
|
228
|
+
return order === "bytewise" ? compareBytesLexicographic(a, b) : compareBytes(a, b);
|
|
229
|
+
}
|
|
210
230
|
function serializeValueForComparison(value) {
|
|
211
231
|
if (value === null) return "null";
|
|
212
232
|
if (value === void 0) return "undefined";
|
|
@@ -314,8 +334,8 @@ function useCborInteger() {
|
|
|
314
334
|
|
|
315
335
|
// src/parser/composables/useCborString.ts
|
|
316
336
|
function useCborString() {
|
|
317
|
-
const { create: createByteString } =
|
|
318
|
-
const { create: createTextString } =
|
|
337
|
+
const { create: createByteString } = chunkP6A2OOIY_cjs.useCborByteString();
|
|
338
|
+
const { create: createTextString } = chunkP6A2OOIY_cjs.useCborTextString();
|
|
319
339
|
const parseLength = (buffer, offset, ai, options) => {
|
|
320
340
|
if (ai < 24) {
|
|
321
341
|
return { length: ai, bytesConsumed: 0 };
|
|
@@ -771,7 +791,7 @@ function useCborTag() {
|
|
|
771
791
|
if (additionalInfo === 31 && !isIndefiniteAllowed) {
|
|
772
792
|
throw new Error("Indefinite-length encoding is not allowed (strict/canonical mode)");
|
|
773
793
|
}
|
|
774
|
-
const maxDepth = options?.limits?.maxDepth ??
|
|
794
|
+
const maxDepth = options?.limits?.maxDepth ?? chunkP6A2OOIY_cjs.DEFAULT_LIMITS.maxDepth;
|
|
775
795
|
if (depth >= maxDepth) {
|
|
776
796
|
throw new Error(`Maximum nesting depth ${maxDepth} exceeded`);
|
|
777
797
|
}
|
|
@@ -828,7 +848,7 @@ function useCborTag() {
|
|
|
828
848
|
if (!foundBreak) {
|
|
829
849
|
throw new Error("Indefinite-length array missing break code (0xFF)");
|
|
830
850
|
}
|
|
831
|
-
items[
|
|
851
|
+
items[chunkP6A2OOIY_cjs.INDEFINITE_SYMBOL] = true;
|
|
832
852
|
} else {
|
|
833
853
|
for (let i = 0; i < length; i++) {
|
|
834
854
|
if (currentOffset >= buffer.length) {
|
|
@@ -854,7 +874,7 @@ function useCborTag() {
|
|
|
854
874
|
if (additionalInfo === 31 && !isIndefiniteAllowed) {
|
|
855
875
|
throw new Error("Indefinite-length encoding is not allowed (strict/canonical mode)");
|
|
856
876
|
}
|
|
857
|
-
const maxDepth = options?.limits?.maxDepth ??
|
|
877
|
+
const maxDepth = options?.limits?.maxDepth ?? chunkP6A2OOIY_cjs.DEFAULT_LIMITS.maxDepth;
|
|
858
878
|
if (depth >= maxDepth) {
|
|
859
879
|
throw new Error(`Maximum nesting depth ${maxDepth} exceeded`);
|
|
860
880
|
}
|
|
@@ -913,7 +933,7 @@ function useCborTag() {
|
|
|
913
933
|
if (!foundBreak) {
|
|
914
934
|
throw new Error("Indefinite-length map missing break code (0xFF)");
|
|
915
935
|
}
|
|
916
|
-
map[
|
|
936
|
+
map[chunkP6A2OOIY_cjs.INDEFINITE_SYMBOL] = true;
|
|
917
937
|
} else {
|
|
918
938
|
for (let i = 0; i < length; i++) {
|
|
919
939
|
if (currentOffset >= buffer.length) {
|
|
@@ -1199,11 +1219,14 @@ function useCborTag() {
|
|
|
1199
1219
|
if (majorType !== 6) {
|
|
1200
1220
|
throw new Error(`Expected major type 6 (tag), got ${majorType}`);
|
|
1201
1221
|
}
|
|
1202
|
-
const maxTagDepth = options?.limits?.maxTagDepth ??
|
|
1222
|
+
const maxTagDepth = options?.limits?.maxTagDepth ?? chunkP6A2OOIY_cjs.DEFAULT_LIMITS.maxTagDepth;
|
|
1203
1223
|
if (tagDepth >= maxTagDepth) {
|
|
1204
1224
|
throw new Error(`Tag nesting depth ${tagDepth} exceeds limit of ${maxTagDepth}`);
|
|
1205
1225
|
}
|
|
1206
1226
|
const { tagNumber, bytesConsumed } = parseTagNumber(buffer, offset + 1, additionalInfo);
|
|
1227
|
+
if (options?.validateCanonical) {
|
|
1228
|
+
validateCanonicalInteger(tagNumber, additionalInfo);
|
|
1229
|
+
}
|
|
1207
1230
|
let currentOffset = offset + 1 + bytesConsumed;
|
|
1208
1231
|
if (currentOffset >= buffer.length) {
|
|
1209
1232
|
throw new Error(`Unexpected end of buffer after tag ${tagNumber}`);
|
|
@@ -1432,7 +1455,7 @@ function useCborCollection() {
|
|
|
1432
1455
|
if (!foundBreak) {
|
|
1433
1456
|
throw new Error("Indefinite-length array missing break code (0xFF)");
|
|
1434
1457
|
}
|
|
1435
|
-
items[
|
|
1458
|
+
items[chunkP6A2OOIY_cjs.INDEFINITE_SYMBOL] = true;
|
|
1436
1459
|
} else {
|
|
1437
1460
|
if (options?.limits?.maxArrayLength && length > options.limits.maxArrayLength) {
|
|
1438
1461
|
throw new Error(`Array length ${length} exceeds limit of ${options.limits.maxArrayLength}`);
|
|
@@ -1512,7 +1535,7 @@ function useCborCollection() {
|
|
|
1512
1535
|
if (!foundBreak) {
|
|
1513
1536
|
throw new Error("Indefinite-length map missing break code (0xFF)");
|
|
1514
1537
|
}
|
|
1515
|
-
map[
|
|
1538
|
+
map[chunkP6A2OOIY_cjs.INDEFINITE_SYMBOL] = true;
|
|
1516
1539
|
} else {
|
|
1517
1540
|
if (options?.limits?.maxMapSize && length > options.limits.maxMapSize) {
|
|
1518
1541
|
throw new Error(`Map size ${length} exceeds limit of ${options.limits.maxMapSize}`);
|
|
@@ -1547,16 +1570,17 @@ function useCborCollection() {
|
|
|
1547
1570
|
allEntries.push([keyResult.value, valueResult.value]);
|
|
1548
1571
|
}
|
|
1549
1572
|
}
|
|
1550
|
-
map[
|
|
1573
|
+
map[chunkP6A2OOIY_cjs.ALL_ENTRIES_SYMBOL] = allEntries;
|
|
1551
1574
|
if (options?.validateCanonical && keyBytes.length > 1) {
|
|
1575
|
+
const keyOrder = options?.mapKeyOrder ?? "length-first";
|
|
1552
1576
|
for (let i = 1; i < keyBytes.length; i++) {
|
|
1553
1577
|
const prevKey = keyBytes[i - 1];
|
|
1554
1578
|
const currKey = keyBytes[i];
|
|
1555
1579
|
if (prevKey && currKey) {
|
|
1556
|
-
const cmp =
|
|
1580
|
+
const cmp = compareMapKeys(prevKey, currKey, keyOrder);
|
|
1557
1581
|
if (cmp > 0) {
|
|
1558
1582
|
throw new Error(
|
|
1559
|
-
`Map keys are not in canonical order: key at index ${i} should come before key at index ${i - 1}`
|
|
1583
|
+
`Map keys are not in canonical order (${keyOrder}): key at index ${i} should come before key at index ${i - 1}`
|
|
1560
1584
|
);
|
|
1561
1585
|
}
|
|
1562
1586
|
if (cmp === 0) {
|
|
@@ -1603,29 +1627,32 @@ function useCborCollection() {
|
|
|
1603
1627
|
// src/parser/composables/useCborParser.ts
|
|
1604
1628
|
function useCborParser() {
|
|
1605
1629
|
const mergeOptions = (options) => {
|
|
1606
|
-
if (!options) return
|
|
1630
|
+
if (!options) return chunkP6A2OOIY_cjs.DEFAULT_OPTIONS;
|
|
1607
1631
|
const isCanonical = options.validateCanonical ?? (options.strict ? true : false);
|
|
1608
1632
|
return {
|
|
1609
|
-
strict: options.strict ??
|
|
1633
|
+
strict: options.strict ?? chunkP6A2OOIY_cjs.DEFAULT_OPTIONS.strict,
|
|
1610
1634
|
validateCanonical: isCanonical,
|
|
1611
1635
|
// RFC 8949 Section 4.2: Deterministic encoding MUST NOT use indefinite-length
|
|
1612
|
-
allowIndefinite: options.allowIndefinite ?? (isCanonical || options.strict ? false :
|
|
1636
|
+
allowIndefinite: options.allowIndefinite ?? (isCanonical || options.strict ? false : chunkP6A2OOIY_cjs.DEFAULT_OPTIONS.allowIndefinite),
|
|
1613
1637
|
// Auto-enable duplicate key rejection for canonical or strict mode
|
|
1614
|
-
dupMapKeyMode: options.dupMapKeyMode ?? (isCanonical || options.strict ? "reject" :
|
|
1615
|
-
validateUtf8Strict: options.validateUtf8Strict ?? (options.strict ? true :
|
|
1616
|
-
validateSetUniqueness: options.validateSetUniqueness ?? (options.strict ? true :
|
|
1617
|
-
validateTagSemantics: options.validateTagSemantics ?? (options.strict ? true :
|
|
1618
|
-
validatePlutusSemantics: options.validatePlutusSemantics ?? (options.strict ? true :
|
|
1638
|
+
dupMapKeyMode: options.dupMapKeyMode ?? (isCanonical || options.strict ? "reject" : chunkP6A2OOIY_cjs.DEFAULT_OPTIONS.dupMapKeyMode),
|
|
1639
|
+
validateUtf8Strict: options.validateUtf8Strict ?? (options.strict ? true : chunkP6A2OOIY_cjs.DEFAULT_OPTIONS.validateUtf8Strict),
|
|
1640
|
+
validateSetUniqueness: options.validateSetUniqueness ?? (options.strict ? true : chunkP6A2OOIY_cjs.DEFAULT_OPTIONS.validateSetUniqueness),
|
|
1641
|
+
validateTagSemantics: options.validateTagSemantics ?? (options.strict ? true : chunkP6A2OOIY_cjs.DEFAULT_OPTIONS.validateTagSemantics),
|
|
1642
|
+
validatePlutusSemantics: options.validatePlutusSemantics ?? (options.strict ? true : chunkP6A2OOIY_cjs.DEFAULT_OPTIONS.validatePlutusSemantics),
|
|
1643
|
+
mapKeyOrder: options.mapKeyOrder ?? chunkP6A2OOIY_cjs.DEFAULT_OPTIONS.mapKeyOrder,
|
|
1644
|
+
// Strict mode rejects trailing data after the top-level item (well-formedness).
|
|
1645
|
+
allowTrailingData: options.allowTrailingData ?? (options.strict ? false : chunkP6A2OOIY_cjs.DEFAULT_OPTIONS.allowTrailingData),
|
|
1619
1646
|
limits: {
|
|
1620
|
-
maxInputSize: options.limits?.maxInputSize ??
|
|
1621
|
-
maxOutputSize: options.limits?.maxOutputSize ??
|
|
1622
|
-
maxStringLength: options.limits?.maxStringLength ??
|
|
1623
|
-
maxArrayLength: options.limits?.maxArrayLength ??
|
|
1624
|
-
maxMapSize: options.limits?.maxMapSize ??
|
|
1625
|
-
maxDepth: options.limits?.maxDepth ??
|
|
1626
|
-
maxTagDepth: options.limits?.maxTagDepth ??
|
|
1627
|
-
maxBignumBytes: options.limits?.maxBignumBytes ??
|
|
1628
|
-
maxParseTime: options.limits?.maxParseTime ??
|
|
1647
|
+
maxInputSize: options.limits?.maxInputSize ?? chunkP6A2OOIY_cjs.DEFAULT_LIMITS.maxInputSize,
|
|
1648
|
+
maxOutputSize: options.limits?.maxOutputSize ?? chunkP6A2OOIY_cjs.DEFAULT_LIMITS.maxOutputSize,
|
|
1649
|
+
maxStringLength: options.limits?.maxStringLength ?? chunkP6A2OOIY_cjs.DEFAULT_LIMITS.maxStringLength,
|
|
1650
|
+
maxArrayLength: options.limits?.maxArrayLength ?? chunkP6A2OOIY_cjs.DEFAULT_LIMITS.maxArrayLength,
|
|
1651
|
+
maxMapSize: options.limits?.maxMapSize ?? chunkP6A2OOIY_cjs.DEFAULT_LIMITS.maxMapSize,
|
|
1652
|
+
maxDepth: options.limits?.maxDepth ?? chunkP6A2OOIY_cjs.DEFAULT_LIMITS.maxDepth,
|
|
1653
|
+
maxTagDepth: options.limits?.maxTagDepth ?? chunkP6A2OOIY_cjs.DEFAULT_LIMITS.maxTagDepth,
|
|
1654
|
+
maxBignumBytes: options.limits?.maxBignumBytes ?? chunkP6A2OOIY_cjs.DEFAULT_LIMITS.maxBignumBytes,
|
|
1655
|
+
maxParseTime: options.limits?.maxParseTime ?? chunkP6A2OOIY_cjs.DEFAULT_LIMITS.maxParseTime
|
|
1629
1656
|
}
|
|
1630
1657
|
};
|
|
1631
1658
|
};
|
|
@@ -1650,7 +1677,9 @@ function useCborParser() {
|
|
|
1650
1677
|
if (mergedOptions.limits?.maxInputSize && input.length > mergedOptions.limits.maxInputSize) {
|
|
1651
1678
|
throw new Error(`Input size ${input.length} bytes exceeds limit of ${mergedOptions.limits.maxInputSize} bytes`);
|
|
1652
1679
|
}
|
|
1653
|
-
|
|
1680
|
+
const bufResult = dispatchFromBuffer(input, 0, mergedOptions);
|
|
1681
|
+
checkTrailingData(bufResult.bytesRead, input.length, mergedOptions);
|
|
1682
|
+
return bufResult;
|
|
1654
1683
|
}
|
|
1655
1684
|
const cleanHex = input.replace(/\s+/g, "");
|
|
1656
1685
|
if (!cleanHex || cleanHex.length === 0) {
|
|
@@ -1669,26 +1698,42 @@ function useCborParser() {
|
|
|
1669
1698
|
const buffer = hexToBytes(cleanHex);
|
|
1670
1699
|
const initialByte = readByte(buffer, 0);
|
|
1671
1700
|
const { majorType } = extractCborHeader(initialByte);
|
|
1701
|
+
let result;
|
|
1672
1702
|
switch (majorType) {
|
|
1673
1703
|
case 0:
|
|
1674
1704
|
// Unsigned integer
|
|
1675
1705
|
case 1:
|
|
1676
|
-
|
|
1706
|
+
result = parseInteger(cleanHex, mergedOptions);
|
|
1707
|
+
break;
|
|
1677
1708
|
case 2:
|
|
1678
1709
|
// Byte string
|
|
1679
1710
|
case 3:
|
|
1680
|
-
|
|
1711
|
+
result = parseString(cleanHex, mergedOptions);
|
|
1712
|
+
break;
|
|
1681
1713
|
case 4:
|
|
1682
|
-
|
|
1714
|
+
result = parseArray(cleanHex, mergedOptions);
|
|
1715
|
+
break;
|
|
1683
1716
|
case 5:
|
|
1684
|
-
|
|
1717
|
+
result = parseMap(cleanHex, mergedOptions);
|
|
1718
|
+
break;
|
|
1685
1719
|
case 6:
|
|
1686
|
-
|
|
1720
|
+
result = parseTag(cleanHex, mergedOptions);
|
|
1721
|
+
break;
|
|
1687
1722
|
case 7:
|
|
1688
|
-
|
|
1723
|
+
result = parseFloatOrSimple(cleanHex, mergedOptions);
|
|
1724
|
+
break;
|
|
1689
1725
|
default:
|
|
1690
1726
|
throw new Error(`Unknown major type: ${majorType}`);
|
|
1691
1727
|
}
|
|
1728
|
+
checkTrailingData(result.bytesRead, buffer.length, mergedOptions);
|
|
1729
|
+
return result;
|
|
1730
|
+
};
|
|
1731
|
+
const checkTrailingData = (bytesRead, totalLength, opts) => {
|
|
1732
|
+
if (!opts.allowTrailingData && bytesRead < totalLength) {
|
|
1733
|
+
throw new Error(
|
|
1734
|
+
`Trailing data: ${totalLength - bytesRead} byte(s) remain after the top-level CBOR item (bytesRead=${bytesRead}, length=${totalLength}). Use parseSequence to decode multiple items.`
|
|
1735
|
+
);
|
|
1736
|
+
}
|
|
1692
1737
|
};
|
|
1693
1738
|
const parseWithSourceMap = (input, options) => {
|
|
1694
1739
|
const mergedOptions = mergeOptions(options);
|
|
@@ -2185,6 +2230,12 @@ function useCborParser() {
|
|
|
2185
2230
|
}
|
|
2186
2231
|
};
|
|
2187
2232
|
const parseTagWithMap = (ctx, offset, path, sourceMap) => {
|
|
2233
|
+
const previousTagDepth = ctx.currentTagDepth ?? 0;
|
|
2234
|
+
const maxTagDepth = ctx.options?.limits?.maxTagDepth ?? chunkP6A2OOIY_cjs.DEFAULT_LIMITS.maxTagDepth;
|
|
2235
|
+
if (previousTagDepth >= maxTagDepth) {
|
|
2236
|
+
throw new Error(`Tag nesting depth ${previousTagDepth} exceeds limit of ${maxTagDepth}`);
|
|
2237
|
+
}
|
|
2238
|
+
ctx.currentTagDepth = previousTagDepth + 1;
|
|
2188
2239
|
const startOffset = offset;
|
|
2189
2240
|
const initialByte = readByte(ctx.buffer, offset);
|
|
2190
2241
|
const { additionalInfo } = extractCborHeader(initialByte);
|
|
@@ -2193,6 +2244,9 @@ function useCborParser() {
|
|
|
2193
2244
|
offset + 1,
|
|
2194
2245
|
additionalInfo
|
|
2195
2246
|
);
|
|
2247
|
+
if (ctx.options?.validateCanonical) {
|
|
2248
|
+
validateCanonicalInteger(tagNumber, additionalInfo);
|
|
2249
|
+
}
|
|
2196
2250
|
let currentOffset = offset + 1 + bytesConsumed;
|
|
2197
2251
|
const headerEnd = currentOffset;
|
|
2198
2252
|
const tagEntryIndex = sourceMap.length;
|
|
@@ -2218,7 +2272,7 @@ function useCborParser() {
|
|
|
2218
2272
|
}
|
|
2219
2273
|
let finalValue = valueResult.value;
|
|
2220
2274
|
if ((tagNumber === 2 || tagNumber === 3) && finalValue instanceof Uint8Array) {
|
|
2221
|
-
const maxBignumBytes = ctx.options?.limits?.maxBignumBytes ??
|
|
2275
|
+
const maxBignumBytes = ctx.options?.limits?.maxBignumBytes ?? chunkP6A2OOIY_cjs.DEFAULT_LIMITS.maxBignumBytes;
|
|
2222
2276
|
if (finalValue.length > maxBignumBytes) {
|
|
2223
2277
|
throw new Error(
|
|
2224
2278
|
`Bignum (tag ${tagNumber}) size ${finalValue.length} bytes exceeds limit of ${maxBignumBytes} bytes`
|
|
@@ -2237,6 +2291,7 @@ function useCborParser() {
|
|
|
2237
2291
|
value: finalValue,
|
|
2238
2292
|
...plutusConstr && { plutus: plutusConstr }
|
|
2239
2293
|
};
|
|
2294
|
+
ctx.currentTagDepth = previousTagDepth;
|
|
2240
2295
|
return {
|
|
2241
2296
|
value: taggedValue,
|
|
2242
2297
|
bytesRead: currentOffset - startOffset
|
|
@@ -2315,8 +2370,7 @@ function useCborParser() {
|
|
|
2315
2370
|
if (byte === 255) {
|
|
2316
2371
|
throw new Error(`Unexpected break code (0xff) at offset ${offset}`);
|
|
2317
2372
|
}
|
|
2318
|
-
const
|
|
2319
|
-
const result = parseWithSourceMap(remainingHex, mergedOptions);
|
|
2373
|
+
const result = parseWithSourceMap(buffer.subarray(offset), mergedOptions);
|
|
2320
2374
|
const adjustedSourceMap = result.sourceMap.map((entry) => ({
|
|
2321
2375
|
...entry,
|
|
2322
2376
|
start: entry.start + offset,
|
|
@@ -2349,5 +2403,5 @@ exports.useCborParser = useCborParser;
|
|
|
2349
2403
|
exports.useCborString = useCborString;
|
|
2350
2404
|
exports.useCborTag = useCborTag;
|
|
2351
2405
|
exports.validateUtf8Strict = validateUtf8Strict;
|
|
2352
|
-
//# sourceMappingURL=chunk-
|
|
2353
|
-
//# sourceMappingURL=chunk-
|
|
2406
|
+
//# sourceMappingURL=chunk-3Z45RBZP.cjs.map
|
|
2407
|
+
//# sourceMappingURL=chunk-3Z45RBZP.cjs.map
|