Skip to content

v0.5.6 — Fix Callback Stack-Move Corruption

Choose a tag to compare

@kolkov kolkov released this 05 Jul 08:57
bbded27

What's Changed

Fixed — Critical: Callback Stack-Move Corruption

When a C callback re-enters Go and the callback's Go code grows the goroutine stack (copystack), syscallArgs on the goroutine stack would move — but syscallN running on g0 still held the old address. Return values were written to freed/recycled memory, causing silent data corruption.

Root cause: The v0.5.4 //go:noescape optimization kept syscallArgs on the goroutine stack. The Go runtime clears syscallsp during callback re-entry (cgocallbackgexitsyscall()), allowing copystack to fire. See Go issues #8771, #11089.

Fix: syscallArgs is now heap-allocated via sync.Pool, immune to goroutine stack moves. Pool reuse gives 0 allocs/op in steady state. The //go:noescape directive has been removed from hot-path runtime_cgocall declarations.

Also in this release

  • sret cleanup — simplified >16B struct return path, removed redundant sretBuf
  • TestCallbackGrowStack — deterministic reproducer for the stack-move bug
  • TestStructReturn24B — end-to-end test for >16B struct return via sret

Thanks to @tie for discovering the bug, writing the reproducer, and contributing the fix!