golang/go

plugin: type switches fail with reflect-created types

Open

#24,399 opened on Mar 15, 2018

View on GitHub
 (2 comments) (0 reactions) (0 assignees)Go (19,008 forks)batch import
NeedsFixcompiler/runtimehelp wanted

Repository metrics

Stars
 (133,883 stars)
PR merge metrics
 (No merged PRs in 30d)

Description

cmd/compile generates type hashes using MD5, but package reflect uses FNV-1 when dynamically constructing anonymous types. This causes type switches (which first search on type hash) to misbehave when using package plugin:

$ go build -buildmode=plugin w.go
$ go run x.go
FAIL; got *[8675309]int

$ cat x.go
package main

import (
	"plugin"
	"reflect"
)

func main() {
	v := reflect.New(reflect.ArrayOf(8675309, reflect.TypeOf(0))).Interface()

	p, err := plugin.Open("w.so")
	if err != nil {
		panic(err)
	}
	f, err := p.Lookup("F")
	if err != nil {
		panic(err)
	}
	f.(func(interface{}))(v)
}

$ cat w.go
package main

import "fmt"

func F(x interface{}) {
	switch x.(type) {
	case *[8675309]int:
		fmt.Println("ok")
	default:
		fmt.Printf("FAIL; got %T\n", x)
	}
}

Notably, the failure goes away if the array type is constructed after the plugin.Open call, or if there's an explicit *[8675309]int type in x.go.

/cc @ianlancetaylor @mwhudson @crawshaw

Contributor guide