golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.16k stars 17.69k forks source link

fmt: Scanf EOF error inconsistency #16563

Open fjl opened 8 years ago

fjl commented 8 years ago

Please answer these questions before submitting your issue. Thanks!

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

go version devel +ff227b8 Thu Jul 21 01:04:22 2016 +0000 linux/amd64 but older versions of Go are also affected.

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN="/home/fjl/bin"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/fjl/"
GORACE=""
GOROOT="/usr/lib/go"
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build153025883=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"

What did you do?

I use fmt.Sscanf to parse integers and big integers.

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

What did you expect to see?

When there is not enough input Sscanf (and Fscanf, Scanf) should return io.ErrUnexpectedEOF

What did you see instead?

It returns io.ErrUnexpectedEOF for big.Int and io.EOF for uint.

2opremio commented 7 years ago

Similarly, Scanf is inconsistent when providing a prefix in the format

// results in io.EOF error
_, err = fmt.Sscanf("", "%d\n", &foo)
// results in io.ErrUnexpectedEOF
_, err := fmt.Sscanf("", "prefix %d\n", &foo)

I also expect io.EOF in the latter

https://play.golang.org/p/fNU3lL-KWn

(Happy to create a different issue if you want to treat this separately)

bradfitz commented 7 years ago

@robpike, opinions here? Go 1.9, document, do nothing, punt to 1.10?

robpike commented 7 years ago

Punt to 1.10. Also @rsc was the last one to work on that code, although the problems could well be original. Scanf should never have been written. Mea culpa.

agnivade commented 7 years ago

Hi,

If anyone is not working on this, may I take this up ?

Also, a question on approaching this - If the appropriate behavior is to return ErrUnexpectedEOF in cases like the ones above, in which cases should we return EOF ?

As far as I understand, EOF is not exactly an error per se. It just signifies that the input has ended. If that is the case, then I believe in all cases where we return EOF, it should be ErrUnexpectedEOF. Let me know what you guys think.

robpike commented 7 years ago

It's trivial. Line 90 returns EOF, reading from a string. Line 928 converts an EOF from an external scanner (here math/big) into ErrUnexpectedEOF. It's inconsistent, yes. Will it break anything to make that change? I don't know. Does it matter? Not really.

It's really not worth fixing. The Scan part of fmt is poorly designed and I would prefer to leave it alone. It's not a good idea to use it. Scan[f] is an idea borrowed from C that's really not a good fit for the Go library.

Perhaps the documentation should be more discouraging.

rsc commented 7 years ago

I still intend to look at this to see if there's a clear fix. The problem is the deciding, not the code.

agnivade commented 7 years ago

Sure, let me know what you guys decide. Would be happy to send a CL and reap some commit karma 😝

almas1992 commented 1 year ago

I also expect io.EOF error

func main() {
    var str string
    n, err := fmt.Sscanf("some (thing)", "some (%s)", &str)
    fmt.Println(n, err) // 1 unexpected EOF
    fmt.Println(str)    // thing)
}