Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix big number accuracy #2276

Closed
wants to merge 1 commit into from
Closed

Conversation

KunZhou-at
Copy link
Contributor

@KunZhou-at KunZhou-at commented Nov 14, 2023

Previously, big numbers were sometimes returned as number instead of string even if the number is larger than Number.MAX_SAFE_INTEGER or smaller than Number.MIN_SAFE_INTEGER. The behavior was conditional on the equality of bigNumber.toString() === fullAccuracyNumberInString. However, the number may not be at full accuracy: for many big numbers BigInt(bigNumber).toString() !== bigNumber.toString(), e.g., 99000001013466380

Screenshot 2023-11-13 at 7 43 29 PM

@KunZhou-at KunZhou-at force-pushed the fixBigNumber branch 4 times, most recently from 3ccf7e4 to a345aed Compare November 14, 2023 10:34
}
return sign === -1 ? `-${str}` : str;
}
if (numDigits > 16) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code?

@KunZhou-at KunZhou-at marked this pull request as ready for review November 16, 2023 20:25
@KunZhou-at
Copy link
Contributor Author

cc @wellwelwel @sidorares this was a pretty critical bug that caused data corruption for us, would love to contribute the fix to upstream

@wellwelwel wellwelwel mentioned this pull request Apr 17, 2024
@wellwelwel
Copy link
Collaborator

@KunZhou-at, in fact the Number.MAX_SAFE_INTEGER is 9007199254740991.

this was a pretty critical bug that caused data corruption for us

I couldn't understand the issue, could you show an example where this would fail? It would be great if we could add a test to cover this possible failure as well 🙋🏻‍♂️

@KunZhou-at
Copy link
Contributor Author

KunZhou-at commented Apr 17, 2024

@wellwelwel thanks for taking a look! Basically my change is from

res = resNumber.toString() === resString ? resNumber : resString;

to

res = res.greaterThan(Number.MAX_SAFE_INTEGER) || res.lessThan(Number.MIN_SAFE_INTEGER) ? resString : res.toNumber();

There are numbers larger than Number.MAX_SAFE_INTEGER such that resNumber.toString() === resString, and the example I have provided is 99000001013466380. While the number's toString does print out the same number, it does not behave nicely with other native node facilities such as bigint. I think it's expected that the behavior of numbers outside of the safe range is undefined. I don't think toString is the correct way to determine if a number is at full accuracy.

I updated the test to only return strings for numbers above Number.MAX_SAFE_INTEGER, i.e. 9007199254740991.

@KunZhou-at
Copy link
Contributor Author

@wellwelwel I still think this is a critical bug that can cause database corruption, but closing since it's not getting attention. Feel free to open and I can resolve the conflicts if that changes.

@KunZhou-at KunZhou-at closed this May 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants