fix(#4336): use Long.compareUnsigned to detect zigzag overflow for Long.MAX/MIN_VALUE#4361
Conversation
There was a problem hiding this comment.
Code Review
This pull request fixes a bug in Simple8bCodec.encode() where extreme values like Long.MAX_VALUE and Long.MIN_VALUE bypassed validation due to signed comparison of zigzag-encoded values, leading to silent truncation. The fix replaces the signed comparison with Long.compareUnsigned. Tests and documentation were added to verify the fix. The reviewer pointed out a minor discrepancy in the documentation file, which references a test name (extremeNegativeBoundaryStillThrows()) that does not match the actual test name added in the code (nearLongMaxValueThrows()).
| ### `Simple8bCodecTest.java` | ||
| - Added `longMaxValueThrows()` — `Long.MAX_VALUE` must throw `IllegalArgumentException` | ||
| - Added `longMinValueThrows()` — `Long.MIN_VALUE` must throw `IllegalArgumentException` | ||
| - Added `extremeNegativeBoundaryStillThrows()` — values just outside range from below still throw |
There was a problem hiding this comment.
The documentation mentions extremeNegativeBoundaryStillThrows() as being added, but the actual test added in Simple8bCodecTest.java is named nearLongMaxValueThrows(). Please update this line to match the actual test name.
| - Added `extremeNegativeBoundaryStillThrows()` — values just outside range from below still throw | |
| - Added nearLongMaxValueThrows() — values just outside range from above still throw |
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Coverage variation | ✅ -7.75% coverage variation |
| Diff coverage | ✅ 100.00% diff coverage |
Coverage variation details
Coverable lines Covered lines Coverage Common ancestor commit (f2a41f8) 127753 94277 73.80% Head commit (8c31704) 159431 (+31678) 105295 (+11018) 66.04% (-7.75%) Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch:
<coverage of head commit> - <coverage of common ancestor commit>
Diff coverage details
Coverable lines Covered lines Diff coverage Pull request (#4361) 1 1 100.00% Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified:
<covered lines added or modified>/<coverable lines added or modified> * 100%
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
… not extremeNegativeBoundaryStillThrows)
Code ReviewOverviewThis PR fixes a real data-corruption bug in Fix Correctness - Looks GoodThe if (encoded < 0 || encoded > MAX_ZIGZAG_VALUE)This also works because valid zigzag-encoded values (for inputs within the supported range) are always non-negative — a negative Tests - Good Coverage, Minor Wording NitThree focused regression tests are added and they cover the right cases. One minor comment: The Javadoc on There is also a minor inconsistency between the PR description's Changes section (which names the test Production Impact - Worth Calling Out ExplicitlyThe PR body mentions this in the impact analysis section, but it is worth reiterating: nanosecond timestamps in the range No Issues
Summary: The fix is correct and the test coverage is solid. The only actionable items are the wording nit in the |
Code ReviewOverall AssessmentThis is a correct, minimal, and well-reasoned bug fix. The root cause analysis is accurate and the solution is the right tool for the job. A few points worth discussing. The Fix (Simple8bCodec.java) - ApprovedThe one-line change is correct. The arithmetic proof in the PR description is solid:
Both bypass the old signed guard, and Tests - Good coverage with a minor style noteThe three new regression tests ( Minor: The multi-line Javadoc comments in the test methods repeat information already captured in the method names and the PR description. One short line per method would be sufficient per project conventions. Not blocking. Suggestion: Consider adding Documentation file (docs/4336-simple8b-zigzag-validation.md) - Recommend droppingA per-issue markdown file in
The most durable place for this explanation is as a comment on the comparison line in // Unsigned comparison required: zigzagEncode(Long.MAX/MIN_VALUE) returns negative signed values
// that look smaller than MAX_ZIGZAG_VALUE in signed arithmetic but exceed it unsigned.
if (Long.compareUnsigned(encoded, MAX_ZIGZAG_VALUE) > 0)That makes the non-obvious invariant visible to any future reader right at the call site, which is more useful than a detached markdown file. Potential follow-up (not blocking this PR)Any data already written to disk before this fix with SummaryThe core fix is correct and the tests are solid. I would recommend dropping the documentation file (or folding its key insight into a single inline comment on the comparison), and optionally adding |
Code ReviewOverviewThis PR fixes a real data-corruption bug in The Fix (Simple8bCodec.java)The one-line change is correct. Manual verification:
No issues with the production code change. Test Coverage (Simple8bCodecTest.java)The three new tests are sound and consistent with the existing test style ( One minor style note from the project's CLAUDE.md:
The three new test methods each carry a 3-4 line Javadoc block. These should be trimmed to a single-line comment, e.g.: // Regression: zigzagEncode(Long.MAX_VALUE) = -2 (negative signed) bypassed the old > guard.
@Test
void longMaxValueThrows() { ... }Same for Documentation File (docs/4336-simple8b-zigzag-validation.md) - Needs RemovalThis file should not be committed to the repository. It contains:
This is working-document content that belongs in the PR description (where it already lives verbatim) and not in the tracked codebase. Please drop this file before merging. Summary
The core fix is solid. Please remove the docs file and trim the multi-line Javadoc blocks to single lines, then this is ready to merge. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4361 +/- ##
============================================
- Coverage 64.65% 64.36% -0.30%
- Complexity 423 455 +32
============================================
Files 1647 1647
Lines 127753 127753
Branches 27382 27382
============================================
- Hits 82599 82224 -375
- Misses 33507 33958 +451
+ Partials 11647 11571 -76 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Closes #4336
Summary
Simple8bCodec.encode()silently truncated values nearLong.MAX_VALUEandLong.MIN_VALUEinstead of throwingIllegalArgumentException. The root cause:zigzagEncode(Long.MAX_VALUE)returns-2andzigzagEncode(Long.MIN_VALUE)returns-1. Both are negative in signed arithmetic, so the validation guardencoded > MAX_ZIGZAG_VALUE(MAX_ZIGZAG_VALUE = (1L<<60)-1is a large positive) was alwaysfalsefor these inputs — bypassing validation entirely. The encoder then masked with(1L<<60)-1, silently dropping the top 4 bits and storing a wrong value. The fix replaces the signed comparison withLong.compareUnsigned(encoded, MAX_ZIGZAG_VALUE) > 0, which correctly treats the bit-patterns of the negative encoded values as large unsigned integers exceeding the 60-bit limit.Test plan
Simple8bCodecTest.longMaxValueThrows—Long.MAX_VALUEnow correctly throwsIllegalArgumentException(was silently corrupted)Simple8bCodecTest.longMinValueThrows—Long.MIN_VALUEnow correctly throwsIllegalArgumentException(was silently corrupted)Simple8bCodecTest.nearLongMaxValueThrows—Long.MAX_VALUE - 1also correctly rejected (zigzag-encoded bit-pattern also exceeds 60 bits unsigned)Simple8bCodecTesttests still pass, including boundary acceptance (-(2^59)still accepted as it zigzag-encodes to exactlyMAX_ZIGZAG_VALUE)