]> Cypherpunks repositories - gostls13.git/commitdiff
fmt: give correct error for % at end of string when scanning
authorRob Pike <r@golang.org>
Fri, 20 Nov 2015 21:17:32 +0000 (13:17 -0800)
committerRob Pike <r@golang.org>
Fri, 20 Nov 2015 21:50:54 +0000 (21:50 +0000)
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 <iant@golang.org>
src/fmt/scan.go
src/fmt/scan_test.go

index 6bd8fd52e08c6b3338587690ccafb46f5ff3b8da..4618ed4a827f4ee41e10f7f53fb3796bf161b984 100644 (file)
@@ -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]
index 1924c02ac69a873c4dcf0bc2e47ae35ceb5487ad..7ac74dcb4bd7ce1b22ce050e6ea8609b8b9fbb93 100644 (file)
@@ -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), ""},