fix: guard non-scientific formatter against positive-exp int224 overflow#243
Conversation
`_toNonScientific` produced strings whose integer part exceeded int224.max when `exponent > 0`, causing `parseDecimalFloat` to return `ParseDecimalPrecisionLoss` instead of round-tripping cleanly. Replace the incorrect digit-count guard (based on int256, not int224) with a precise value check: when `exponent > 0`, revert `UnformatableExponent` if `absCoef > floor(int224.max / 10^exponent)`. Update tests to expect the new revert for previously-accepted non-round-trippable inputs, and add a fuzz test that confirms round-trip succeeds for every positive-exponent float that the formatter accepts. Closes #184 Co-Authored-By: Claude <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 10 minutes and 3 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (4)
WalkthroughAdds an overflow guard to ChangesNon-scientific positive-exponent overflow guard
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…flows int32 `_toScientific` produced strings like `1.23e2147483720` when the display exponent exceeded `int32.max`, because `displayExponent = exp + scaleExponent` (75 or 76) was computed in int256 but never bounds-checked. `parseDecimalFloat` subsequently rejected the string with `ExponentOverflow`. Save the original exponent before `maximizeFull`, then after computing `displayExponent` check it fits in `[int32.min, int32.max]` and revert `UnformatableExponent(originalExponent)` if not. Closes #185 Co-Authored-By: Claude <noreply@anthropic.com>
…ter fix Formatter source changes in LibFormatDecimalFloat.sol change the bytecode of DecimalFloat, so the Zoltu deployment address and codehash must be updated. Also regenerates crates/float/abi/DecimalFloat.json via CopyArtifacts. Co-Authored-By: Claude <noreply@anthropic.com>
The positive-exponent int224-overflow guard added for issue #184 raises the function's CC to 15; the logic mirrors the complexity already present in `div` (which carries the same suppress comment). Co-Authored-By: Claude <noreply@anthropic.com>
|
human-approved; merging (all failing checks are testProdDeployment* deploy-pinned tests — DecimalFloat not yet deployed on live networks, known pre-existing env condition) |
|
@coderabbitai assess this PR size classification for the totality of the PR with the following criterias and report it in your comment: S/M/L PR Classification Guidelines:This guide helps classify merged pull requests by effort and complexity rather than just line count. The goal is to assess the difficulty and scope of changes after they have been completed. Small (S)Characteristics:
Review Effort: Would have taken 5-10 minutes Examples:
Medium (M)Characteristics:
Review Effort: Would have taken 15-30 minutes Examples:
Large (L)Characteristics:
Review Effort: Would have taken 45+ minutes Examples:
Additional Factors to ConsiderWhen deciding between sizes, also consider:
Notes:
|
|
Tip For best results, initiate chat on the files or code changes. SIZE=M |
Summary
_toNonScientificaccepted floats withexponent > 0and emitted integer strings whose value exceededint224.max(e.g.(1, 77)→"100…0"with 78 digits), causingparseDecimalFloatto fail withParseDecimalPrecisionLossinstead of round-tripping.int256-based digit count (76) rather than checking the actual value againstint224.max(≈1.34e67).exponent > 0, revertUnformatableExponentifabsCoef > floor(int224.max / 10^exponent). Forexponent ≥ 68the check short-circuits immediately (10^68 > int224.max unconditionally).LargePositiveExponent,LargeCoefficientLargeExponent,OutputShape) are updated to either expect the new revert or bound inputs to the safe range.testFormatParseRoundTripNonScientificSafePosExpmirrors the formatter guard invm.assumeand confirms round-trip holds for every accepted positive-exponent float.Closes #184
Test plan
forge test --match-path test/src/lib/format/LibFormatDecimalFloat.toDecimalString.t.sol— all 26 passforge testsuite passes (no regressions)testFormatNonScientificLargePositiveExponentandtestFormatNonScientificLargeCoefficientLargeExponentnow testvm.expectRevertnot successtestFormatNonScientificAtIntDigitBoundarywith(1, 67)round-trips (1e67 < int224.max ≈ 1.34e67)🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Tests