Commits

Anonymous committed a203e31

cmd/gc: fix use of nil interface, slice

Fixes issue 3670.

R=ken2
CC=golang-dev
http://codereview.appspot.com/6542058

  • Participants
  • Parent commits 5a92a8a

Comments (0)

Files changed (6)

File src/cmd/5g/cgen.c

 	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;

File src/cmd/6g/cgen.c

 	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);

File src/cmd/6g/gsubr.c

 	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);

File src/cmd/8g/cgen.c

 	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)

File src/cmd/8g/gsubr.c

 	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);

File test/fixedbugs/bug444.go

 
 // The no-op conversion here used to confuse the compiler
 // into doing a load-effective-address of nil.
+// See issue 3670.
 
 package main
 
 
 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()
+}