fix(edf): use offset instead of stale slice for MarshalEDF length prefix#257
Merged
halturin merged 2 commits intoergo-services:masterfrom Apr 20, 2026
Merged
Conversation
When MarshalEDF writes enough data to trigger lib.Buffer reallocation (via append), the slice returned by Extend(4) points to freed memory. The 4-byte length prefix is then written to the old backing array, leaving zeros in the new buffer. The decoder reads length=0 and fails with "malformed EDF: end of data". Fix by recording the buffer offset before Extend and indexing into b.B[] after MarshalEDF returns, which always references the current (potentially reallocated) backing array.
Verifies that Encode/Decode roundtrip works correctly when MarshalEDF writes enough data to trigger lib.Buffer reallocation. Uses a small initial buffer capacity (64 bytes) to guarantee reallocation occurs. Without the offset-based fix in register.go, the length prefix is written to a stale slice and the decoder returns zero-length data.
Collaborator
|
Such a great catch 👍. Will take a look closer in a week (on a vacation now), but so far looks good |
halturin
pushed a commit
that referenced
this pull request
Apr 20, 2026
…fix (#257) * fix(edf): use offset instead of stale slice for MarshalEDF length prefix When MarshalEDF writes enough data to trigger lib.Buffer reallocation (via append), the slice returned by Extend(4) points to freed memory. The 4-byte length prefix is then written to the old backing array, leaving zeros in the new buffer. The decoder reads length=0 and fails with "malformed EDF: end of data". Fix by recording the buffer offset before Extend and indexing into b.B[] after MarshalEDF returns, which always references the current (potentially reallocated) backing array. * test(edf): regression test for MarshalEDF buffer reallocation Verifies that Encode/Decode roundtrip works correctly when MarshalEDF writes enough data to trigger lib.Buffer reallocation. Uses a small initial buffer capacity (64 bytes) to guarantee reallocation occurs. Without the offset-based fix in register.go, the length prefix is written to a stale slice and the decoder returns zero-length data.
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.
When a type registered via
RegisterTypeOfimplementsMarshaler, the encoder reserves a 4-byte length prefix viaExtend(4)before callingMarshalEDF. IfMarshalEDFwrites enough data to triggerlib.Bufferreallocation (via append), the slice returned byExtendpoints to the old backing array. The length prefix is then written to freed memory, leaving zeros in the actual buffer. The decoder reads length=0 and fails withmalformed EDF: end of data.The fix records the buffer offset before
Extendand indexes intob.B[]afterMarshalEDFreturns, which always references the current backing array regardless of reallocation.