summaryrefslogtreecommitdiff
path: root/libgo/go/image/gif/reader.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/image/gif/reader.go')
-rw-r--r--libgo/go/image/gif/reader.go45
1 files changed, 35 insertions, 10 deletions
diff --git a/libgo/go/image/gif/reader.go b/libgo/go/image/gif/reader.go
index e61112817b7..b1335e61259 100644
--- a/libgo/go/image/gif/reader.go
+++ b/libgo/go/image/gif/reader.go
@@ -231,8 +231,8 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
}
return errNotEnough
}
- // Both lzwr and br should be exhausted. Reading from them should
- // yield (0, io.EOF).
+ // In theory, both lzwr and br should be exhausted. Reading from them
+ // should yield (0, io.EOF).
//
// The spec (Appendix F - Compression), says that "An End of
// Information code... must be the last code output by the encoder
@@ -248,11 +248,21 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
}
return errTooMuch
}
- if n, err := br.Read(d.tmp[:1]); n != 0 || err != io.EOF {
+
+ // In practice, some GIFs have an extra byte in the data sub-block
+ // stream, which we ignore. See https://golang.org/issue/16146.
+ for nExtraBytes := 0; ; {
+ n, err := br.Read(d.tmp[:2])
+ nExtraBytes += n
+ if nExtraBytes > 1 {
+ return errTooMuch
+ }
+ if err == io.EOF {
+ break
+ }
if err != nil {
return fmt.Errorf("gif: reading image data: %v", err)
}
- return errTooMuch
}
// Check that the color indexes are inside the palette.
@@ -410,14 +420,29 @@ func (d *decoder) newImageFromDescriptor() (*image.Paletted, error) {
height := int(d.tmp[6]) + int(d.tmp[7])<<8
d.imageFields = d.tmp[8]
- // The GIF89a spec, Section 20 (Image Descriptor) says:
- // "Each image must fit within the boundaries of the Logical
- // Screen, as defined in the Logical Screen Descriptor."
- bounds := image.Rect(left, top, left+width, top+height)
- if bounds != bounds.Intersect(image.Rect(0, 0, d.width, d.height)) {
+ // The GIF89a spec, Section 20 (Image Descriptor) says: "Each image must
+ // fit within the boundaries of the Logical Screen, as defined in the
+ // Logical Screen Descriptor."
+ //
+ // This is conceptually similar to testing
+ // frameBounds := image.Rect(left, top, left+width, top+height)
+ // imageBounds := image.Rect(0, 0, d.width, d.height)
+ // if !frameBounds.In(imageBounds) { etc }
+ // but the semantics of the Go image.Rectangle type is that r.In(s) is true
+ // whenever r is an empty rectangle, even if r.Min.X > s.Max.X. Here, we
+ // want something stricter.
+ //
+ // Note that, by construction, left >= 0 && top >= 0, so we only have to
+ // explicitly compare frameBounds.Max (left+width, top+height) against
+ // imageBounds.Max (d.width, d.height) and not frameBounds.Min (left, top)
+ // against imageBounds.Min (0, 0).
+ if left+width > d.width || top+height > d.height {
return nil, errors.New("gif: frame bounds larger than image bounds")
}
- return image.NewPaletted(bounds, nil), nil
+ return image.NewPaletted(image.Rectangle{
+ Min: image.Point{left, top},
+ Max: image.Point{left + width, top + height},
+ }, nil), nil
}
func (d *decoder) readBlock() (int, error) {