Reset cached AppendableByteArray before it is reused - #51156
Open
skdas20 wants to merge 1 commit into
Open
Conversation
AppendableByteArray.reset() was only called from toByteArray(), so an encode that failed part-way left its partial output in the thread-local cached instance. The next value encoded on that thread was then prefixed with it, which in structured logging corrupted the log event following a failed one. Reset the cached instance when it is handed out instead, so the buffer is clean regardless of how the previous use ended. This also covers the early return in toByteArray() for empty content, which returns without resetting. See spring-projectsgh-51154 Signed-off-by: Sumit Kumar Das <skdas5405@gmail.com>
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.
See gh-51154.
AppendableByteArray.reset()is only reached fromtoByteArray():so when
to(appendable)inWritableJson.toByteArray(Charset)throws part-way through, the partially written bytes stay in the instance held by theThreadLocalcache, andget()hands that dirty instance to the next caller on the same thread. In structured logging that means one failed event corrupts the next event into invalid JSON, as reported.This resets the cached instance when it is handed out rather than when it is drained, so the buffer is clean regardless of how the previous use ended. That also covers the early return in
toByteArray():which the alternative (resetting on the failure path in
WritableJson) would not.Tests added:
AppendableByteArrayTests.getWhenPreviousUseWasAbandonedReturnsCleanInstance— covers the cache contract directly: append to an instance, never drain it, then assert the nextget()returns it clean.WritableJsonTests.toByteArrayWhenPreviousWriteFailedDoesNotIncludePartialContent— the reported end-to-end shape: a failed encode followed by an unrelated writer on the same thread.Both fail on
mainand pass with the change.org.springframework.boot.json.*, thelogging.structuredtests, andcheckFormatMain/checkFormatTestare all green locally.I raised the analysis on the issue first and offered either placement — happy to move the reset into
WritableJson.toByteArrayinstead if you'd prefer to keepget()free of side effects, or to close this if you'd rather fix it in-house given it's a regression in recent code.