Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fmt: Scanning '%%' is a verb #34180

Closed
pavel opened this issue Sep 9, 2019 · 5 comments
Closed

fmt: Scanning '%%' is a verb #34180

pavel opened this issue Sep 9, 2019 · 5 comments
Assignees

Comments

@pavel
Copy link

@pavel pavel commented Sep 9, 2019

What version of Go are you using (go version)?

$ go version
go version go1.13 linux/amd64

Does this issue reproduce with the latest release?

Yes

What did you do?

https://play.golang.org/p/PNBiGNussAs

package main

import (
	"fmt"
	"log"
)

func readVersion(f, s string) {
	var major, minor uint8

	_, err := fmt.Sscanf(s, f, &major, &minor)
	if err != nil {
		log.Println("Failed to parse", s, ". Reason:", err)
		return
	}

	log.Println("Parsed", s, "into", major, minor)
}

func main() {
	readVersion("%%VER-%d.%d", "%VER-1.4")
	readVersion("%%VER-%d.%d", "%ER-1.4") // fails: "bad verb '%%' for integer"
	readVersion("VER-%d.%d", "VER-1.4")
	readVersion("VER-%d.%d", "ER-1.4") // fails: "input does not match format"
}

What did you expect to see?

Second run should return input does not match format, just like the call number 4.

What did you see instead?

bad verb '%%' for integer error.

@rusq
Copy link

@rusq rusq commented Sep 10, 2019

Observing the same behaviour for Go 1.8, Go 1.9.5 and Go 1.10.5, not something introduced in 1.13.

34180.go contains the code from the playground mentioned above. https://play.golang.org/p/PNBiGNussAs

$ go1.8 run 34180.go
2019/09/10 22:10:03 Parsed %VER-1.4 into 1 4
2019/09/10 22:10:03 Failed to parse %ER-1.4 . Reason: bad verb '%%' for integer
2019/09/10 22:10:03 Parsed VER-1.4 into 1 4
2019/09/10 22:10:03 Failed to parse ER-1.4 . Reason: input does not match format
@pavel
Copy link
Author

@pavel pavel commented Sep 12, 2019

The logic fails here:

if format[i] != '%' {

This assumes that a scanning problem is signaled when i points to a non % rune, which is not true.
During a line 2 call in the original example, advance function fails to match runes E and V returning -1. At this point state is i = 0, w = -1 and format[i] = '%'. This causes scanning to continue, failing later at integer scanning.

CC @smasher164 Investigation done.

@pavel
Copy link
Author

@pavel pavel commented Sep 12, 2019

Another failing case would be https://play.golang.org/p/itkheUx5t3O

package main

import (
	"fmt"
	"log"
)

func main() {
	var n int
	if _, err := fmt.Sscanf("123 %", "%d%%", &n); err != nil {
		log.Println(err)
	} else {
		log.Println("OK", n)
	}
}

Error returned too few operands for format '%%'.
Expected error to be input does not match format.

@smasher164
Copy link
Member

@smasher164 smasher164 commented Sep 14, 2019

@gopherbot
Copy link

@gopherbot gopherbot commented Oct 24, 2019

Change https://golang.org/cl/202879 mentions this issue: fmt: fix handling of %% verb in Scanf

@gopherbot gopherbot closed this in 4f70c15 Oct 25, 2019
@golang golang locked and limited conversation to collaborators Oct 24, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants
You can’t perform that action at this time.