goffi v0.6.3 - ARM64 FFI Return Safety Fixes


goffi v0.6.3, published on August 1, 2026, fixes an ARM64 HFA return path that crashed under go test -race. The release also corrects a separate compact struct return path that could silently write beyond the intended result size, which is the more consequential risk for services that move data across a Go and C boundary.

The full release notes and downloads are on the GitHub release page.

The visible failure was in handleHFAReturn. That code treated rvalue as (*[4]float64), creating a 32 byte view even when the returned homogeneous floating point aggregate held only two or three elements. The notes cite CGSize and CGPoint as 16 byte examples.

With go test -race, Go pointer checking rejected that conversion because the apparent array crossed an allocation boundary. The resulting error was converted pointer straddles multiple allocations. This made the unsafe memory assumption visible during an instrumented test run instead of allowing the return handler to proceed.

Version v0.6.3 replaces the fixed array cast with writes for each element through unsafe.Add. The handler no longer needs to claim that every destination has room for four float64 values. The change is scoped to the ARM64 return implementation described in issue 67, which was reported from an Apple M1 environment.

For teams running native bindings in web processing or data services, the practical check is direct: keep an ARM64 job that runs go test -race. That is the execution mode named in the release notes, and it exercises the pointer boundary that exposed this defect.

A second ARM64 defect affected struct returns from 9 through 16 bytes. The old path viewed the destination as (*[2]uint64) and wrote a complete eight byte high word. When the structure was smaller than 16 bytes, that final write covered more memory than the result owned.

The release notes describe this as possible silent corruption with packed C structures. Pointer checking could not detect it, so a clean test process was not evidence that the returned bytes were confined to the destination. That distinction matters at an FFI boundary: a visible crash stops processing, while an oversized write can leave later code handling damaged state.

The fix uses copy with the exact number of bytes remaining. It also matches the existing AMD64 pattern, reducing the architecture specific difference in this return path. This is an internal correctness change. The notes list no new flag, configuration key, or caller migration step.

Operators validating the update should include compact C return values at the lower end of the affected range, not only full 16 byte structures. The release makes no broader compatibility claim, so validation should stay focused on ARM64 HFA values and 9 through 16 byte struct results.

Two focused unit tests accompany the HFA correction. TestHandleHFAReturn_Checkptr covers the pointer checking failure, while TestHandleHFAReturn_Float32 exercises HFA returns built from float32 elements. Together they test both the instrumented pointer case and a scalar width that differs from the oversized float64 cast behind the original crash.

The notes do not name a new dedicated test for the 9 through 16 byte struct path. That does not change the fix, but it is useful context when deciding how much local binding coverage to run. A service that depends on packed C structures should keep its own exact size cases in ARM64 CI.

This is a regular release, not a prerelease. There are no stated schema changes or deployment migrations. The useful signal is narrower: unsafe return handling now writes according to the actual element or byte count in two ARM64 paths.