]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: fix use of nil interface, slice
authorRuss Cox <rsc@golang.org>
Sun, 23 Sep 2012 00:42:11 +0000 (20:42 -0400)
committerRuss Cox <rsc@golang.org>
Sun, 23 Sep 2012 00:42:11 +0000 (20:42 -0400)
Fixes #3670.

R=ken2
CC=golang-dev
https://golang.org/cl/6542058

src/cmd/5g/cgen.c
src/cmd/6g/cgen.c
src/cmd/6g/gsubr.c
src/cmd/8g/cgen.c
src/cmd/8g/gsubr.c
test/fixedbugs/bug444.go

index 4f56cccbd3e0b22481b915f3d8e48bf6f4457952..bb4b8946415c1b6afc6bac4c9bf377846bfb5190 100644 (file)
@@ -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;
index 891d0bab03a7828424531c518c128c37ca88e93a..89d35450e046519a6bc86a7a63b5d27554034fd6 100644 (file)
@@ -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);
index 0b50b4f43e5b68423d63afb69108872836b70a76..ea64b8821d87e01ea2b9edd91b110d7c17521cbb 100644 (file)
@@ -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);
index fb0f441b35248772e8e500e9e4e254b2a6443035..f3990d736bfab1dd07dfc2220de47e50523bc4b7 100644 (file)
@@ -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)
index 4e4261804cc60485af905bc6cb93e950e210b933..dcbd6dbcfaedc6d2d224f7ee10bb548515a7a6b2 100644 (file)
@@ -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);
index 0bbd16faed36780a96d6c4549bc5054df53873b4..b54fb4f5817f32b3c960bdc121229c8bc05715e8 100644 (file)
@@ -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()
 }