fix(bigint): correct log2(10) buffer-estimate constant#5
Open
LukaszRozmej wants to merge 2 commits into
Open
Conversation
Collaborator
|
@LukaszRozmej let's make a run in Actions for this particular patch. |
The integer-math buffer-length estimate in the BigInteger parsing patch used 3321928095 (= round(log2(10) * 10^9), a decimal scaling) together with a binary `>> 35` shift. That pairs a base-10 numerator with a base-2 divisor, so the effective multiplier is 0.0966808 instead of the intended log2(10)/32 = 0.1038103 — a 6.87% under-estimate. Once the digit count exceeds ~424, the shortfall exceeds the +3 slack and the result buffer is undersized, causing out-of-bounds writes (e.g. parsing a BigInteger from a numeric string of a few hundred or more digits). Replace the constant with round(log2(10) * 2^30) = 3566893132 in all three sites, matching the comment's stated intent. Verified the corrected value never under-allocates across digit counts up to 2,000,000. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse the three duplicated word-count estimates into a single static local function in NumberToBigInteger, used by the method body and the nested DivideAndConquer/Recursive local functions. The log2(10) fixed-point constant now appears exactly once, so it can no longer drift between sites, and each call-site is a single readable line carrying its own slack. The overflow-checked addition on the two inner sites is preserved. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
LukaszRozmej
force-pushed
the
fix/bigint-buffer-estimate-constant
branch
from
June 30, 2026 16:02
e0d38cc to
eb93de3
Compare
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
Two related commits:
Correctness fix. The integer-math buffer-length estimate added to
17_bigint.patch(BigInteger decimal parsing) used the constant3321928095with a binary>> 35shift. That constant isround(log2(10) × 10⁹)— a decimal scaling of log₂(10) — but it is divided by2³⁵(a binary unit). The unit mismatch makes the effective per-digit word multiplier0.09668083instead of the intendedlog2(10)/32 = 0.10381025— a 6.87% under-estimate (matching theround(log2(10)·2³⁰) = 3566893132the comment claims). Fixed by using3566893132.Helper extraction. The same estimate was duplicated across three sites (
NumberToBigInteger,DivideAndConquer,Recursive), each with its own copy of the fixed-point constant. Extracted into a singleEstimateWordCountstatic local function so the constant lives in exactly one place and can never drift between sites again. The overflow-checkedadditions on the two inner sites are preserved.Impact of the bug
The buffer carries a
+3slack. The deficit≈ 0.00713 · digitCount − 3overtakes that slack once the digit count passes ~424, after which the result buffer is undersized:All three sites share the defect. An undersized buffer leads to out-of-bounds writes during conversion — reachable by parsing a
BigIntegerfrom any numeric string of a few hundred or more digits.Verification
Confirmed the corrected constant never under-allocates for digit counts from 1 to 2,000,000.
🤖 Generated with Claude Code