Skip to content

Commit

Permalink
fix(NODE-6144): Long.fromString incorrectly coerces valid inputs to L…
Browse files Browse the repository at this point in the history
…ong.ZERO in special cases (#677)
  • Loading branch information
aditi-khare-mongoDB authored May 1, 2024
1 parent 9d5a5df commit 208f7e8
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 6 deletions.
40 changes: 38 additions & 2 deletions src/long.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,26 +371,58 @@ export class Long extends BSONValue {

/**
* Returns a signed Long representation of the given string, written using radix 10.
*
* If the input string is empty, this function will throw a BSONError.
*
* If input string does not have valid signed 64-bit Long representation, this method will return a coerced value:
* - inputs that overflow 64-bit signed long will be coerced to Long.MAX_VALUE and Long.MIN_VALUE respectively
* - 'NaN' or '+/-Infinity' are coerced to Long.ZERO
* - other invalid characters sequences have variable behavior
*
* @param str - The textual representation of the Long
* @returns The corresponding Long value
*/
static fromString(str: string): Long;
/**
* Returns a signed Long representation of the given string, written using radix 10.
* Returns a signed Long representation of the given string, written using the provided radix.
*
* If the input string is empty or a provided radix is not within (2-36), this function will throw a BSONError.
*
* If input parameters do not have valid signed 64-bit Long representation, this method will return a coerced value:
* - inputs that overflow 64-bit signed long will be coerced to Long.MAX_VALUE and Long.MIN_VALUE respectively
* - if the radix is less than 24, 'NaN' is coerced to Long.ZERO
* - if the radix is less than 35, '+/-Infinity' inputs are coerced to Long.ZERO
* - other invalid characters sequences have variable behavior
* @param str - The textual representation of the Long
* @param radix - The radix in which the text is written (2-36), defaults to 10
* @returns The corresponding Long value
*/
static fromString(str: string, radix?: number): Long;
/**
* Returns a Long representation of the given string, written using radix 10.
*
* If the input string is empty, this function will throw a BSONError.
*
* If input parameters do not have a valid 64-bit Long representation, this method will return a coerced value:
* - inputs that overflow 64-bit long will be coerced to max or min (if signed) values
* - if the radix is less than 24, 'NaN' is coerced to Long.ZERO
* - if the radix is less than 35, '+/-Infinity' inputs are coerced to Long.ZERO
* - other invalid characters sequences have variable behavior
* @param str - The textual representation of the Long
* @param unsigned - Whether unsigned or not, defaults to signed
* @returns The corresponding Long value
*/
static fromString(str: string, unsigned?: boolean): Long;
/**
* Returns a Long representation of the given string, written using the specified radix.
*
* If the input string is empty or a provided radix is not within (2-36), this function will throw a BSONError.
*
* If input parameters do not have a valid 64-bit Long representation, this method will return a coerced value:
* - inputs that overflow 64-bit long will be coerced to max or min (if signed) values
* - if the radix is less than 24, 'NaN' is coerced to Long.ZERO
* - if the radix is less than 35, '+/-Infinity' inputs are coerced to Long.ZERO
* - other invalid characters sequences have variable behavior
* @param str - The textual representation of the Long
* @param unsigned - Whether unsigned or not, defaults to signed
* @param radix - The radix in which the text is written (2-36), defaults to 10
Expand All @@ -406,7 +438,11 @@ export class Long extends BSONValue {
unsigned = !!unsignedOrRadix;
}
radix ??= 10;
if (str === 'NaN' || str === 'Infinity' || str === '+Infinity' || str === '-Infinity') {
if (str === 'NaN' && radix < 24) {
// radix does not support n, so coerce to zero
return Long.ZERO;
} else if ((str === 'Infinity' || str === '+Infinity' || str === '-Infinity') && radix < 35) {
// radix does not support y, so coerce to zero
return Long.ZERO;
}
return Long._fromString(str, unsigned, radix);
Expand Down
12 changes: 8 additions & 4 deletions test/node/long.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,14 @@ describe('Long', function () {
radix: number | undefined,
expectedStr?: string
][] = [
['Infinity', 'Infinity', false, 34, '0'],
['-Infinity', '-Infinity', false, 23, '0'],
['+Infinity', '+Infinity', false, 12, '0'],
['NaN', 'NaN', false, 16, '0']
['radix 36 Infinity', 'Infinity', false, 36],
['radix 36 -Infinity', '-Infinity', false, 36],
['radix 36 +Infinity', '+Infinity', false, 36, 'infinity'],
['radix < 35 Infinity', 'Infinity', false, 34, '0'],
['radix < 35 -Infinity', '-Infinity', false, 23, '0'],
['radix < 35 +Infinity', '+Infinity', false, 12, '0'],
['radix < 24 NaN', 'NaN', false, 16, '0'],
['radix > 24 NaN', 'NaN', false, 25]
];

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

0 comments on commit 208f7e8

Please sign in to comment.