From 76f320836720635b30896d91493c02c1f9578cca Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 23 Oct 2024 17:27:44 -0700 Subject: [PATCH] runtime: support cgo index into pointer-to-array We were missing a case for calling a C function with an index into a pointer-to-array. Fixes #70016 Change-Id: I9c74d629e58722813c1aaa0f0dc225a5a64d111b Reviewed-on: https://go-review.googlesource.com/c/go/+/621576 Reviewed-by: Keith Randall Reviewed-by: Michael Knyszek LUCI-TryBot-Result: Go LUCI Auto-Submit: Ian Lance Taylor Reviewed-by: Keith Randall --- src/cmd/cgo/internal/testerrors/ptr_test.go | 17 +++++++++++++++++ src/runtime/cgocall.go | 11 +++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/cmd/cgo/internal/testerrors/ptr_test.go b/src/cmd/cgo/internal/testerrors/ptr_test.go index 4f8a0ee583a787..9a8187f55f20f1 100644 --- a/src/cmd/cgo/internal/testerrors/ptr_test.go +++ b/src/cmd/cgo/internal/testerrors/ptr_test.go @@ -472,6 +472,23 @@ var ptrTests = []ptrTest{ body: `s := struct { a [4]byte; p *int }{p: new(int)}; C.f43(unsafe.Pointer(unsafe.SliceData(s.a[:])))`, fail: false, }, + { + // Passing the address of an element of a pointer-to-array. + name: "arraypointer", + c: `void f44(void* p) {}`, + imports: []string{"unsafe"}, + body: `a := new([10]byte); C.f44(unsafe.Pointer(&a[0]))`, + fail: false, + }, + { + // Passing the address of an element of a pointer-to-array + // that contains a Go pointer. + name: "arraypointer2", + c: `void f45(void** p) {}`, + imports: []string{"unsafe"}, + body: `i := 0; a := &[2]unsafe.Pointer{nil, unsafe.Pointer(&i)}; C.f45(&a[0])`, + fail: true, + }, } func TestPointerChecks(t *testing.T) { diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go index 54ce0e8dfca470..18a10041182356 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -563,6 +563,17 @@ func cgoCheckPointer(ptr any, arg any) { ep = aep t = ep._type top = false + case abi.Pointer: + // The Go code is indexing into a pointer to an array, + // and we have been passed the pointer-to-array. + // Check the array rather than the pointer. + pt := (*abi.PtrType)(unsafe.Pointer(aep._type)) + t = pt.Elem + if t.Kind_&abi.KindMask != abi.Array { + throw("can't happen") + } + ep = aep + top = false default: throw("can't happen") }