Skip to content

Commit 4927981

Browse files
committed
fix(core/cbor): calculation of bigInteger offset
1 parent d633bf1 commit 4927981

File tree

3 files changed

+82
-8
lines changed

3 files changed

+82
-8
lines changed

.changeset/clever-shirts-prove.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@smithy/core": patch
3+
---
4+
5+
fix offset calculation when decoding bigInteger in CBOR

packages/core/src/submodules/cbor/cbor-decode.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,22 +129,26 @@ export function decode(at: Uint32, to: Uint32): CborValueType {
129129
for (let i = start; i < start + length; ++i) {
130130
b = (b << BigInt(8)) | BigInt(payload[i]);
131131
}
132-
133-
_offset = offset + length;
132+
// the new offset is the sum of:
133+
// 1. the local major offset (1)
134+
// 2. the offset of the decoded count of the bigInteger
135+
// 3. the length of the data bytes of the bigInteger
136+
_offset = offset + _offset + length;
134137
return minor === 3 ? -b - BigInt(1) : b;
135138
} else if (minor === 4) {
136139
const decimalFraction = decode(at + offset, to);
137140
const [exponent, mantissa] = decimalFraction;
138141
const s = mantissa.toString();
139142
const numericString = exponent === 0 ? s : s.slice(0, s.length + exponent) + "." + s.slice(exponent);
140-
143+
// no new _offset is set here, because
144+
// the call to decode for the decimalFraction
145+
// has set it.
141146
return new NumericValue(numericString, "bigDecimal");
142147
} else {
143148
const value = decode(at + offset, to);
144149
const valueOffset = _offset;
145150

146151
_offset = offset + valueOffset;
147-
148152
return tag({ tag: castBigInt(unsignedInt), value });
149153
}
150154
}

packages/core/src/submodules/cbor/cbor.spec.ts

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { NumericValue } from "@smithy/core/serde";
1+
import { NumericValue, nv } from "@smithy/core/serde";
22
import * as fs from "fs";
33
// @ts-ignore
44
import JSONbig from "json-bigint";
@@ -219,12 +219,23 @@ describe("cbor", () => {
219219
name: "object containing big numbers",
220220
data: {
221221
map: {
222-
items: [BigInt(1e80)],
222+
items: [BigInt(1e80), BigInt(1e80), nv("0.0000000001234000000001234"), nv("0.0000000001234000000001234")],
223+
bigint: BigInt(1e80),
224+
bigDecimal: nv("0.0000000001234000000001234"),
223225
},
224226
},
225227
cbor: allocByteArray([
226-
161, 99, 109, 97, 112, 161, 101, 105, 116, 101, 109, 115, 129, 194, 88, 34, 3, 95, 157, 234, 62, 31, 107, 224,
227-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
228+
161, 99, 109, 97, 112, 163, 101, 105, 116, 101, 109, 115, 132, 194, 88, 34, 3, 95, 157, 234, 62, 31, 107, 224,
229+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 88, 34, 3, 95, 157, 234, 62,
230+
31, 107, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 102, 115, 116,
231+
114, 105, 110, 103, 120, 27, 48, 46, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 50, 51, 52, 48, 48, 48, 48, 48, 48,
232+
48, 48, 49, 50, 51, 52, 100, 116, 121, 112, 101, 106, 98, 105, 103, 68, 101, 99, 105, 109, 97, 108, 162, 102,
233+
115, 116, 114, 105, 110, 103, 120, 27, 48, 46, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 50, 51, 52, 48, 48, 48,
234+
48, 48, 48, 48, 48, 49, 50, 51, 52, 100, 116, 121, 112, 101, 106, 98, 105, 103, 68, 101, 99, 105, 109, 97, 108,
235+
102, 98, 105, 103, 105, 110, 116, 194, 88, 34, 3, 95, 157, 234, 62, 31, 107, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
236+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 98, 105, 103, 68, 101, 99, 105, 109, 97, 108, 162, 102,
237+
115, 116, 114, 105, 110, 103, 120, 27, 48, 46, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 50, 51, 52, 48, 48, 48,
238+
48, 48, 48, 48, 48, 49, 50, 51, 52, 100, 116, 121, 112, 101, 106, 98, 105, 103, 68, 101, 99, 105, 109, 97, 108,
228239
]),
229240
},
230241
];
@@ -305,6 +316,60 @@ describe("cbor", () => {
305316
}
306317
});
307318

319+
it("should round-trip sequences of big numbers", () => {
320+
const sequence = {
321+
map: {
322+
items1: [
323+
BigInt(1e20),
324+
BigInt(2e30),
325+
BigInt(3e40),
326+
BigInt(4e50),
327+
BigInt(5e60),
328+
BigInt(6e70),
329+
BigInt(7e80),
330+
BigInt(8e90),
331+
],
332+
items2: [BigInt(1e20), BigInt(2e30), nv("0.0000000001123434"), nv("0.000000000126781234")],
333+
items3: [nv("0.0000000001234000000001234"), nv("0.00000000678678001234"), BigInt(1e20), BigInt(2e30)],
334+
items4: [
335+
BigInt(1e20),
336+
BigInt(2e30),
337+
nv("0.0000000001234000000001234"),
338+
nv("0.0000067867867801234"),
339+
BigInt(1e20),
340+
BigInt(2e30),
341+
nv("0.0000000001234000000001234"),
342+
nv("0.000000000123678678678234"),
343+
],
344+
items5: [
345+
nv("0.0000000001234000000001234"),
346+
nv("0.00006786781234678678678"),
347+
BigInt(1e20),
348+
BigInt(2e30),
349+
nv("0.0000000001234000000001234"),
350+
nv("0.000000000123400000087678634"),
351+
BigInt(1e20),
352+
BigInt(2e30),
353+
],
354+
items6: [
355+
nv("0.0000000001234000000001234"),
356+
nv("0.00006786781234678678678"),
357+
nv("0.0000000001234000000001234"),
358+
nv("0.000000000123400000087678634"),
359+
nv("0.0000000001234000000001234"),
360+
nv("0.00006786781234678678678"),
361+
nv("0.0000000001234000000001234"),
362+
nv("0.000000000123400000087678634"),
363+
],
364+
},
365+
};
366+
367+
const serialized = cbor.serialize(sequence);
368+
const deserialized = cbor.deserialize(serialized);
369+
370+
expect(deserialized).toEqual(sequence);
371+
});
372+
308373
it("should throw an error if serializing a tag with missing properties", () => {
309374
expect(() =>
310375
cbor.serialize({

0 commit comments

Comments
 (0)