Fix TraceStateBuilder.remove double-counting a repeated removal - #8763
Open
TimurRakhmatullin86 wants to merge 1 commit into
Open
Conversation
ArrayBasedTraceStateBuilder.remove decremented numEntries unconditionally, even when the entry was already a null tombstone from a previous remove of the same key. put() guards the symmetric update with if (currentValue == null); remove() lacked the mirror guard. So removing an already-removed key drove numEntries below the real count and corrupted build(): it either returned empty() and dropped unrelated valid entries, emitted a TraceState with a null value via the size()==2 fast path, or threw ArrayIndexOutOfBoundsException from the undersized entries[] array. The remove javadoc says it removes the entry 'if it is present', so a repeated remove must be a no-op. Only decrement when the entry is still present, and add tests for the three corruption paths. Signed-off-by: Timur Rakhmatullin <174210871+TimurRakhmatullin86@users.noreply.github.com>
Pull request dashboard statusWaiting on reviewers · refreshed 2026-09-02 14:36 UTC Review the latest changes. Also blocked by: Merge conflicts. Status above doesn't look right?
|
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.
Problem
ArrayBasedTraceStateBuilder.remove(key)decrementsnumEntriesunconditionally, even when the key's slot is already anulltombstone from a previousremoveof the same key.put()guards the symmetric update (if (currentValue == null) { numEntries++; });remove()has no mirror guard, so a repeatedremoveof an already-removed key double-decrements the count.Because
build()trustsnumEntries, a repeated removal corrupts the result three different ways:The
removejavadoc says it removes the entry "if it is present", so a secondremoveof a key that is no longer present must be a no-op — the same as removing a key that was never added (whichremoveNotPresentalready covers).Fix
Only account for the removal (set the tombstone and decrement) when the entry is still present, mirroring the guard in
put().Tests
Added three cases in
TraceStateTestfor the data-loss, null-value, andArrayIndexOutOfBoundsExceptionpaths. All three fail against the current code and pass with the fix; the existingTraceStateTestcases stay green.