Skip to content

Commit 84fce98

Browse files
nottiianlancetaylor
authored andcommitted
cmd/cgo: fix check for conversion of ptr to struct field
According to the documentation "When passing a pointer to a field in a struct, the Go memory in question is the memory occupied by the field, not the entire struct.". checkAddr states that this should also work with type conversions, which is implemented in isType. However, ast.StarExpr must be enclosed in ast.ParenExpr according to the go spec (see example below), which is not considered in the checks. Example: // struct Si { int i; int *p; }; void f(struct I *x) {} import "C" type S { p *int i C.struct_Si } func main() { v := &S{new(int)} C.f((*C.struct_I)(&v.i)) // <- panic } This example will cause cgo to emit a cgoCheck that checks the whole struct S instead of just S.i causing the panic "cgo argument has Go pointer to Go pointer". This patch fixes this situation by adding support for ast.ParenExpr to isType and adds a test, that fails without the fix. Fixes #32970. Change-Id: I15ea28c98f839e9fa708859ed107a2e5f1483133 Reviewed-on: https://go-review.googlesource.com/c/go/+/185098 Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 06ef108 commit 84fce98

File tree

2 files changed

+11
-0
lines changed

2 files changed

+11
-0
lines changed

misc/cgo/errors/ptr_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,15 @@ var ptrTests = []ptrTest{
423423
body: `t := reflect.StructOf([]reflect.StructField{{Name: "MyInt38", Type: reflect.TypeOf(MyInt38(0)), Anonymous: true}}); v := reflect.New(t).Elem(); v.Interface().(Getter38).Get()`,
424424
fail: false,
425425
},
426+
{
427+
// Test that a converted address of a struct field results
428+
// in a check for just that field and not the whole struct.
429+
name: "structfieldcast",
430+
c: `struct S40i { int i; int* p; }; void f40(struct S40i* p) {}`,
431+
support: `type S40 struct { p *int; a C.struct_S40i }`,
432+
body: `s := &S40{p: new(int)}; C.f40((*C.struct_S40i)(&s.a))`,
433+
fail: false,
434+
},
426435
}
427436

428437
func TestPointerChecks(t *testing.T) {

src/cmd/cgo/gcc.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,6 +1239,8 @@ func (p *Package) isType(t ast.Expr) bool {
12391239
if strings.HasPrefix(t.Name, "_Ctype_") {
12401240
return true
12411241
}
1242+
case *ast.ParenExpr:
1243+
return p.isType(t.X)
12421244
case *ast.StarExpr:
12431245
return p.isType(t.X)
12441246
case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType,

0 commit comments

Comments
 (0)