-
Notifications
You must be signed in to change notification settings - Fork 18k
reflect: Value.Interface "panic: bad indir" after go1.15.4+ #45451
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Does your program work with the 1.15.3 release? Or, which releases does your program work with? What is the |
@ianlancetaylor Yes, 1.15.3 was the last release that worked. In that version, in the switch statement, default:
// Value is direct, and so is the interface.
e.word = v.ptr In v1.16.3,
It's coming from the GEOS library, and I think it's being created somewhere in preprocessing, so as such I'm not sure exactly what it looks like. What I can do is provide steps to reproduce this: This example requires the sudo apt install -y libgeos-dev Sample application: package main
/*
#include "geos_c.h"
*/
import "C"
import (
"fmt"
"reflect"
)
func main() {
var geom *C.GEOSGeometry
t := reflect.ValueOf(geom).Type().Elem()
v := reflect.New(t)
fmt.Println("v.CanInterface(): ", v.CanInterface())
v.Interface() // Panics in 1.15.4+
} The program completes successfully when compiled with go1.15.3 and panics with go1.15.4+. go version
go version go1.15.3 linux/amd64
go run main ; echo EXITED $?
v.CanInterface(): true
EXITED 0
--
go version
go version go1.15.4 linux/amd64
go run main ; echo EXITED $?
v.CanInterface(): true
panic: bad indir
goroutine 1 [running]:
reflect.packEface(0x4a2aa0, 0x588650, 0x16, 0x0, 0x0)
/usr/local/go/src/reflect/value.go:113 +0xed
reflect.valueInterface(0x4a2aa0, 0x588650, 0x16, 0x1, 0x2, 0x18)
/usr/local/go/src/reflect/value.go:1046 +0xe9
reflect.Value.Interface(...)
/usr/local/go/src/reflect/value.go:1016
main.main()
/home/user/src/main/main.go:17 +0x1bb
exit status 2
EXITED 1
--
go version
go version go1.16.3 linux/amd64
go run main ; echo EXITED $?
v.CanInterface(): true
panic: bad indir
goroutine 1 [running]:
reflect.packEface(0x4a0a40, 0x57c660, 0x16, 0x0, 0x18)
/usr/local/go/src/reflect/value.go:113 +0xed
reflect.valueInterface(0x4a0a40, 0x57c660, 0x16, 0x1, 0x2, 0x18)
/usr/local/go/src/reflect/value.go:1046 +0xe9
reflect.Value.Interface(...)
/usr/local/go/src/reflect/value.go:1016
main.main()
/home/user/src/main/main.go:17 +0x1bb
exit status 2
EXITED 1 @ianlancetaylor let me know if there's anything else I can provide. Thanks |
I believe this is due to the
Did this ever work? It used to compile, probably, but did the thing you allocated here actually work correctly? Try printing I think there is something to fix here, though. The allocation shouldn't succeed - we should fail there, instead of a random later spot. |
Standalone repro:
Fails from 1.15.4 through tip. |
Note that if you add
I think it is just the reflect allocation path that isn't being checked (because the error above comes from the compiler - we probably need a runtime check in reflect). |
Thanks. I think this was caused by the fix for #42076. Here is a standalone test case: package main
// typedef struct unknown u;
import "C"
import "reflect"
func main() {
var u *C.u
t := reflect.ValueOf(u).Type().Elem()
v := reflect.New(t)
v.Interface()
} I have a patch. CC @randall77 I want to note that your example code is very unlikely to do what you want. Presumably the real code is different. This code is allocating a struct value, where the struct type is left undefined in the C header file and as such is not visible to Go. The effect is going to be to allocate a zero-typed struct, which is almost certainly not the C definition. Using this struct for anything, such as passing it to C, is quite likely to fail. It's basically the equivalent of writing, in C, "GEOSGeometry g;", for which the C compiler will give an error Because this code is unlikely to work correctly, it's not clear to me whether we should backport the fix or not. Can you say more about how your code uses the value created by |
Change https://golang.org/cl/308970 mentions this issue: |
@randall77 Sorry for the overlapping messages, for some reason I didn't see your comments. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
I'm using a C Library called GEOS which provides a C-backed implementation for handling Geometric operations. A struct containing this C type was used during some reflection operations, but upon upgrading to Go v1.15.4 (Or any version after, including latest) this results in a panic.
I've isolated the problem, and it appears that when using a reflect
Type
to create a new reflectValue
, a subsequent call ofInterface()
results in the panic: bad indir:What did you expect to see?
No code within the underlying C library nor the use of the reflection changed, only the output of
Interface()
. I'd have expected to see the value being returned the same as before the update.What did you see instead?
panic: bad indir
This is coming from
func packEface
insidereflect/value.go
where the following occurs:Note: Here
v.flag
resolves to 22 (flagIndir
is 128)The text was updated successfully, but these errors were encountered: