mirror of
https://github.com/golang/go
synced 2024-11-24 04:40:24 -07:00
image/gif: accept an out-of-bounds transparent color index.
This is an error according to the spec, but Firefox and Google Chrome seem OK with this. Fixes #15059. Change-Id: I841cf44e96655e91a2481555f38fbd7055a32202 Reviewed-on: https://go-review.googlesource.com/22546 Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
parent
ac0ee77d63
commit
4618dd8704
@ -178,12 +178,25 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
|
||||
}
|
||||
m.Palette = d.globalColorTable
|
||||
}
|
||||
if d.hasTransparentIndex && int(d.transparentIndex) < len(m.Palette) {
|
||||
if d.hasTransparentIndex {
|
||||
if !useLocalColorTable {
|
||||
// Clone the global color table.
|
||||
m.Palette = append(color.Palette(nil), d.globalColorTable...)
|
||||
}
|
||||
m.Palette[d.transparentIndex] = color.RGBA{}
|
||||
if ti := int(d.transparentIndex); ti < len(m.Palette) {
|
||||
m.Palette[ti] = color.RGBA{}
|
||||
} else {
|
||||
// The transparentIndex is out of range, which is an error
|
||||
// according to the spec, but Firefox and Google Chrome
|
||||
// seem OK with this, so we enlarge the palette with
|
||||
// transparent colors. See golang.org/issue/15059.
|
||||
p := make(color.Palette, ti+1)
|
||||
copy(p, m.Palette)
|
||||
for i := len(m.Palette); i < len(p); i++ {
|
||||
p[i] = color.RGBA{}
|
||||
}
|
||||
m.Palette = p
|
||||
}
|
||||
}
|
||||
litWidth, err := d.r.ReadByte()
|
||||
if err != nil {
|
||||
|
@ -22,12 +22,16 @@ const (
|
||||
trailerStr = "\x3b"
|
||||
)
|
||||
|
||||
// lzwEncode returns an LZW encoding (with 2-bit literals) of n zeroes.
|
||||
func lzwEncode(n int) []byte {
|
||||
// lzwEncode returns an LZW encoding (with 2-bit literals) of in.
|
||||
func lzwEncode(in []byte) []byte {
|
||||
b := &bytes.Buffer{}
|
||||
w := lzw.NewWriter(b, lzw.LSB, 2)
|
||||
w.Write(make([]byte, n))
|
||||
w.Close()
|
||||
if _, err := w.Write(in); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := w.Close(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
@ -53,7 +57,7 @@ func TestDecode(t *testing.T) {
|
||||
// byte, and 2-bit LZW literals.
|
||||
b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02")
|
||||
if tc.nPix > 0 {
|
||||
enc := lzwEncode(tc.nPix)
|
||||
enc := lzwEncode(make([]byte, tc.nPix))
|
||||
if len(enc) > 0xff {
|
||||
t.Errorf("nPix=%d, extra=%t: compressed length %d is too large", tc.nPix, tc.extra, len(enc))
|
||||
continue
|
||||
@ -103,7 +107,7 @@ func TestTransparentIndex(t *testing.T) {
|
||||
}
|
||||
// Write an image with bounds 2x1, as per TestDecode.
|
||||
b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02")
|
||||
enc := lzwEncode(2)
|
||||
enc := lzwEncode([]byte{0x00, 0x00})
|
||||
if len(enc) > 0xff {
|
||||
t.Fatalf("compressed length %d is too large", len(enc))
|
||||
}
|
||||
@ -196,21 +200,13 @@ func TestNoPalette(t *testing.T) {
|
||||
b.WriteString(headerStr[:len(headerStr)-3])
|
||||
b.WriteString("\x00\x00\x00") // No global palette.
|
||||
|
||||
// Image descriptor: 2x1, no local palette.
|
||||
// Image descriptor: 2x1, no local palette, and 2-bit LZW literals.
|
||||
b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02")
|
||||
|
||||
// Encode the pixels: neither is in range, because there is no palette.
|
||||
pix := []byte{0, 3}
|
||||
enc := &bytes.Buffer{}
|
||||
w := lzw.NewWriter(enc, lzw.LSB, 2)
|
||||
if _, err := w.Write(pix); err != nil {
|
||||
t.Fatalf("Write: %v", err)
|
||||
}
|
||||
if err := w.Close(); err != nil {
|
||||
t.Fatalf("Close: %v", err)
|
||||
}
|
||||
b.WriteByte(byte(len(enc.Bytes())))
|
||||
b.Write(enc.Bytes())
|
||||
enc := lzwEncode([]byte{0x00, 0x03})
|
||||
b.WriteByte(byte(len(enc)))
|
||||
b.Write(enc)
|
||||
b.WriteByte(0x00) // An empty block signifies the end of the image data.
|
||||
|
||||
b.WriteString(trailerStr)
|
||||
@ -226,21 +222,13 @@ func TestPixelOutsidePaletteRange(t *testing.T) {
|
||||
b.WriteString(headerStr)
|
||||
b.WriteString(paletteStr)
|
||||
|
||||
// Image descriptor: 2x1, no local palette.
|
||||
// Image descriptor: 2x1, no local palette, and 2-bit LZW literals.
|
||||
b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02")
|
||||
|
||||
// Encode the pixels; some pvals trigger the expected error.
|
||||
pix := []byte{pval, pval}
|
||||
enc := &bytes.Buffer{}
|
||||
w := lzw.NewWriter(enc, lzw.LSB, 2)
|
||||
if _, err := w.Write(pix); err != nil {
|
||||
t.Fatalf("Write: %v", err)
|
||||
}
|
||||
if err := w.Close(); err != nil {
|
||||
t.Fatalf("Close: %v", err)
|
||||
}
|
||||
b.WriteByte(byte(len(enc.Bytes())))
|
||||
b.Write(enc.Bytes())
|
||||
enc := lzwEncode([]byte{pval, pval})
|
||||
b.WriteByte(byte(len(enc)))
|
||||
b.Write(enc)
|
||||
b.WriteByte(0x00) // An empty block signifies the end of the image data.
|
||||
|
||||
b.WriteString(trailerStr)
|
||||
@ -254,6 +242,36 @@ func TestPixelOutsidePaletteRange(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransparentPixelOutsidePaletteRange(t *testing.T) {
|
||||
b := &bytes.Buffer{}
|
||||
|
||||
// Manufacture a GIF with a 2 color palette.
|
||||
b.WriteString(headerStr)
|
||||
b.WriteString(paletteStr)
|
||||
|
||||
// Graphic Control Extension: transparency, transparent color index = 3.
|
||||
//
|
||||
// This index, 3, is out of range of the global palette and there is no
|
||||
// local palette in the subsequent image descriptor. This is an error
|
||||
// according to the spec, but Firefox and Google Chrome seem OK with this.
|
||||
//
|
||||
// See golang.org/issue/15059.
|
||||
b.WriteString("\x21\xf9\x04\x01\x00\x00\x03\x00")
|
||||
|
||||
// Image descriptor: 2x1, no local palette, and 2-bit LZW literals.
|
||||
b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02")
|
||||
|
||||
// Encode the pixels.
|
||||
enc := lzwEncode([]byte{0x03, 0x03})
|
||||
b.WriteByte(byte(len(enc)))
|
||||
b.Write(enc)
|
||||
b.WriteByte(0x00) // An empty block signifies the end of the image data.
|
||||
|
||||
b.WriteString(trailerStr)
|
||||
|
||||
try(t, b.Bytes(), "")
|
||||
}
|
||||
|
||||
func TestLoopCount(t *testing.T) {
|
||||
data := []byte("GIF89a000\x00000,0\x00\x00\x00\n\x00" +
|
||||
"\n\x00\x80000000\x02\b\xf01u\xb9\xfdal\x05\x00;")
|
||||
|
Loading…
Reference in New Issue
Block a user