mirror of
https://github.com/golang/go
synced 2024-11-26 23:01:23 -07:00
image/gif: don't panic on large or nil-containing color.Palettes.
Fixes #20249 Change-Id: I5dceaef31de96345f8e6c155e12775dc4cc31bfb Reviewed-on: https://go-review.googlesource.com/42790 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
2eeaba4172
commit
6d9b900a6f
@ -132,7 +132,12 @@ func (e *encoder) writeHeader() {
|
||||
e.buf[1] = e.g.BackgroundIndex
|
||||
e.buf[2] = 0x00 // Pixel Aspect Ratio.
|
||||
e.write(e.buf[:3])
|
||||
e.globalCT = encodeColorTable(e.globalColorTable[:], p, paddedSize)
|
||||
var err error
|
||||
e.globalCT, err = encodeColorTable(e.globalColorTable[:], p, paddedSize)
|
||||
if err != nil && e.err == nil {
|
||||
e.err = err
|
||||
return
|
||||
}
|
||||
e.write(e.globalColorTable[:e.globalCT])
|
||||
} else {
|
||||
// All frames have a local color table, so a global color table
|
||||
@ -149,8 +154,9 @@ func (e *encoder) writeHeader() {
|
||||
e.buf[1] = 0xff // Application Label.
|
||||
e.buf[2] = 0x0b // Block Size.
|
||||
e.write(e.buf[:3])
|
||||
_, e.err = io.WriteString(e.w, "NETSCAPE2.0") // Application Identifier.
|
||||
if e.err != nil {
|
||||
_, err := io.WriteString(e.w, "NETSCAPE2.0") // Application Identifier.
|
||||
if err != nil && e.err == nil {
|
||||
e.err = err
|
||||
return
|
||||
}
|
||||
e.buf[0] = 0x03 // Block Size.
|
||||
@ -161,11 +167,18 @@ func (e *encoder) writeHeader() {
|
||||
}
|
||||
}
|
||||
|
||||
func encodeColorTable(dst []byte, p color.Palette, size int) int {
|
||||
func encodeColorTable(dst []byte, p color.Palette, size int) (int, error) {
|
||||
if uint(size) >= uint(len(log2Lookup)) {
|
||||
return 0, errors.New("gif: cannot encode color table with more than 256 entries")
|
||||
}
|
||||
n := log2Lookup[size]
|
||||
for i := 0; i < n; i++ {
|
||||
if i < len(p) {
|
||||
r, g, b, _ := p[i].RGBA()
|
||||
c := p[i]
|
||||
if c == nil {
|
||||
return 0, errors.New("gif: cannot encode color table with nil entries")
|
||||
}
|
||||
r, g, b, _ := c.RGBA()
|
||||
dst[3*i+0] = uint8(r >> 8)
|
||||
dst[3*i+1] = uint8(g >> 8)
|
||||
dst[3*i+2] = uint8(b >> 8)
|
||||
@ -176,7 +189,7 @@ func encodeColorTable(dst []byte, p color.Palette, size int) int {
|
||||
dst[3*i+2] = 0x00
|
||||
}
|
||||
}
|
||||
return 3 * n
|
||||
return 3 * n, nil
|
||||
}
|
||||
|
||||
func (e *encoder) writeImageBlock(pm *image.Paletted, delay int, disposal byte) {
|
||||
@ -201,6 +214,10 @@ func (e *encoder) writeImageBlock(pm *image.Paletted, delay int, disposal byte)
|
||||
|
||||
transparentIndex := -1
|
||||
for i, c := range pm.Palette {
|
||||
if c == nil {
|
||||
e.err = errors.New("gif: cannot encode color table with nil entries")
|
||||
return
|
||||
}
|
||||
if _, _, _, a := c.RGBA(); a == 0 {
|
||||
transparentIndex = i
|
||||
break
|
||||
@ -235,8 +252,12 @@ func (e *encoder) writeImageBlock(pm *image.Paletted, delay int, disposal byte)
|
||||
e.write(e.buf[:9])
|
||||
|
||||
paddedSize := log2(len(pm.Palette)) // Size of Local Color Table: 2^(1+n).
|
||||
ct := encodeColorTable(e.localColorTable[:], pm.Palette, paddedSize)
|
||||
if ct != e.globalCT || !bytes.Equal(e.globalColorTable[:ct], e.localColorTable[:ct]) {
|
||||
if ct, err := encodeColorTable(e.localColorTable[:], pm.Palette, paddedSize); err != nil {
|
||||
if e.err == nil {
|
||||
e.err = err
|
||||
}
|
||||
return
|
||||
} else if ct != e.globalCT || !bytes.Equal(e.globalColorTable[:ct], e.localColorTable[:ct]) {
|
||||
// Use a local color table.
|
||||
e.writeByte(fColorTable | uint8(paddedSize))
|
||||
e.write(e.localColorTable[:ct])
|
||||
|
@ -438,6 +438,39 @@ func TestEncodePalettes(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeBadPalettes(t *testing.T) {
|
||||
const w, h = 5, 5
|
||||
for _, n := range []int{256, 257} {
|
||||
for _, nilColors := range []bool{false, true} {
|
||||
pal := make(color.Palette, n)
|
||||
if !nilColors {
|
||||
for i := range pal {
|
||||
pal[i] = color.Black
|
||||
}
|
||||
}
|
||||
|
||||
err := EncodeAll(ioutil.Discard, &GIF{
|
||||
Image: []*image.Paletted{
|
||||
image.NewPaletted(image.Rect(0, 0, w, h), pal),
|
||||
},
|
||||
Delay: make([]int, 1),
|
||||
Disposal: make([]byte, 1),
|
||||
Config: image.Config{
|
||||
ColorModel: pal,
|
||||
Width: w,
|
||||
Height: h,
|
||||
},
|
||||
})
|
||||
|
||||
got := err != nil
|
||||
want := n > 256 || nilColors
|
||||
if got != want {
|
||||
t.Errorf("n=%d, nilColors=%t: err != nil: got %t, want %t", n, nilColors, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncode(b *testing.B) {
|
||||
b.StopTimer()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user