summaryrefslogtreecommitdiff
path: root/libgo/go/image/gif
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/image/gif')
-rw-r--r--libgo/go/image/gif/reader.go83
-rw-r--r--libgo/go/image/gif/reader_test.go17
2 files changed, 71 insertions, 29 deletions
diff --git a/libgo/go/image/gif/reader.go b/libgo/go/image/gif/reader.go
index 6181a946fad..e61112817b7 100644
--- a/libgo/go/image/gif/reader.go
+++ b/libgo/go/image/gif/reader.go
@@ -63,6 +63,22 @@ const (
eApplication = 0xFF // Application
)
+func readFull(r io.Reader, b []byte) error {
+ _, err := io.ReadFull(r, b)
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return err
+}
+
+func readByte(r io.ByteReader) (byte, error) {
+ b, err := r.ReadByte()
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return b, err
+}
+
// decoder is the type used to decode a GIF file.
type decoder struct {
r reader
@@ -124,7 +140,7 @@ func (b *blockReader) Read(p []byte) (int, error) {
return 0, b.err
}
b.slice = b.tmp[:blockLen]
- if _, b.err = io.ReadFull(b.r, b.slice); b.err != nil {
+ if b.err = readFull(b.r, b.slice); b.err != nil {
return 0, b.err
}
}
@@ -151,9 +167,9 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
}
for {
- c, err := d.r.ReadByte()
+ c, err := readByte(d.r)
if err != nil {
- return err
+ return fmt.Errorf("gif: reading frames: %v", err)
}
switch c {
case sExtension:
@@ -198,9 +214,9 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
m.Palette = p
}
}
- litWidth, err := d.r.ReadByte()
+ litWidth, err := readByte(d.r)
if err != nil {
- return err
+ return fmt.Errorf("gif: reading image data: %v", err)
}
if litWidth < 2 || litWidth > 8 {
return fmt.Errorf("gif: pixel size in decode out of range: %d", litWidth)
@@ -209,9 +225,9 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
br := &blockReader{r: d.r}
lzwr := lzw.NewReader(br, lzw.LSB, int(litWidth))
defer lzwr.Close()
- if _, err = io.ReadFull(lzwr, m.Pix); err != nil {
+ if err = readFull(lzwr, m.Pix); err != nil {
if err != io.ErrUnexpectedEOF {
- return err
+ return fmt.Errorf("gif: reading image data: %v", err)
}
return errNotEnough
}
@@ -228,13 +244,13 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
// See https://golang.org/issue/9856 for an example GIF.
if n, err := lzwr.Read(d.tmp[:1]); n != 0 || (err != io.EOF && err != io.ErrUnexpectedEOF) {
if err != nil {
- return err
+ return fmt.Errorf("gif: reading image data: %v", err)
}
return errTooMuch
}
if n, err := br.Read(d.tmp[:1]); n != 0 || err != io.EOF {
if err != nil {
- return err
+ return fmt.Errorf("gif: reading image data: %v", err)
}
return errTooMuch
}
@@ -264,7 +280,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
case sTrailer:
if len(d.image) == 0 {
- return io.ErrUnexpectedEOF
+ return fmt.Errorf("gif: missing image data")
}
return nil
@@ -275,13 +291,13 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
}
func (d *decoder) readHeaderAndScreenDescriptor() error {
- _, err := io.ReadFull(d.r, d.tmp[:13])
+ err := readFull(d.r, d.tmp[:13])
if err != nil {
- return err
+ return fmt.Errorf("gif: reading header: %v", err)
}
d.vers = string(d.tmp[:6])
if d.vers != "GIF87a" && d.vers != "GIF89a" {
- return fmt.Errorf("gif: can't recognize format %s", d.vers)
+ return fmt.Errorf("gif: can't recognize format %q", d.vers)
}
d.width = int(d.tmp[6]) + int(d.tmp[7])<<8
d.height = int(d.tmp[8]) + int(d.tmp[9])<<8
@@ -298,9 +314,9 @@ func (d *decoder) readHeaderAndScreenDescriptor() error {
func (d *decoder) readColorTable(fields byte) (color.Palette, error) {
n := 1 << (1 + uint(fields&fColorTableBitsMask))
- _, err := io.ReadFull(d.r, d.tmp[:3*n])
+ err := readFull(d.r, d.tmp[:3*n])
if err != nil {
- return nil, fmt.Errorf("gif: short read on color table: %s", err)
+ return nil, fmt.Errorf("gif: reading color table: %s", err)
}
j, p := 0, make(color.Palette, n)
for i := range p {
@@ -311,9 +327,9 @@ func (d *decoder) readColorTable(fields byte) (color.Palette, error) {
}
func (d *decoder) readExtension() error {
- extension, err := d.r.ReadByte()
+ extension, err := readByte(d.r)
if err != nil {
- return err
+ return fmt.Errorf("gif: reading extension: %v", err)
}
size := 0
switch extension {
@@ -324,9 +340,9 @@ func (d *decoder) readExtension() error {
case eComment:
// nothing to do but read the data.
case eApplication:
- b, err := d.r.ReadByte()
+ b, err := readByte(d.r)
if err != nil {
- return err
+ return fmt.Errorf("gif: reading extension: %v", err)
}
// The spec requires size be 11, but Adobe sometimes uses 10.
size = int(b)
@@ -334,8 +350,8 @@ func (d *decoder) readExtension() error {
return fmt.Errorf("gif: unknown extension 0x%.2x", extension)
}
if size > 0 {
- if _, err := io.ReadFull(d.r, d.tmp[:size]); err != nil {
- return err
+ if err := readFull(d.r, d.tmp[:size]); err != nil {
+ return fmt.Errorf("gif: reading extension: %v", err)
}
}
@@ -343,8 +359,11 @@ func (d *decoder) readExtension() error {
// this extension defines a loop count.
if extension == eApplication && string(d.tmp[:size]) == "NETSCAPE2.0" {
n, err := d.readBlock()
- if n == 0 || err != nil {
- return err
+ if err != nil {
+ return fmt.Errorf("gif: reading extension: %v", err)
+ }
+ if n == 0 {
+ return nil
}
if n == 3 && d.tmp[0] == 1 {
d.loopCount = int(d.tmp[1]) | int(d.tmp[2])<<8
@@ -352,14 +371,17 @@ func (d *decoder) readExtension() error {
}
for {
n, err := d.readBlock()
- if n == 0 || err != nil {
- return err
+ if err != nil {
+ return fmt.Errorf("gif: reading extension: %v", err)
+ }
+ if n == 0 {
+ return nil
}
}
}
func (d *decoder) readGraphicControl() error {
- if _, err := io.ReadFull(d.r, d.tmp[:6]); err != nil {
+ if err := readFull(d.r, d.tmp[:6]); err != nil {
return fmt.Errorf("gif: can't read graphic control: %s", err)
}
if d.tmp[0] != 4 {
@@ -379,7 +401,7 @@ func (d *decoder) readGraphicControl() error {
}
func (d *decoder) newImageFromDescriptor() (*image.Paletted, error) {
- if _, err := io.ReadFull(d.r, d.tmp[:9]); err != nil {
+ if err := readFull(d.r, d.tmp[:9]); err != nil {
return nil, fmt.Errorf("gif: can't read image descriptor: %s", err)
}
left := int(d.tmp[0]) + int(d.tmp[1])<<8
@@ -399,11 +421,14 @@ func (d *decoder) newImageFromDescriptor() (*image.Paletted, error) {
}
func (d *decoder) readBlock() (int, error) {
- n, err := d.r.ReadByte()
+ n, err := readByte(d.r)
if n == 0 || err != nil {
return 0, err
}
- return io.ReadFull(d.r, d.tmp[:n])
+ if err := readFull(d.r, d.tmp[:n]); err != nil {
+ return 0, err
+ }
+ return int(n), nil
}
// interlaceScan defines the ordering for a pass of the interlace algorithm.
diff --git a/libgo/go/image/gif/reader_test.go b/libgo/go/image/gif/reader_test.go
index 90c81493cba..1267ba06a9d 100644
--- a/libgo/go/image/gif/reader_test.go
+++ b/libgo/go/image/gif/reader_test.go
@@ -10,6 +10,7 @@ import (
"image"
"image/color"
"reflect"
+ "strings"
"testing"
)
@@ -292,3 +293,19 @@ func TestLoopCount(t *testing.T) {
t.Errorf("loop count mismatch: %d vs %d", img.LoopCount, img1.LoopCount)
}
}
+
+func TestUnexpectedEOF(t *testing.T) {
+ for i := len(testGIF) - 1; i >= 0; i-- {
+ _, err := Decode(bytes.NewReader(testGIF[:i]))
+ if err == errNotEnough {
+ continue
+ }
+ text := ""
+ if err != nil {
+ text = err.Error()
+ }
+ if !strings.HasPrefix(text, "gif:") || !strings.HasSuffix(text, ": unexpected EOF") {
+ t.Errorf("Decode(testGIF[:%d]) = %v, want gif: ...: unexpected EOF", i, err)
+ }
+ }
+}