From 04923042bd402def7f48663a165d759d1fdbf15d Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 22 Nov 2014 13:55:33 -0500 Subject: [PATCH] image/jpeg: handle Read returning n > 0, err != nil in d.fill Fixes #9127. LGTM=r R=bradfitz, r CC=golang-codereviews, nigeltao https://golang.org/cl/178120043 --- src/image/jpeg/reader.go | 3 +++ src/image/jpeg/reader_test.go | 46 +++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/src/image/jpeg/reader.go b/src/image/jpeg/reader.go index c8fae3cea96..6d8b1d1d036 100644 --- a/src/image/jpeg/reader.go +++ b/src/image/jpeg/reader.go @@ -143,6 +143,9 @@ func (d *decoder) fill() error { // Fill in the rest of the buffer. n, err := d.r.Read(d.bytes.buf[d.bytes.j:]) d.bytes.j += n + if n > 0 { + err = nil + } return err } diff --git a/src/image/jpeg/reader_test.go b/src/image/jpeg/reader_test.go index 93f4adab9dc..4de2e8ee737 100644 --- a/src/image/jpeg/reader_test.go +++ b/src/image/jpeg/reader_test.go @@ -9,6 +9,7 @@ import ( "fmt" "image" "image/color" + "io" "io/ioutil" "math/rand" "os" @@ -88,6 +89,51 @@ func decodeFile(filename string) (image.Image, error) { return Decode(f) } +type eofReader struct { + data []byte // deliver from Read without EOF + dataEOF []byte // then deliver from Read with EOF on last chunk + lenAtEOF int +} + +func (r *eofReader) Read(b []byte) (n int, err error) { + if len(r.data) > 0 { + n = copy(b, r.data) + r.data = r.data[n:] + } else { + n = copy(b, r.dataEOF) + r.dataEOF = r.dataEOF[n:] + if len(r.dataEOF) == 0 { + err = io.EOF + if r.lenAtEOF == -1 { + r.lenAtEOF = n + } + } + } + return +} + +func TestDecodeEOF(t *testing.T) { + // Check that if reader returns final data and EOF at same time, jpeg handles it. + data, err := ioutil.ReadFile("../testdata/video-001.jpeg") + if err != nil { + t.Fatal(err) + } + + n := len(data) + for i := 0; i < n; { + r := &eofReader{data[:n-i], data[n-i:], -1} + _, err := Decode(r) + if err != nil { + t.Errorf("Decode with Read() = %d, EOF: %v", r.lenAtEOF, err) + } + if i == 0 { + i = 1 + } else { + i *= 2 + } + } +} + // check checks that the two pix data are equal, within the given bounds. func check(bounds image.Rectangle, pix0, pix1 []byte, stride0, stride1 int) error { if stride0 <= 0 || stride0%8 != 0 {