tiff: don't panic on reading short block data.
Fixes golang/go#10394 Change-Id: I12621650f0c21579047497407ca2745febe4521b Reviewed-on: https://go-review.googlesource.com/9278 Reviewed-by: Benny Siegert <bsiegert@gmail.com> Reviewed-by: Nigel Tao <nigeltao@golang.org>
This commit is contained in:
parent
72a6583050
commit
b2f48f3f51
|
@ -164,9 +164,12 @@ func (d *decoder) parseIFD(p []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// readBits reads n bits from the internal buffer starting at the current offset.
|
// readBits reads n bits from the internal buffer starting at the current offset.
|
||||||
func (d *decoder) readBits(n uint) uint32 {
|
func (d *decoder) readBits(n uint) (v uint32, ok bool) {
|
||||||
for d.nbits < n {
|
for d.nbits < n {
|
||||||
d.v <<= 8
|
d.v <<= 8
|
||||||
|
if d.off >= len(d.buf) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
d.v |= uint32(d.buf[d.off])
|
d.v |= uint32(d.buf[d.off])
|
||||||
d.off++
|
d.off++
|
||||||
d.nbits += 8
|
d.nbits += 8
|
||||||
|
@ -174,7 +177,7 @@ func (d *decoder) readBits(n uint) uint32 {
|
||||||
d.nbits -= n
|
d.nbits -= n
|
||||||
rv := d.v >> d.nbits
|
rv := d.v >> d.nbits
|
||||||
d.v &^= rv << d.nbits
|
d.v &^= rv << d.nbits
|
||||||
return rv
|
return rv, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// flushBits discards the unread bits in the buffer used by readBits.
|
// flushBits discards the unread bits in the buffer used by readBits.
|
||||||
|
@ -203,12 +206,14 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
|
||||||
if d.firstVal(tPredictor) == prHorizontal {
|
if d.firstVal(tPredictor) == prHorizontal {
|
||||||
if d.bpp == 16 {
|
if d.bpp == 16 {
|
||||||
var off int
|
var off int
|
||||||
spp := len(d.features[tBitsPerSample]) // samples per pixel
|
n := 2 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel
|
||||||
bpp := spp * 2 // bytes per pixel
|
|
||||||
for y := ymin; y < ymax; y++ {
|
for y := ymin; y < ymax; y++ {
|
||||||
off += spp * 2
|
off += n
|
||||||
for x := 0; x < (xmax-xmin-1)*bpp; x += 2 {
|
for x := 0; x < (xmax-xmin-1)*n; x += 2 {
|
||||||
v0 := d.byteOrder.Uint16(d.buf[off-bpp : off-bpp+2])
|
if off+2 > len(d.buf) {
|
||||||
|
return FormatError("not enough pixel data")
|
||||||
|
}
|
||||||
|
v0 := d.byteOrder.Uint16(d.buf[off-n : off-n+2])
|
||||||
v1 := d.byteOrder.Uint16(d.buf[off : off+2])
|
v1 := d.byteOrder.Uint16(d.buf[off : off+2])
|
||||||
d.byteOrder.PutUint16(d.buf[off:off+2], v1+v0)
|
d.byteOrder.PutUint16(d.buf[off:off+2], v1+v0)
|
||||||
off += 2
|
off += 2
|
||||||
|
@ -216,11 +221,14 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
|
||||||
}
|
}
|
||||||
} else if d.bpp == 8 {
|
} else if d.bpp == 8 {
|
||||||
var off int
|
var off int
|
||||||
spp := len(d.features[tBitsPerSample]) // samples per pixel
|
n := 1 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel
|
||||||
for y := ymin; y < ymax; y++ {
|
for y := ymin; y < ymax; y++ {
|
||||||
off += spp
|
off += n
|
||||||
for x := 0; x < (xmax-xmin-1)*spp; x++ {
|
for x := 0; x < (xmax-xmin-1)*n; x++ {
|
||||||
d.buf[off] += d.buf[off-spp]
|
if off >= len(d.buf) {
|
||||||
|
return FormatError("not enough pixel data")
|
||||||
|
}
|
||||||
|
d.buf[off] += d.buf[off-n]
|
||||||
off++
|
off++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,6 +243,9 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
|
||||||
img := dst.(*image.Gray16)
|
img := dst.(*image.Gray16)
|
||||||
for y := ymin; y < rMaxY; y++ {
|
for y := ymin; y < rMaxY; y++ {
|
||||||
for x := xmin; x < rMaxX; x++ {
|
for x := xmin; x < rMaxX; x++ {
|
||||||
|
if d.off+2 > len(d.buf) {
|
||||||
|
return FormatError("not enough pixel data")
|
||||||
|
}
|
||||||
v := d.byteOrder.Uint16(d.buf[d.off : d.off+2])
|
v := d.byteOrder.Uint16(d.buf[d.off : d.off+2])
|
||||||
d.off += 2
|
d.off += 2
|
||||||
if d.mode == mGrayInvert {
|
if d.mode == mGrayInvert {
|
||||||
|
@ -248,11 +259,15 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
|
||||||
max := uint32((1 << d.bpp) - 1)
|
max := uint32((1 << d.bpp) - 1)
|
||||||
for y := ymin; y < rMaxY; y++ {
|
for y := ymin; y < rMaxY; y++ {
|
||||||
for x := xmin; x < rMaxX; x++ {
|
for x := xmin; x < rMaxX; x++ {
|
||||||
v := uint8(d.readBits(d.bpp) * 0xff / max)
|
v, ok := d.readBits(d.bpp)
|
||||||
|
if !ok {
|
||||||
|
return FormatError("not enough pixel data")
|
||||||
|
}
|
||||||
|
v = v * 0xff / max
|
||||||
if d.mode == mGrayInvert {
|
if d.mode == mGrayInvert {
|
||||||
v = 0xff - v
|
v = 0xff - v
|
||||||
}
|
}
|
||||||
img.SetGray(x, y, color.Gray{v})
|
img.SetGray(x, y, color.Gray{uint8(v)})
|
||||||
}
|
}
|
||||||
d.flushBits()
|
d.flushBits()
|
||||||
}
|
}
|
||||||
|
@ -261,7 +276,11 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
|
||||||
img := dst.(*image.Paletted)
|
img := dst.(*image.Paletted)
|
||||||
for y := ymin; y < rMaxY; y++ {
|
for y := ymin; y < rMaxY; y++ {
|
||||||
for x := xmin; x < rMaxX; x++ {
|
for x := xmin; x < rMaxX; x++ {
|
||||||
img.SetColorIndex(x, y, uint8(d.readBits(d.bpp)))
|
v, ok := d.readBits(d.bpp)
|
||||||
|
if !ok {
|
||||||
|
return FormatError("not enough pixel data")
|
||||||
|
}
|
||||||
|
img.SetColorIndex(x, y, uint8(v))
|
||||||
}
|
}
|
||||||
d.flushBits()
|
d.flushBits()
|
||||||
}
|
}
|
||||||
|
@ -270,6 +289,9 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
|
||||||
img := dst.(*image.RGBA64)
|
img := dst.(*image.RGBA64)
|
||||||
for y := ymin; y < rMaxY; y++ {
|
for y := ymin; y < rMaxY; y++ {
|
||||||
for x := xmin; x < rMaxX; x++ {
|
for x := xmin; x < rMaxX; x++ {
|
||||||
|
if d.off+6 > len(d.buf) {
|
||||||
|
return FormatError("not enough pixel data")
|
||||||
|
}
|
||||||
r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
|
r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
|
||||||
g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
|
g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
|
||||||
b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
|
b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
|
||||||
|
@ -284,6 +306,9 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
|
||||||
max := img.PixOffset(rMaxX, y)
|
max := img.PixOffset(rMaxX, y)
|
||||||
off := (y - ymin) * (xmax - xmin) * 3
|
off := (y - ymin) * (xmax - xmin) * 3
|
||||||
for i := min; i < max; i += 4 {
|
for i := min; i < max; i += 4 {
|
||||||
|
if d.off+3 > len(d.buf) {
|
||||||
|
return FormatError("not enough pixel data")
|
||||||
|
}
|
||||||
img.Pix[i+0] = d.buf[off+0]
|
img.Pix[i+0] = d.buf[off+0]
|
||||||
img.Pix[i+1] = d.buf[off+1]
|
img.Pix[i+1] = d.buf[off+1]
|
||||||
img.Pix[i+2] = d.buf[off+2]
|
img.Pix[i+2] = d.buf[off+2]
|
||||||
|
@ -297,6 +322,9 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
|
||||||
img := dst.(*image.NRGBA64)
|
img := dst.(*image.NRGBA64)
|
||||||
for y := ymin; y < rMaxY; y++ {
|
for y := ymin; y < rMaxY; y++ {
|
||||||
for x := xmin; x < rMaxX; x++ {
|
for x := xmin; x < rMaxX; x++ {
|
||||||
|
if d.off+8 > len(d.buf) {
|
||||||
|
return FormatError("not enough pixel data")
|
||||||
|
}
|
||||||
r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
|
r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
|
||||||
g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
|
g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
|
||||||
b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
|
b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
|
||||||
|
@ -310,8 +338,11 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
|
||||||
for y := ymin; y < rMaxY; y++ {
|
for y := ymin; y < rMaxY; y++ {
|
||||||
min := img.PixOffset(xmin, y)
|
min := img.PixOffset(xmin, y)
|
||||||
max := img.PixOffset(rMaxX, y)
|
max := img.PixOffset(rMaxX, y)
|
||||||
buf := d.buf[(y-ymin)*(xmax-xmin)*4 : (y-ymin+1)*(xmax-xmin)*4]
|
i0, i1 := (y-ymin)*(xmax-xmin)*4, (y-ymin+1)*(xmax-xmin)*4
|
||||||
copy(img.Pix[min:max], buf)
|
if i1 > len(d.buf) {
|
||||||
|
return FormatError("not enough pixel data")
|
||||||
|
}
|
||||||
|
copy(img.Pix[min:max], d.buf[i0:i1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case mRGBA:
|
case mRGBA:
|
||||||
|
@ -319,6 +350,9 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
|
||||||
img := dst.(*image.RGBA64)
|
img := dst.(*image.RGBA64)
|
||||||
for y := ymin; y < rMaxY; y++ {
|
for y := ymin; y < rMaxY; y++ {
|
||||||
for x := xmin; x < rMaxX; x++ {
|
for x := xmin; x < rMaxX; x++ {
|
||||||
|
if d.off+8 > len(d.buf) {
|
||||||
|
return FormatError("not enough pixel data")
|
||||||
|
}
|
||||||
r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
|
r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
|
||||||
g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
|
g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
|
||||||
b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
|
b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
|
||||||
|
@ -332,8 +366,11 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
|
||||||
for y := ymin; y < rMaxY; y++ {
|
for y := ymin; y < rMaxY; y++ {
|
||||||
min := img.PixOffset(xmin, y)
|
min := img.PixOffset(xmin, y)
|
||||||
max := img.PixOffset(rMaxX, y)
|
max := img.PixOffset(rMaxX, y)
|
||||||
buf := d.buf[(y-ymin)*(xmax-xmin)*4 : (y-ymin+1)*(xmax-xmin)*4]
|
i0, i1 := (y-ymin)*(xmax-xmin)*4, (y-ymin+1)*(xmax-xmin)*4
|
||||||
copy(img.Pix[min:max], buf)
|
if i1 > len(d.buf) {
|
||||||
|
return FormatError("not enough pixel data")
|
||||||
|
}
|
||||||
|
copy(img.Pix[min:max], d.buf[i0:i1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,32 @@ func TestUnpackBits(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestShortBlockData(t *testing.T) {
|
||||||
|
b, err := ioutil.ReadFile("../testdata/bw-uncompressed.tiff")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// The bw-uncompressed.tiff image is a 153x55 bi-level image. This is 1 bit
|
||||||
|
// per pixel, or 20 bytes per row, times 55 rows, or 1100 bytes of pixel
|
||||||
|
// data. 1100 in hex is 0x44c, or "\x4c\x04" in little-endian. We replace
|
||||||
|
// that byte count (StripByteCounts-tagged data) by something less than
|
||||||
|
// that, so that there is not enough pixel data.
|
||||||
|
old := []byte{0x4c, 0x04}
|
||||||
|
new := []byte{0x01, 0x01}
|
||||||
|
i := bytes.Index(b, old)
|
||||||
|
if i < 0 {
|
||||||
|
t.Fatal(`could not find "\x4c\x04" byte count`)
|
||||||
|
}
|
||||||
|
if bytes.Contains(b[i+len(old):], old) {
|
||||||
|
t.Fatal(`too many occurrences of "\x4c\x04"`)
|
||||||
|
}
|
||||||
|
b[i+0] = new[0]
|
||||||
|
b[i+1] = new[1]
|
||||||
|
if _, err = Decode(bytes.NewReader(b)); err == nil {
|
||||||
|
t.Fatal("got nil error, want non-nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func compare(t *testing.T, img0, img1 image.Image) {
|
func compare(t *testing.T, img0, img1 image.Image) {
|
||||||
b0 := img0.Bounds()
|
b0 := img0.Bounds()
|
||||||
b1 := img1.Bounds()
|
b1 := img1.Bounds()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user