gc: more cleanup
 * disallow surrogate pair runes.
 * diagnose impossible type assertions
 * eliminate another static buffer.
 * do not overflow lexbuf.
 * add -u flag to disable package unsafe.

R=ken2
CC=golang-dev
https://golang.org/cl/1619042
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 18e87f0..2cf408e 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -659,6 +659,7 @@
 EXTERN	Biobuf*	bout;
 EXTERN	int	nerrors;
 EXTERN	int	nsyntaxerrors;
+EXTERN	int	safemode;
 EXTERN	char	namebuf[NSYMB];
 EXTERN	char	lexbuf[NSYMB];
 EXTERN	char	debug[256];
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 7f85271..5dc6d78 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -21,6 +21,26 @@
 	EOF		= -1,
 };
 
+void
+usage(void)
+{
+	print("usage: %cg [flags] file.go...\n");
+	print("flags:\n");
+	// -A is allow use of "any" type, for bootstrapping
+	print("  -I DIR search for packages in DIR\n");
+	print("  -d print declarations\n");
+	print("  -e no limit on number of errors printed\n");
+	print("  -f print stack frame structure\n");
+	print("  -h panic on an error\n");
+	print("  -o file specify output file\n");
+	print("  -S print the assembly language\n");
+	print("  -V print the compiler version\n");
+	print("  -u disable package unsafe\n");
+	print("  -w print the parse tree after typing\n");
+	print("  -x print lex tokens\n");
+	exit(0);
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -62,19 +82,24 @@
 		break;
 
 	case 'o':
-		outfile = ARGF();
+		outfile = EARGF(usage());
 		break;
 
 	case 'I':
-		addidir(ARGF());
+		addidir(EARGF(usage()));
 		break;
+	
+	case 'u':
+		safemode = 1;
+		break;
+
 	case 'V':
 		print("%cg version %s\n", thechar, getgoversion());
-		errorexit();
+		exit(0);
 	} ARGEND
 
 	if(argc < 1)
-		goto usage;
+		usage();
 
 	// special flag to detect compilation of package runtime
 	compiling_runtime = debug['+'];
@@ -188,22 +213,6 @@
 	flusherrors();
 	exit(0);
 	return 0;
-
-usage:
-	print("flags:\n");
-	// -A is allow use of "any" type, for bootstrapping
-	print("  -I DIR search for packages in DIR\n");
-	print("  -d print declarations\n");
-	print("  -e no limit on number of errors printed\n");
-	print("  -f print stack frame structure\n");
-	print("  -h panic on an error\n");
-	print("  -o file specify output file\n");
-	print("  -S print the assembly language\n");
-	print("  -V print the compiler version\n");
-	print("  -w print the parse tree after typing\n");
-	print("  -x print lex tokens\n");
-	exit(0);
-	return 0;
 }
 
 int
@@ -336,6 +345,10 @@
 	}
 
 	if(strcmp(f->u.sval->s, "unsafe") == 0) {
+		if(safemode) {
+			yyerror("cannot import package unsafe");
+			errorexit();
+		}
 		importpkg = mkpkg(f->u.sval);
 		cannedimports("unsafe.6", unsafeimport);
 		return;
@@ -461,7 +474,7 @@
 {
 	int c, c1, clen, escflag, ncp;
 	vlong v;
-	char *cp;
+	char *cp, *ep;
 	Rune rune;
 	Sym *s;
 	static Loophack *lstk;
@@ -485,11 +498,13 @@
 	if(c >= Runeself) {
 		/* all multibyte runes are alpha */
 		cp = lexbuf;
+		ep = lexbuf+sizeof lexbuf;
 		goto talph;
 	}
 
 	if(isalpha(c)) {
 		cp = lexbuf;
+		ep = lexbuf+sizeof lexbuf;
 		goto talph;
 	}
 
@@ -504,12 +519,14 @@
 
 	case '_':
 		cp = lexbuf;
+		ep = lexbuf+sizeof lexbuf;
 		goto talph;
 
 	case '.':
 		c1 = getc();
 		if(isdigit(c1)) {
 			cp = lexbuf;
+			ep = lexbuf+sizeof lexbuf;
 			*cp++ = c;
 			c = c1;
 			c1 = 0;
@@ -862,6 +879,10 @@
 	 * prefix has been stored
 	 */
 	for(;;) {
+		if(cp+10 >= ep) {
+			yyerror("identifier too long");
+			errorexit();
+		}
 		if(c >= Runeself) {
 			ungetc(c);
 			rune = getr();
@@ -898,8 +919,13 @@
 tnum:
 	c1 = 0;
 	cp = lexbuf;
+	ep = lexbuf+sizeof lexbuf;
 	if(c != '0') {
 		for(;;) {
+			if(cp+10 >= ep) {
+				yyerror("identifier too long");
+				errorexit();
+			}
 			*cp++ = c;
 			c = getc();
 			if(isdigit(c))
@@ -911,6 +937,10 @@
 	c = getc();
 	if(c == 'x' || c == 'X') {
 		for(;;) {
+			if(cp+10 >= ep) {
+				yyerror("identifier too long");
+				errorexit();
+			}
 			*cp++ = c;
 			c = getc();
 			if(isdigit(c))
@@ -930,6 +960,10 @@
 
 	c1 = 0;
 	for(;;) {
+		if(cp+10 >= ep) {
+			yyerror("identifier too long");
+			errorexit();
+		}
 		if(!isdigit(c))
 			break;
 		if(c < '0' || c > '7')
@@ -973,6 +1007,10 @@
 
 casedot:
 	for(;;) {
+		if(cp+10 >= ep) {
+			yyerror("identifier too long");
+			errorexit();
+		}
 		*cp++ = c;
 		c = getc();
 		if(!isdigit(c))
@@ -993,6 +1031,10 @@
 	if(!isdigit(c))
 		yyerror("malformed fp constant exponent");
 	while(isdigit(c)) {
+		if(cp+10 >= ep) {
+			yyerror("identifier too long");
+			errorexit();
+		}
 		*cp++ = c;
 		c = getc();
 	}
@@ -1010,6 +1052,10 @@
 	if(!isdigit(c))
 		yyerror("malformed fp constant exponent");
 	while(isdigit(c)) {
+		if(cp+10 >= ep) {
+			yyerror("identifier too long");
+			errorexit();
+		}
 		*cp++ = c;
 		c = getc();
 	}
@@ -1254,7 +1300,7 @@
 		ungetc(c);
 		break;
 	}
-	if(u && l > Runemax) {
+	if(u && (l > Runemax || (0xd800 <= l && l < 0xe000))) {
 		yyerror("invalid Unicode code point in escape sequence: %#llx", l);
 		l = Runeerror;
 	}
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 96d0361..649b8f5 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -877,7 +877,6 @@
 int
 Lconv(Fmt *fp)
 {
-	char str[STRINGSZ], s[STRINGSZ];
 	struct
 	{
 		Hist*	incl;	/* start of this include file */
@@ -917,29 +916,25 @@
 	if(n > HISTSZ)
 		n = HISTSZ;
 
-	str[0] = 0;
 	for(i=n-1; i>=0; i--) {
 		if(i != n-1) {
 			if(fp->flags & ~(FmtWidth|FmtPrec))
 				break;
-			strcat(str, " ");
+			fmtprint(fp, " ");
 		}
 		if(a[i].line)
-			snprint(s, STRINGSZ, "%s:%ld[%s:%ld]",
+			fmtprint(fp, "%s:%ld[%s:%ld]",
 				a[i].line->name, lno-a[i].ldel+1,
 				a[i].incl->name, lno-a[i].idel+1);
 		else
-			snprint(s, STRINGSZ, "%s:%ld",
+			fmtprint(fp, "%s:%ld",
 				a[i].incl->name, lno-a[i].idel+1);
-		if(strlen(s)+strlen(str) >= STRINGSZ-10)
-			break;
-		strcat(str, s);
 		lno = a[i].incl->line - 1;	/* now print out start of this file */
 	}
 	if(n == 0)
-		strcat(str, "<epoch>");
+		fmtprint(fp, "<epoch>");
 
-	return fmtstrcpy(fp, str);
+	return 0;
 }
 
 /*
@@ -1135,10 +1130,10 @@
 	Type *t1;
 	Sym *s;
 	
-	if(debug['U']) {
-		debug['U'] = 0;
+	if(debug['r']) {
+		debug['r'] = 0;
 		fmtprint(fp, "%T (orig=%T)", t, t->orig);
-		debug['U'] = 1;
+		debug['r'] = 1;
 		return 0;
 	}
 
@@ -1871,6 +1866,11 @@
 	if(why != nil)
 		*why = "";
 
+	if(safemode && (isptrto(src, TANY) || isptrto(dst, TANY))) {
+		yyerror("cannot use unsafe.Pointer");
+		errorexit();
+	}
+
 	if(src == dst)
 		return OCONVNOP;
 	if(src == T || dst == T || src->etype == TFORW || dst->etype == TFORW || src->orig == T || dst->orig == T)
@@ -1894,7 +1894,8 @@
 				*why = smprint(": %T is pointer to interface, not interface", src);
 			else if(have)
 				*why = smprint(": %T does not implement %T (wrong type for %S method)\n"
-					"\thave %T\n\twant %T", src, dst, missing->sym, have->type, missing->type);
+					"\thave %S%hhT\n\twant %S%hhT", src, dst, missing->sym,
+					have->sym, have->type, missing->sym, missing->type);
 			else
 				*why = smprint(": %T does not implement %T (missing %S method)",
 					src, dst, missing->sym);
@@ -2031,7 +2032,6 @@
 	// 9. src is unsafe.Pointer and dst is a pointer or uintptr.
 	if(isptrto(src, TANY) && (isptr[dst->etype] || dst->etype == TUINTPTR))
 		return OCONVNOP;
-		
 
 	return 0;
 }
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index d285ad0..592166c 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -52,7 +52,7 @@
 	Node *n, *l, *r;
 	NodeList *args;
 	int lno, ok, ntop;
-	Type *t;
+	Type *t, *missing, *have;
 	Sym *sym;
 	Val v;
 	char *why;
@@ -521,6 +521,18 @@
 			if(n->type == T)
 				goto error;
 		}
+		if(n->type != T && n->type->etype != TINTER)
+		if(!implements(n->type, t, &missing, &have)) {
+			if(have)
+				yyerror("impossible type assertion: %+N cannot have dynamic type %T"
+					" (wrong type for %S method)\n\thave %S%hhT\n\twant %S%hhT",
+					l, n->type, missing->sym, have->sym, have->type,
+					missing->sym, missing->type);
+			else
+				yyerror("impossible type assertion: %+N cannot have dynamic type %T"
+					" (missing %S method)", l, n->type, missing->sym);
+			goto error;
+		}
 		goto ret;
 
 	case OINDEX:
@@ -1179,6 +1191,8 @@
 			checkwidth(t);
 		}
 	}
+	if(safemode && isptrto(t, TANY))
+		yyerror("cannot use unsafe.Pointer");
 
 	evconst(n);
 	if(n->op == OTYPE && !(top & Etype)) {
diff --git a/src/cmd/gc/unsafe.c b/src/cmd/gc/unsafe.c
index 423fc08..dbf6f70 100644
--- a/src/cmd/gc/unsafe.c
+++ b/src/cmd/gc/unsafe.c
@@ -19,7 +19,7 @@
 	long v;
 	Val val;
 
-	if(fn == N || fn->op != ONAME || (s = fn->sym) == S)
+	if(safemode || fn == N || fn->op != ONAME || (s = fn->sym) == S)
 		goto no;
 	if(s->pkg != unsafepkg)
 		goto no;
diff --git a/test/interface/explicit.go b/test/interface/explicit.go
index 797cec8..120135c 100644
--- a/test/interface/explicit.go
+++ b/test/interface/explicit.go
@@ -1,4 +1,4 @@
-// errchk $G $D/$F.go
+// errchk $G -e $D/$F.go
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -50,3 +50,22 @@
 	e = E(t) // ok
 	t = T(e) // ERROR "need explicit|need type assertion|incompatible"
 }
+
+type M interface { M() }
+var m M
+
+var _ = m.(int)	// ERROR "impossible type assertion"
+
+type Int int
+func (Int) M(float) {}
+
+var _ = m.(Int)	// ERROR "impossible type assertion"
+
+var ii int
+var jj Int
+
+var m1 M = ii	// ERROR "missing"
+var m2 M = jj	// ERROR "wrong type for M method"
+
+var m3 = M(ii)	// ERROR "missing"
+var m4 = M(jj)	// ERROR "wrong type for M method"