fix: prevent _decimalPlaces infinite loop when multiplier overflows to Infinity#12266
Open
JSap0914 wants to merge 1 commit into
Open
fix: prevent _decimalPlaces infinite loop when multiplier overflows to Infinity#12266JSap0914 wants to merge 1 commit into
JSap0914 wants to merge 1 commit into
Conversation
When x is a finite number smaller than ~1e-305, the multiplier e grows beyond Number.MAX_VALUE and overflows to Infinity. At that point: - Math.round(x * Infinity) / Infinity evaluates to NaN - NaN !== x is always true, causing an infinite loop Add an isFinite(e) guard that exits the loop and returns undefined, consistent with the function's existing behavior for non-finite inputs. Fixes: _decimalPlaces(1e-305), _decimalPlaces(Number.MIN_VALUE), etc. Related: chartjs#5992
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
_decimalPlaces(x)insrc/helpers/helpers.math.tscan enter an infinite loop for certain finite numbers — specifically, values smaller than approximately1e-305.Root Cause
The algorithm multiplies
eby 10 each iteration, looking for a power of 10 whereMath.round(x * e) / e === x. For very small numbers, the required power of 10 exceedsNumber.MAX_VALUE(~1.8e308). Whene *= 10overflows toInfinity:x * Infinity=InfinityMath.round(Infinity) / Infinity=NaNNaN !== xis alwaystrue→ infinite loopFix
A single guard inside the while loop:
This returns
undefinedwheneoverflows, consistent with the function's existing behavior for non-finite inputs (!isFiniteNumber(x)path).Affected values
Any finite
xwhere the loop needse > Number.MAX_VALUEto converge — in practice, numbers smaller than approximately1e-305. Examples:1e-306,1e-307,1e-308,Number.MIN_VALUE.Impact on callers
_decimalPlacesis called inscale.linearbase.jsduring tick generation. Returningundefinedthere falls through toMath.max(undefined, ...) = NaNin thedecimalPlacesvariable — the same degenerate outcome as passing a non-finite axis range, which is already an unsupported input. The infinite loop (current behavior) is strictly worse than returningundefined.Testing
New assertions added to the existing
it('should get the correct number of decimal places')block — no existing tests were modified.