strconv: use Quote to escape the input string for failed conversion errors

This reveals the presence of control and non-printable characters in the
errors returned by the Parse functions.  Also add unit tests for NumError.

R=golang-dev, r, rsc
CC=golang-dev
https://golang.org/cl/7393075
diff --git a/src/pkg/strconv/atof_test.go b/src/pkg/strconv/atof_test.go
index b4f3a6f..ba49332 100644
--- a/src/pkg/strconv/atof_test.go
+++ b/src/pkg/strconv/atof_test.go
@@ -110,6 +110,7 @@
 	{"1e", "0", ErrSyntax},
 	{"1e-", "0", ErrSyntax},
 	{".e-1", "0", ErrSyntax},
+	{"1\x00.2", "0", ErrSyntax},
 
 	// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
 	{"2.2250738585072012e-308", "2.2250738585072014e-308", nil},
diff --git a/src/pkg/strconv/atoi.go b/src/pkg/strconv/atoi.go
index bdd5d71..21c6900 100644
--- a/src/pkg/strconv/atoi.go
+++ b/src/pkg/strconv/atoi.go
@@ -20,7 +20,7 @@
 }
 
 func (e *NumError) Error() string {
-	return "strconv." + e.Func + ": " + `parsing "` + e.Num + `": ` + e.Err.Error()
+	return "strconv." + e.Func + ": " + "parsing " + Quote(e.Num) + ": " + e.Err.Error()
 }
 
 func syntaxError(fn, str string) *NumError {
diff --git a/src/pkg/strconv/atoi_test.go b/src/pkg/strconv/atoi_test.go
index d0e7b61..9407573 100644
--- a/src/pkg/strconv/atoi_test.go
+++ b/src/pkg/strconv/atoi_test.go
@@ -5,6 +5,7 @@
 package strconv_test
 
 import (
+	"errors"
 	"reflect"
 	. "strconv"
 	"testing"
@@ -146,6 +147,16 @@
 	{"-2147483649", -1 << 31, ErrRange},
 }
 
+type numErrorTest struct {
+	num, want string
+}
+
+var numErrorTests = []numErrorTest{
+	{"0", `strconv.ParseFloat: parsing "0": failed`},
+	{"`", "strconv.ParseFloat: parsing \"`\": failed"},
+	{"1\x00.2", `strconv.ParseFloat: parsing "1\x00.2": failed`},
+}
+
 func init() {
 	// The atoi routines return NumErrors wrapping
 	// the error and the string.  Convert the tables above.
@@ -277,6 +288,19 @@
 	}
 }
 
+func TestNumError(t *testing.T) {
+	for _, test := range numErrorTests {
+		err := &NumError{
+			Func: "ParseFloat",
+			Num:  test.num,
+			Err:  errors.New("failed"),
+		}
+		if got := err.Error(); got != test.want {
+			t.Errorf(`(&NumError{"ParseFloat", %q, "failed"}).Error() = %v, want %v`, test.num, got, test.want)
+		}
+	}
+}
+
 func BenchmarkAtoi(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		ParseInt("12345678", 10, 0)