Skip to content

Commit 208f7e8

Browse files
fix(NODE-6144): Long.fromString incorrectly coerces valid inputs to Long.ZERO in special cases (#677)
1 parent 9d5a5df commit 208f7e8

File tree

2 files changed

+46
-6
lines changed

2 files changed

+46
-6
lines changed

src/long.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,26 +371,58 @@ export class Long extends BSONValue {
371371

372372
/**
373373
* Returns a signed Long representation of the given string, written using radix 10.
374+
*
375+
* If the input string is empty, this function will throw a BSONError.
376+
*
377+
* If input string does not have valid signed 64-bit Long representation, this method will return a coerced value:
378+
* - inputs that overflow 64-bit signed long will be coerced to Long.MAX_VALUE and Long.MIN_VALUE respectively
379+
* - 'NaN' or '+/-Infinity' are coerced to Long.ZERO
380+
* - other invalid characters sequences have variable behavior
381+
*
374382
* @param str - The textual representation of the Long
375383
* @returns The corresponding Long value
376384
*/
377385
static fromString(str: string): Long;
378386
/**
379-
* Returns a signed Long representation of the given string, written using radix 10.
387+
* Returns a signed Long representation of the given string, written using the provided radix.
388+
*
389+
* If the input string is empty or a provided radix is not within (2-36), this function will throw a BSONError.
390+
*
391+
* If input parameters do not have valid signed 64-bit Long representation, this method will return a coerced value:
392+
* - inputs that overflow 64-bit signed long will be coerced to Long.MAX_VALUE and Long.MIN_VALUE respectively
393+
* - if the radix is less than 24, 'NaN' is coerced to Long.ZERO
394+
* - if the radix is less than 35, '+/-Infinity' inputs are coerced to Long.ZERO
395+
* - other invalid characters sequences have variable behavior
380396
* @param str - The textual representation of the Long
381397
* @param radix - The radix in which the text is written (2-36), defaults to 10
382398
* @returns The corresponding Long value
383399
*/
384400
static fromString(str: string, radix?: number): Long;
385401
/**
386402
* Returns a Long representation of the given string, written using radix 10.
403+
*
404+
* If the input string is empty, this function will throw a BSONError.
405+
*
406+
* If input parameters do not have a valid 64-bit Long representation, this method will return a coerced value:
407+
* - inputs that overflow 64-bit long will be coerced to max or min (if signed) values
408+
* - if the radix is less than 24, 'NaN' is coerced to Long.ZERO
409+
* - if the radix is less than 35, '+/-Infinity' inputs are coerced to Long.ZERO
410+
* - other invalid characters sequences have variable behavior
387411
* @param str - The textual representation of the Long
388412
* @param unsigned - Whether unsigned or not, defaults to signed
389413
* @returns The corresponding Long value
390414
*/
391415
static fromString(str: string, unsigned?: boolean): Long;
392416
/**
393417
* Returns a Long representation of the given string, written using the specified radix.
418+
*
419+
* If the input string is empty or a provided radix is not within (2-36), this function will throw a BSONError.
420+
*
421+
* If input parameters do not have a valid 64-bit Long representation, this method will return a coerced value:
422+
* - inputs that overflow 64-bit long will be coerced to max or min (if signed) values
423+
* - if the radix is less than 24, 'NaN' is coerced to Long.ZERO
424+
* - if the radix is less than 35, '+/-Infinity' inputs are coerced to Long.ZERO
425+
* - other invalid characters sequences have variable behavior
394426
* @param str - The textual representation of the Long
395427
* @param unsigned - Whether unsigned or not, defaults to signed
396428
* @param radix - The radix in which the text is written (2-36), defaults to 10
@@ -406,7 +438,11 @@ export class Long extends BSONValue {
406438
unsigned = !!unsignedOrRadix;
407439
}
408440
radix ??= 10;
409-
if (str === 'NaN' || str === 'Infinity' || str === '+Infinity' || str === '-Infinity') {
441+
if (str === 'NaN' && radix < 24) {
442+
// radix does not support n, so coerce to zero
443+
return Long.ZERO;
444+
} else if ((str === 'Infinity' || str === '+Infinity' || str === '-Infinity') && radix < 35) {
445+
// radix does not support y, so coerce to zero
410446
return Long.ZERO;
411447
}
412448
return Long._fromString(str, unsigned, radix);

test/node/long.test.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,14 @@ describe('Long', function () {
172172
radix: number | undefined,
173173
expectedStr?: string
174174
][] = [
175-
['Infinity', 'Infinity', false, 34, '0'],
176-
['-Infinity', '-Infinity', false, 23, '0'],
177-
['+Infinity', '+Infinity', false, 12, '0'],
178-
['NaN', 'NaN', false, 16, '0']
175+
['radix 36 Infinity', 'Infinity', false, 36],
176+
['radix 36 -Infinity', '-Infinity', false, 36],
177+
['radix 36 +Infinity', '+Infinity', false, 36, 'infinity'],
178+
['radix < 35 Infinity', 'Infinity', false, 34, '0'],
179+
['radix < 35 -Infinity', '-Infinity', false, 23, '0'],
180+
['radix < 35 +Infinity', '+Infinity', false, 12, '0'],
181+
['radix < 24 NaN', 'NaN', false, 16, '0'],
182+
['radix > 24 NaN', 'NaN', false, 25]
179183
];
180184

181185
for (const [testName, str, unsigned, radix, expectedStr] of successInputs) {

0 commit comments

Comments
 (0)