Skip to content

Commit 18e6578

Browse files
authored
fix(NODE-6827): incorrect negative bigint handling (#771)
1 parent 9ded2fc commit 18e6578

File tree

2 files changed

+57
-8
lines changed

2 files changed

+57
-8
lines changed

src/utils/number_utils.ts

+17-8
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,23 @@ export const NumberUtils: NumberUtils = {
7979

8080
/** Reads a little-endian 64-bit integer from source */
8181
getBigInt64LE(source: Uint8Array, offset: number): bigint {
82-
const lo = NumberUtils.getUint32LE(source, offset);
83-
const hi = NumberUtils.getUint32LE(source, offset + 4);
84-
85-
/*
86-
eslint-disable-next-line no-restricted-globals
87-
-- This is allowed since this helper should not be called unless bigint features are enabled
88-
*/
89-
return (BigInt(hi) << BigInt(32)) + BigInt(lo);
82+
// eslint-disable-next-line no-restricted-globals
83+
const hi = BigInt(
84+
source[offset + 4] +
85+
source[offset + 5] * 256 +
86+
source[offset + 6] * 65536 +
87+
(source[offset + 7] << 24)
88+
); // Overflow
89+
90+
// eslint-disable-next-line no-restricted-globals
91+
const lo = BigInt(
92+
source[offset] +
93+
source[offset + 1] * 256 +
94+
source[offset + 2] * 65536 +
95+
source[offset + 3] * 16777216
96+
);
97+
// eslint-disable-next-line no-restricted-globals
98+
return (hi << BigInt(32)) + lo;
9099
},
91100

92101
/** 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)