go: cmd/link: removing deadcode check for reflect.Value.Call causes miscompilation
This program now panics at master due to CL 228792:
package main
import "reflect"
type foo struct {}
func (foo) X() { println("ok") }
var h = reflect.Type.Method
func main() {
v := reflect.ValueOf(foo{})
m := h(v.Type(), 0)
m.Func.Call([]reflect.Value{v})
}
It should print “ok”.
/cc @cherrymui @bradfitz
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 23 (21 by maintainers)
Yeah, I think so. Thanks.
@cherrymui Thanks for pointing out that example.
Yeah, I don’t think the linker should need to check for Call or CallSlice. I only suggested restoring those checks as a short-term workaround.
I think if we just fix the compiler’s
usemethod
check so that reflect.Type.Method is marked REFLECTMETHOD, we should be in a good state. Do you agree with that assessment?Edit: I do think the linker should / needs to continue checking for reflect.Value.Method.
Okay, I can do that. Thanks!
@cuonglm Oh, right, LongString uses package name, not package path.
No, I don’t think that’s a desirable change. It’s not likely to cause problems in practice, but that can lead to false positives. We always want to identify standard library packages by path, not name.
Observation: Changing
to
causes the test cases to pass, even with CL 228792.
It looks like what’s happening is the ReflectMethod check doesn’t work within package reflect itself. While compiling a package, localpkg.Path will be “”, not it’s actual package path (e.g., “reflect”).
Changing
s.Pkg.Path == "reflect"
tos.Pkg.Path == "reflect" || s.Pkg == localpkg && myimportpath == "reflect"
seems like it might work.This program failed even before CL 228792: