mirror of
https://github.com/golang/go
synced 2024-11-05 18:36:08 +00:00
cmd/gc: fix use of nil interface, slice
Fixes #3670. R=ken2 CC=golang-dev https://golang.org/cl/6542058
This commit is contained in:
parent
b51ad9cf45
commit
05ac300830
6 changed files with 74 additions and 1 deletions
|
@ -554,6 +554,21 @@ agen(Node *n, Node *res)
|
|||
while(n->op == OCONVNOP)
|
||||
n = n->left;
|
||||
|
||||
if(isconst(n, CTNIL) && n->type->width > widthptr) {
|
||||
// Use of a nil interface or nil slice.
|
||||
// Create a temporary we can take the address of and read.
|
||||
// The generated code is just going to panic, so it need not
|
||||
// be terribly efficient. See issue 3670.
|
||||
tempname(&n1, n->type);
|
||||
clearfat(&n1);
|
||||
regalloc(&n2, types[tptr], res);
|
||||
gins(ALEAQ, &n1, &n2);
|
||||
gmove(&n2, res);
|
||||
regfree(&n2);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
|
||||
if(n->addable) {
|
||||
memset(&n1, 0, sizeof n1);
|
||||
n1.op = OADDR;
|
||||
|
|
|
@ -518,6 +518,20 @@ agen(Node *n, Node *res)
|
|||
while(n->op == OCONVNOP)
|
||||
n = n->left;
|
||||
|
||||
if(isconst(n, CTNIL) && n->type->width > widthptr) {
|
||||
// Use of a nil interface or nil slice.
|
||||
// Create a temporary we can take the address of and read.
|
||||
// The generated code is just going to panic, so it need not
|
||||
// be terribly efficient. See issue 3670.
|
||||
tempname(&n1, n->type);
|
||||
clearfat(&n1);
|
||||
regalloc(&n2, types[tptr], res);
|
||||
gins(ALEAQ, &n1, &n2);
|
||||
gmove(&n2, res);
|
||||
regfree(&n2);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if(n->addable) {
|
||||
regalloc(&n1, types[tptr], res);
|
||||
gins(ALEAQ, n, &n1);
|
||||
|
|
|
@ -990,6 +990,13 @@ gins(int as, Node *f, Node *t)
|
|||
case AMOVSD:
|
||||
if(f != N && t != N && samaddr(f, t))
|
||||
return nil;
|
||||
break;
|
||||
|
||||
case ALEAQ:
|
||||
if(f != N && isconst(f, CTNIL)) {
|
||||
fatal("gins LEAQ nil %T", f->type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
memset(&af, 0, sizeof af);
|
||||
|
|
|
@ -509,6 +509,20 @@ agen(Node *n, Node *res)
|
|||
while(n->op == OCONVNOP)
|
||||
n = n->left;
|
||||
|
||||
if(isconst(n, CTNIL) && n->type->width > widthptr) {
|
||||
// Use of a nil interface or nil slice.
|
||||
// Create a temporary we can take the address of and read.
|
||||
// The generated code is just going to panic, so it need not
|
||||
// be terribly efficient. See issue 3670.
|
||||
tempname(&n1, n->type);
|
||||
clearfat(&n1);
|
||||
regalloc(&n2, types[tptr], res);
|
||||
gins(ALEAL, &n1, &n2);
|
||||
gmove(&n2, res);
|
||||
regfree(&n2);
|
||||
return;
|
||||
}
|
||||
|
||||
// addressable var is easy
|
||||
if(n->addable) {
|
||||
if(n->op == OREGISTER)
|
||||
|
|
|
@ -1732,6 +1732,12 @@ gins(int as, Node *f, Node *t)
|
|||
case AMOVL:
|
||||
if(f != N && t != N && samaddr(f, t))
|
||||
return nil;
|
||||
break;
|
||||
|
||||
case ALEAL:
|
||||
if(f != N && isconst(f, CTNIL))
|
||||
fatal("gins LEAQ nil %T", f->type);
|
||||
break;
|
||||
}
|
||||
|
||||
memset(&af, 0, sizeof af);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
// The no-op conversion here used to confuse the compiler
|
||||
// into doing a load-effective-address of nil.
|
||||
// See issue 3670.
|
||||
|
||||
package main
|
||||
|
||||
|
@ -13,7 +14,23 @@ import "reflect"
|
|||
|
||||
type T interface {}
|
||||
|
||||
var x bool
|
||||
|
||||
func main() {
|
||||
reflect.TypeOf(nil)
|
||||
reflect.TypeOf(T(nil)) // used to fail
|
||||
reflect.TypeOf(T(nil)) // used to miscompile
|
||||
shouldPanic()
|
||||
}
|
||||
|
||||
func f() byte {
|
||||
return []byte(nil)[0] // used to miscompile
|
||||
}
|
||||
|
||||
func shouldPanic() {
|
||||
defer func() {
|
||||
if recover() == nil {
|
||||
panic("not panicking")
|
||||
}
|
||||
}()
|
||||
f()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue