From: Rob Pike Date: Fri, 20 Nov 2015 21:17:32 +0000 (-0800) Subject: fmt: give correct error for % at end of string when scanning X-Git-Tag: go1.6beta1~344 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=29499858bfa616b19c5108510d3cc6c9fa937bcc;p=gostls13.git fmt: give correct error for % at end of string when scanning Previously it said, "bad verb %% for ...", which is not only wrong, it's ironic as the fix is to use %% rather than % at the end of the string. Diagnose the case where a simple % is at EOF. If there's anything after the percent, the error is already good but this CL also puts quotes around the verb designation ('%d' etc.) to make it even clearer, especially when there is a space involved. Fixes #12315. Change-Id: I31d30659965e940d0bd9ce92a475aab3e2369ef0 Reviewed-on: https://go-review.googlesource.com/17150 Reviewed-by: Ian Lance Taylor --- diff --git a/src/fmt/scan.go b/src/fmt/scan.go index 6bd8fd52e0..4618ed4a82 100644 --- a/src/fmt/scan.go +++ b/src/fmt/scan.go @@ -538,7 +538,7 @@ func (s *ss) okVerb(verb rune, okVerbs, typ string) bool { return true } } - s.errorString("bad verb %" + string(verb) + " for " + typ) + s.errorString("bad verb '%" + string(verb) + "' for " + typ) return false } @@ -1078,6 +1078,10 @@ func (s *ss) advance(format string) (i int) { for i < len(format) { fmtc, w := utf8.DecodeRuneInString(format[i:]) if fmtc == '%' { + // % at end of string is an error. + if i+w == len(format) { + s.errorString("missing verb: % at end of format string") + } // %% acts like a real percent nextc, _ := utf8.DecodeRuneInString(format[i+w:]) // will not match % if string is empty if nextc != '%' { @@ -1179,7 +1183,7 @@ func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err erro } if numProcessed >= len(a) { // out of operands - s.errorString("too few operands for format %" + format[i-w:]) + s.errorString("too few operands for format '%" + format[i-w:] + "'") break } arg := a[numProcessed] diff --git a/src/fmt/scan_test.go b/src/fmt/scan_test.go index 1924c02ac6..7ac74dcb4b 100644 --- a/src/fmt/scan_test.go +++ b/src/fmt/scan_test.go @@ -293,6 +293,7 @@ var scanfTests = []ScanfTest{ // Interesting formats {"here is\tthe value:%d", "here is the\tvalue:118\n", &intVal, 118}, {"%% %%:%d", "% %:119\n", &intVal, 119}, + {"%d%%", "42%", &intVal, 42}, // %% at end of string. // Corner cases {"%x", "FFFFFFFF\n", &uint32Val, uint32(0xFFFFFFFF)}, @@ -358,6 +359,8 @@ var multiTests = []ScanfMultiTest{ {"%d %d", "23 18 27", args(&i, &j, &k), args(23, 18), "too many operands"}, {"%c", "\u0100", args(&int8Val), nil, "overflow"}, {"X%d", "10X", args(&intVal), nil, "input does not match format"}, + {"%d%", "42%", args(&intVal), args(42), "missing verb: % at end of format string"}, + {"%d% ", "42%", args(&intVal), args(42), "too few operands for format '% '"}, // Slightly odd error, but correct. // Bad UTF-8: should see every byte. {"%c%c%c", "\xc2X\xc2", args(&r1, &r2, &r3), args(utf8.RuneError, 'X', utf8.RuneError), ""},