Commit 05ac3008 authored by Russ Cox's avatar Russ Cox

cmd/gc: fix use of nil interface, slice

Fixes #3670.

R=ken2
CC=golang-dev
https://golang.org/cl/6542058
parent b51ad9cf
...@@ -554,6 +554,21 @@ agen(Node *n, Node *res) ...@@ -554,6 +554,21 @@ agen(Node *n, Node *res)
while(n->op == OCONVNOP) while(n->op == OCONVNOP)
n = n->left; 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) { if(n->addable) {
memset(&n1, 0, sizeof n1); memset(&n1, 0, sizeof n1);
n1.op = OADDR; n1.op = OADDR;
......
...@@ -518,6 +518,20 @@ agen(Node *n, Node *res) ...@@ -518,6 +518,20 @@ agen(Node *n, Node *res)
while(n->op == OCONVNOP) while(n->op == OCONVNOP)
n = n->left; 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) { if(n->addable) {
regalloc(&n1, types[tptr], res); regalloc(&n1, types[tptr], res);
gins(ALEAQ, n, &n1); gins(ALEAQ, n, &n1);
......
...@@ -990,6 +990,13 @@ gins(int as, Node *f, Node *t) ...@@ -990,6 +990,13 @@ gins(int as, Node *f, Node *t)
case AMOVSD: case AMOVSD:
if(f != N && t != N && samaddr(f, t)) if(f != N && t != N && samaddr(f, t))
return nil; return nil;
break;
case ALEAQ:
if(f != N && isconst(f, CTNIL)) {
fatal("gins LEAQ nil %T", f->type);
}
break;
} }
memset(&af, 0, sizeof af); memset(&af, 0, sizeof af);
......
...@@ -509,6 +509,20 @@ agen(Node *n, Node *res) ...@@ -509,6 +509,20 @@ agen(Node *n, Node *res)
while(n->op == OCONVNOP) while(n->op == OCONVNOP)
n = n->left; 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 // addressable var is easy
if(n->addable) { if(n->addable) {
if(n->op == OREGISTER) if(n->op == OREGISTER)
......
...@@ -1732,6 +1732,12 @@ gins(int as, Node *f, Node *t) ...@@ -1732,6 +1732,12 @@ gins(int as, Node *f, Node *t)
case AMOVL: case AMOVL:
if(f != N && t != N && samaddr(f, t)) if(f != N && t != N && samaddr(f, t))
return nil; return nil;
break;
case ALEAL:
if(f != N && isconst(f, CTNIL))
fatal("gins LEAQ nil %T", f->type);
break;
} }
memset(&af, 0, sizeof af); memset(&af, 0, sizeof af);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
// The no-op conversion here used to confuse the compiler // The no-op conversion here used to confuse the compiler
// into doing a load-effective-address of nil. // into doing a load-effective-address of nil.
// See issue 3670.
package main package main
...@@ -13,7 +14,23 @@ import "reflect" ...@@ -13,7 +14,23 @@ import "reflect"
type T interface {} type T interface {}
var x bool
func main() { func main() {
reflect.TypeOf(nil) 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()
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment