Skip to content

Commit 66af3fe

Browse files
authored
fix(NODE-6826): incorrect negative bigint handling (#772)
1 parent ab5f111 commit 66af3fe

File tree

2 files changed

+56
-7
lines changed

2 files changed

+56
-7
lines changed

src/utils/number_utils.ts

+16-7
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,23 @@ export const NumberUtils = {
4444

4545
/** Reads a little-endian 64-bit integer from source */
4646
getBigInt64LE(source: Uint8Array, offset: number): bigint {
47-
const lo = NumberUtils.getUint32LE(source, offset);
48-
const hi = NumberUtils.getUint32LE(source, offset + 4);
47+
// eslint-disable-next-line no-restricted-globals
48+
const hi = BigInt(
49+
source[offset + 4] +
50+
source[offset + 5] * 256 +
51+
source[offset + 6] * 65536 +
52+
(source[offset + 7] << 24)
53+
); // Overflow
4954

50-
/*
51-
eslint-disable-next-line no-restricted-globals
52-
-- This is allowed since this helper should not be called unless bigint features are enabled
53-
*/
54-
return (BigInt(hi) << BigInt(32)) + BigInt(lo);
55+
// eslint-disable-next-line no-restricted-globals
56+
const lo = BigInt(
57+
source[offset] +
58+
source[offset + 1] * 256 +
59+
source[offset + 2] * 65536 +
60+
source[offset + 3] * 16777216
61+
);
62+
// eslint-disable-next-line no-restricted-globals
63+
return (hi << BigInt(32)) + lo;
5564
},
5665

5766
/** Reads a little-endian 64-bit float from source */

test/node/bigint.test.ts

+40
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,46 @@ describe('BSON BigInt support', function () {
105105

106106
it(description, test);
107107
}
108+
109+
it('correctly deserializes min 64 bit int (-2n**63n)', function () {
110+
expect(
111+
BSON.deserialize(Buffer.from('10000000126100000000000000008000', 'hex'), {
112+
useBigInt64: true
113+
})
114+
).to.deep.equal({ a: -(2n ** 63n) });
115+
});
116+
117+
it('correctly deserializes -1n', function () {
118+
expect(
119+
BSON.deserialize(Buffer.from('10000000126100FFFFFFFFFFFFFFFF00', 'hex'), {
120+
useBigInt64: true
121+
})
122+
).to.deep.equal({ a: -1n });
123+
});
124+
125+
it('correctly deserializes 0n', function () {
126+
expect(
127+
BSON.deserialize(Buffer.from('10000000126100000000000000000000', 'hex'), {
128+
useBigInt64: true
129+
})
130+
).to.deep.equal({ a: 0n });
131+
});
132+
133+
it('correctly deserializes 1n', function () {
134+
expect(
135+
BSON.deserialize(Buffer.from('10000000126100010000000000000000', 'hex'), {
136+
useBigInt64: true
137+
})
138+
).to.deep.equal({ a: 1n });
139+
});
140+
141+
it('correctly deserializes max 64 bit int (2n**63n -1n)', function () {
142+
expect(
143+
BSON.deserialize(Buffer.from('10000000126100FFFFFFFFFFFFFF7F00', 'hex'), {
144+
useBigInt64: true
145+
})
146+
).to.deep.equal({ a: 2n ** 63n - 1n });
147+
});
108148
});
109149

110150
describe('BSON.serialize()', function () {

0 commit comments

Comments
 (0)