Skip to content

Commit 0959339

Browse files
W-A-Jamesnbbeeken
authored andcommitted
fix(NODE-6764): incorrect negative bigint handling (#752)
1 parent b64e912 commit 0959339

File tree

2 files changed

+56
-7
lines changed

2 files changed

+56
-7
lines changed

src/utils/number_utils.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,23 @@ export const NumberUtils = {
3939

4040
/** Reads a little-endian 64-bit integer from source */
4141
getBigInt64LE(source: Uint8Array, offset: number): bigint {
42-
const lo = NumberUtils.getUint32LE(source, offset);
43-
const hi = NumberUtils.getUint32LE(source, offset + 4);
42+
// eslint-disable-next-line no-restricted-globals
43+
const hi = BigInt(
44+
source[offset + 4] +
45+
source[offset + 5] * 256 +
46+
source[offset + 6] * 65536 +
47+
(source[offset + 7] << 24)
48+
); // Overflow
4449

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

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

test/node/bigint.test.ts

Lines changed: 40 additions & 0 deletions
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)