]> Cypherpunks repositories - gostls13.git/commitdiff
internal/saferio: avoid returning io.EOF from ReadData if data was read
authorJoe Tsai <joetsai@digital-static.net>
Fri, 19 Aug 2022 07:15:53 +0000 (00:15 -0700)
committerGopher Robot <gobot@golang.org>
Mon, 22 Aug 2022 15:01:45 +0000 (15:01 +0000)
ReadData follows the error semantics of io.ReadFull for small sizes,
it should do so as well for large sizes.

Change-Id: I6a11b00d903ac5332e1dda074473790dcf21f32a
Reviewed-on: https://go-review.googlesource.com/c/go/+/424919
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Joseph Tsai <joetsai@digital-static.net>
Run-TryBot: Joseph Tsai <joetsai@digital-static.net>

src/internal/saferio/io.go
src/internal/saferio/io_test.go

index 0361011e95a5eb77fa4615952f95528bbb086961..8fb27b0be3f4ec8684cf81b3cab293e2682eabbb 100644 (file)
@@ -21,6 +21,10 @@ const chunk = 10 << 20 // 10M
 // ReadData reads n bytes from the input stream, but avoids allocating
 // all n bytes if n is large. This avoids crashing the program by
 // allocating all n bytes in cases where n is incorrect.
+//
+// The error is io.EOF only if no bytes were read.
+// If an io.EOF happens after reading some but not all the bytes,
+// ReadData returns io.ErrUnexpectedEOF.
 func ReadData(r io.Reader, n uint64) ([]byte, error) {
        if int64(n) < 0 || n != uint64(int(n)) {
                // n is too large to fit in int, so we can't allocate
@@ -46,6 +50,9 @@ func ReadData(r io.Reader, n uint64) ([]byte, error) {
                }
                _, err := io.ReadFull(r, buf1[:next])
                if err != nil {
+                       if len(buf) > 0 && err == io.EOF {
+                               err = io.ErrUnexpectedEOF
+                       }
                        return nil, err
                }
                buf = append(buf, buf1[:next]...)
index 9214e735c216a6efc2f7bc3534475818ac3093e9..1a7d3e1840bcabeb269ee3e74b8b73af5724d8d9 100644 (file)
@@ -37,6 +37,27 @@ func TestReadData(t *testing.T) {
                        t.Error("large read succeeded unexpectedly")
                }
        })
+
+       t.Run("small-EOF", func(t *testing.T) {
+               _, err := ReadData(bytes.NewReader(nil), chunk-1)
+               if err != io.EOF {
+                       t.Errorf("ReadData = %v, want io.EOF", err)
+               }
+       })
+
+       t.Run("large-EOF", func(t *testing.T) {
+               _, err := ReadData(bytes.NewReader(nil), chunk+1)
+               if err != io.EOF {
+                       t.Errorf("ReadData = %v, want io.EOF", err)
+               }
+       })
+
+       t.Run("large-UnexpectedEOF", func(t *testing.T) {
+               _, err := ReadData(bytes.NewReader(make([]byte, chunk)), chunk+1)
+               if err != io.ErrUnexpectedEOF {
+                       t.Errorf("ReadData = %v, want io.ErrUnexpectedEOF", err)
+               }
+       })
 }
 
 func TestReadDataAt(t *testing.T) {