-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
What version of Go are you using (go version
)?
$ go version go version go1.14.4 linux/amd64
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (go env
)?
go env
Output
$ go envGOARCH="amd64"
GOHOSTARCH="amd64"
GOHOSTOS="linux"
What did you do?
I was deserialising binary data and I hit an unexpected io.EOF
when reading zero bytes. Here is a minimal example that illustrates the problem.
package main
import (
"fmt"
"bytes"
"encoding/binary"
)
func main() {
r := bytes.NewReader([]byte{0,0,0,0})
var length uint32
err := binary.Read(r, binary.BigEndian, &length)
if err != nil{
panic(err)
}
fmt.Printf("length = %d\n", length)
rest := make([]byte, length)
_, err = r.Read(rest)
fmt.Printf("error = %s\n", err)
}
What did you expect to see?
length = 0
error = %!s(<nil>)
What did you see instead?
length = 0
error = EOF
On conformity with io.Reader and other standards
An excerpt from the documentation of io.Reader with the important parts emboldened:
type Reader interface {
Read(p []byte) (n int, err error)
}
Implementations of Read are discouraged from returning a zero byte count
with a nil error, except when len(p) == 0. Callers should treat a return of
0 and nil as indicating that nothing happened; in particular it does not
indicate EOF.
An excerpt from the man page of read(3):
This volume of IEEE Std 1003.1-2001 requires that no action be taken for read() or write() when nbyte is zero. This is not intended to take precedence over detection of errors (such as invalid buffer pointers or file descriptors). This is consistent with the rest of this volume of IEEE Std 1003.1-2001, but the phrasing here could be misread to require detection of the zero case before any other errors. A value of zero is to be considered a correct value, for which the semantics are a no-op.
Related issues
It looks like this issue is in stark contrast to Go2 proposal issue #27531.
There is also an interesting discussion (#5310) about returning (0, nil) from a Read(p []byte).