Repository navigation
Conversation
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The focused implementation addresses the precision defect while retaining existing floating-point behavior and includes comprehensive regression coverage.
Review effort: Balanced
Findings: None
What changed in this PR
Preserves exact numeric operands during multipleOf validation, preventing precision loss for large integers and extreme decimals.
Changes:
- Uses exact
BigDecimalrepresentations for integral and decimal operands. - Adds regression coverage for large integers,
BigInteger, and extreme decimal values.
| File | Description |
|---|---|
MultipleOfValidator.java |
Preserves exact divisors and dividends. |
MultipleOfValidatorTest.java |
Adds precision regression tests. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Code review(xhigh · 8 findings) I found 8 issues in PR #1290. The fix works for integer literals, but there are two problems worth raising before merge:
I also flagged an existing slowdown in the same functions that untrusted instance data can trigger: with typeLoose enabled, the string instance "1e5000000" took 3.8 seconds to validate. I ran each of these on the PR branch to get the timings and behavior. I used a temporary worktree and branch, both now removed, and your feat/validation-execution-limits checkout was not touched. |
|
Thanks for the review. Both PRs have been updated (55e08f1 on master, d4a390c on 2.x).
Full |
|
Code review(xhigh · 14 findings) I reviewed PR #1290 again after the updates, and three new problems block merge. Most of the eight items from the last review are fixed, but the new code and the switch to BigDecimal default readers bring in new crashes and a slowdown. The 14 findings are in the review panel; I reproduced the behavior findings on the PR branch and compared them with master. Blocking:
Compatibility costs of the new default readers:
With a user-supplied mapper: a positive divisor like 1e-400 rounds to 0.0 and is now rejected as "multipleOf must be greater than zero". Master ignored it. The rest are an error in type-loose mode that predates this PR, a few cleanups, and missing tests. I removed the temporary worktrees and the pr-1290 branch I created; your checkout wasn't touched. |
Handle extreme numeric scales and trailing-zero inputs without normalization overflow or excessive computation. Preserve exact numeric values in default validation readers while retaining public mapper defaults and compact doubles where lossless. Fix related enum, uniqueness, bounds, and count-limit handling. Preserve custom-mapper behavior and protected validator hooks. Add regression coverage and update the Numeric Precision documentation. Validation: mvn -B verify on JDK 17; 8,647 tests, 30 skipped, 0 failures or errors.
|
Thanks for the reproductions and the detailed review. I have addressed the three merge blockers and added regression coverage. Updates are pushed in c84af35 (master, #1290) and 15cda47 (2.x, #1291).
I also addressed underflow with a user-supplied double-based mapper, protected-method overrides, bounds validation for large numbers, count limits outside the int range, and error messages. The README's Numeric Precision section is updated accordingly. Exact numeric handling is needed beyond Full Performance on JDK 17 (10,000-number arrays): ordinary decimals were 7.5% faster and scientific notation 5.7% faster; integer parsing took 4.2% longer (95% CI +0.9% to +7.5%). Decimals with nine fractional digits averaged 4.9% longer (95% CI −0.3% to +10.0%). Component-isolation measurements point to parser wrapping as the source of the integer overhead in the current exact-reading implementation. Details below. Performance measurements and full test resultsThe baseline is master commit The following measurements cover parsing an array of 10,000 numbers on JDK 17, pinned to logical CPU 0 with
Ordinary decimals and scientific notation improved, while integer parsing showed additional cost. For decimals with nine fractional digits, the observed mean increased, with a confidence interval that includes zero. On 2.x,
Please take another look at the updated changes. |
|
Code review(xhigh · 14 findings) I reviewed the PR owner's latest commit, c84af35 ("Fix numeric edge cases and preserve mapper compatibility"), and reported 14 findings. I checked Jackson's behaviour against the 3.1.1 sources and the actual 3.2.3 classes, but ran no tests. The four that matter most:
The rest are lower priority: a few smaller edge cases, a README line that misstates when zero or negative multipleOf values throw, extra parsing cost for long machine-written doubles (the benchmark only covers integers), and some duplicated or dead code. I also suspected the compact-double shortcut might be wrong on JDK 17 (the library's minimum Java version), but I couldn't test that here. The PR's 10,000-case random test reportedly passes on Java 17, so I left it out. |
|
Thanks for the detailed review. Updated in 1ffd27f, with the 2.x port in #1291 (59c4691).
Full local verify passed: Java 17, 8,740 tests reported / 30 skipped; Java 8 on 2.x, 8,654 / 15 skipped. No failures or errors. The new 93 regressions cover the reviewed behavior and compatibility cases. I also measured parsing arrays of 1,000 values before/after this update, using JMH on one pinned CPU, 2 forks, 3×300 ms warmup and 3×300 ms measurement per fork (microseconds per array):
Java 17 allocation for serialized doubles fell from about 590 KB to 139 KB per array. Java 8's allocation profiler returned implausibly small values, so I am not using those allocation numbers. The short-decimal Java 8 timings have overlapping JMH error ranges; this small local run does not establish a general performance guarantee. |
Fixes #1286.
Preserve exact
multipleOfoperands so a large odd integer such as9007199254740993is rejected as a multiple of 2. Default JSON/YAML validation readers also preserve decimal literals instead of rounding them before validation.The private readers keep a DoubleNode when its decimal value round-trips exactly and use BigDecimal otherwise. Public mapper factories and caller-supplied mapper settings remain unchanged. Numeric type selection also works with location-aware readers. Bounds preserve FloatNode decimal text, and loose numeric strings with large exponents are compared and checked for divisibility without expanding exponent-sized powers. Protected conversion hooks remain honored.
Compatibility details:
multipleOfdivisors raiseSchemaException. Floating-point zero and non-finite divisors retain their ignored behavior, including custom-reader underflow to zero.maxItemsnow uses the same unrestrictive fallback as the other maximum counts. Out-of-range limits retain their original value in errors; minima aboveInteger.MAX_VALUEstill reject a count ofInteger.MAX_VALUE.Validation:
mvn -B -ntp verifypassed on Java 17: 8,740 tests reported, 30 skipped, no failures or errors. The update adds 93 regressions covering bounds, count limits, large exponents, conversion hooks, and JSON/YAML string/stream readers with and without locations.NumericReaderBenchmarkadds parsing workloads alongside the existing integral-validation benchmark.Corresponding PR: #1291.