cmd/internal/gc: unsafe.Pointer constants may only be converted to uintptr

Fixes #8927.

Change-Id: I638cddd439dd2d4eeef5474118cfcbde0c8a5a43
Reviewed-on: https://go-review.googlesource.com/9632
Run-TryBot: David Chase <drchase@google.com>
Reviewed-by: David Chase <drchase@google.com>
diff --git a/src/cmd/internal/gc/const.go b/src/cmd/internal/gc/const.go
index ad29158..5ec54bd 100644
--- a/src/cmd/internal/gc/const.go
+++ b/src/cmd/internal/gc/const.go
@@ -204,6 +204,9 @@
 		}
 
 	case CTINT, CTRUNE, CTFLT, CTCPLX:
+		if n.Type.Etype == TUNSAFEPTR && t.Etype != TUINTPTR {
+			goto bad
+		}
 		ct := int(n.Val.Ctype)
 		if Isint[et] {
 			switch ct {
@@ -264,8 +267,6 @@
 		defaultlit(&n, nil)
 		*np = n
 	}
-
-	return
 }
 
 func copyval(v Val) Val {
@@ -396,6 +397,11 @@
 		return
 	}
 
+	// Only uintptrs may be converted to unsafe.Pointer, which cannot overflow.
+	if t.Etype == TUNSAFEPTR {
+		return
+	}
+
 	if !doesoverflow(v, t) {
 		return
 	}
diff --git a/test/convlit.go b/test/convlit.go
index 8a6145d..904e1e6 100644
--- a/test/convlit.go
+++ b/test/convlit.go
@@ -9,6 +9,8 @@
 
 package main
 
+import "unsafe"
+
 // explicit conversion of constants
 var x1 = string(1)
 var x2 string = string(1)
@@ -18,6 +20,11 @@
 var x6 = int(1e100)      // ERROR "overflow"
 var x7 = float32(1e1000) // ERROR "overflow"
 
+// unsafe.Pointer can only convert to/from uintptr
+var _ = string(unsafe.Pointer(uintptr(65)))  // ERROR "convert"
+var _ = float64(unsafe.Pointer(uintptr(65))) // ERROR "convert"
+var _ = int(unsafe.Pointer(uintptr(65)))     // ERROR "convert"
+
 // implicit conversions merit scrutiny
 var s string
 var bad1 string = 1  // ERROR "conver|incompatible|invalid|cannot"