Skip to content

fix(go): ensure physical buffer space for unsafe varint fast-paths#3613

Merged
chaokunyang merged 2 commits intoapache:mainfrom
ayush00git:fix/reserve_bytes
Apr 24, 2026
Merged

fix(go): ensure physical buffer space for unsafe varint fast-paths#3613
chaokunyang merged 2 commits intoapache:mainfrom
ayush00git:fix/reserve_bytes

Conversation

@ayush00git
Copy link
Copy Markdown
Contributor

@ayush00git ayush00git commented Apr 24, 2026

Why?

The Go runtime's struct serialization fast-path in struct.go violates the documented contract of UnsafePutVarUint32 and UnsafeReadVarUint32 in buffer.go.

  • UnsafePutVarUint32 documents that the caller must call Reserve(8) (because it performs an 8-byte bulk write for 5-byte varints), but struct.go only calls Reserve(MaxVarintSize), which is 5 for uint32/int32 varint fields.
  • UnsafeReadVarUint32 physically reads 8 bytes, but the fast-path guard in struct.go only checks remaining() >= MaxVarintSize (which can be 5).

What does this PR do?

  • Add +8 byte padding to struct varint reservation and remaining-check guardrails in struct.go. This ensures that the underlying unsafe bulk memory operations (8-byte loads/stores) always stay within the allocated backing array, even when the logical varint size is smaller (e.g., 5 bytes).

  • Includes a regression test in buffer_test.go verifying the physical write width of UnsafePutVarUint32.

Related issues

Closes #3612

AI Contribution Checklist

  • Substantial AI assistance was used in this PR: yes / no
  • If yes, I included a completed AI Contribution Checklist in this PR description and the required AI Usage Disclosure.
  • If yes, my PR description includes the required ai_review summary and screenshot evidence of the final clean AI review results from both fresh reviewers on the current PR diff or current HEAD after the latest code changes.

Does this PR introduce any user-facing change?

  • Does this PR introduce any public API change?
  • Does this PR introduce any binary protocol compatibility change?

Benchmark

@ayush00git ayush00git requested a review from chaokunyang as a code owner April 24, 2026 09:30
@ayush00git
Copy link
Copy Markdown
Contributor Author

@chaokunyang have a look.

Comment thread go/fory/buffer_test.go
// TestUnsafePutVarUint32PhysicalWriteWidth verifies that UnsafePutVarUint32 performs
// an 8-byte physical write for 5-byte varints and that Reserve(8) (as required by
// buffer.go:661) keeps those 8 bytes within the backing array.
func TestUnsafePutVarUint32PhysicalWriteWidth(t *testing.T) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add another test to cover struct.go change

@ayush00git
Copy link
Copy Markdown
Contributor Author

@chaokunyang please have a look.

Copy link
Copy Markdown
Collaborator

@chaokunyang chaokunyang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@chaokunyang chaokunyang merged commit b20311f into apache:main Apr 24, 2026
62 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Go] unsafe Varint fast-path writes/reads more bytes than reserved in struct serializer

2 participants