Skip to content

Commit 3129f81

Browse files
committed
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 <[email protected]> Reviewed-by: Nigel Tao <[email protected]>
1 parent fdb36f1 commit 3129f81

File tree

2 files changed

+81
-18
lines changed

2 files changed

+81
-18
lines changed

tiff/reader.go

+55-18
Original file line numberDiff line numberDiff line change
@@ -164,17 +164,20 @@ func (d *decoder) parseIFD(p []byte) error {
164164
}
165165

166166
// readBits reads n bits from the internal buffer starting at the current offset.
167-
func (d *decoder) readBits(n uint) uint32 {
167+
func (d *decoder) readBits(n uint) (v uint32, ok bool) {
168168
for d.nbits < n {
169169
d.v <<= 8
170+
if d.off >= len(d.buf) {
171+
return 0, false
172+
}
170173
d.v |= uint32(d.buf[d.off])
171174
d.off++
172175
d.nbits += 8
173176
}
174177
d.nbits -= n
175178
rv := d.v >> d.nbits
176179
d.v &^= rv << d.nbits
177-
return rv
180+
return rv, true
178181
}
179182

180183
// flushBits discards the unread bits in the buffer used by readBits.
@@ -203,24 +206,29 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
203206
if d.firstVal(tPredictor) == prHorizontal {
204207
if d.bpp == 16 {
205208
var off int
206-
spp := len(d.features[tBitsPerSample]) // samples per pixel
207-
bpp := spp * 2 // bytes per pixel
209+
n := 2 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel
208210
for y := ymin; y < ymax; y++ {
209-
off += spp * 2
210-
for x := 0; x < (xmax-xmin-1)*bpp; x += 2 {
211-
v0 := d.byteOrder.Uint16(d.buf[off-bpp : off-bpp+2])
211+
off += n
212+
for x := 0; x < (xmax-xmin-1)*n; x += 2 {
213+
if off+2 > len(d.buf) {
214+
return FormatError("not enough pixel data")
215+
}
216+
v0 := d.byteOrder.Uint16(d.buf[off-n : off-n+2])
212217
v1 := d.byteOrder.Uint16(d.buf[off : off+2])
213218
d.byteOrder.PutUint16(d.buf[off:off+2], v1+v0)
214219
off += 2
215220
}
216221
}
217222
} else if d.bpp == 8 {
218223
var off int
219-
spp := len(d.features[tBitsPerSample]) // samples per pixel
224+
n := 1 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel
220225
for y := ymin; y < ymax; y++ {
221-
off += spp
222-
for x := 0; x < (xmax-xmin-1)*spp; x++ {
223-
d.buf[off] += d.buf[off-spp]
226+
off += n
227+
for x := 0; x < (xmax-xmin-1)*n; x++ {
228+
if off >= len(d.buf) {
229+
return FormatError("not enough pixel data")
230+
}
231+
d.buf[off] += d.buf[off-n]
224232
off++
225233
}
226234
}
@@ -235,6 +243,9 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
235243
img := dst.(*image.Gray16)
236244
for y := ymin; y < rMaxY; y++ {
237245
for x := xmin; x < rMaxX; x++ {
246+
if d.off+2 > len(d.buf) {
247+
return FormatError("not enough pixel data")
248+
}
238249
v := d.byteOrder.Uint16(d.buf[d.off : d.off+2])
239250
d.off += 2
240251
if d.mode == mGrayInvert {
@@ -248,11 +259,15 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
248259
max := uint32((1 << d.bpp) - 1)
249260
for y := ymin; y < rMaxY; y++ {
250261
for x := xmin; x < rMaxX; x++ {
251-
v := uint8(d.readBits(d.bpp) * 0xff / max)
262+
v, ok := d.readBits(d.bpp)
263+
if !ok {
264+
return FormatError("not enough pixel data")
265+
}
266+
v = v * 0xff / max
252267
if d.mode == mGrayInvert {
253268
v = 0xff - v
254269
}
255-
img.SetGray(x, y, color.Gray{v})
270+
img.SetGray(x, y, color.Gray{uint8(v)})
256271
}
257272
d.flushBits()
258273
}
@@ -261,7 +276,11 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
261276
img := dst.(*image.Paletted)
262277
for y := ymin; y < rMaxY; y++ {
263278
for x := xmin; x < rMaxX; x++ {
264-
img.SetColorIndex(x, y, uint8(d.readBits(d.bpp)))
279+
v, ok := d.readBits(d.bpp)
280+
if !ok {
281+
return FormatError("not enough pixel data")
282+
}
283+
img.SetColorIndex(x, y, uint8(v))
265284
}
266285
d.flushBits()
267286
}
@@ -270,6 +289,9 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
270289
img := dst.(*image.RGBA64)
271290
for y := ymin; y < rMaxY; y++ {
272291
for x := xmin; x < rMaxX; x++ {
292+
if d.off+6 > len(d.buf) {
293+
return FormatError("not enough pixel data")
294+
}
273295
r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
274296
g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
275297
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 {
284306
max := img.PixOffset(rMaxX, y)
285307
off := (y - ymin) * (xmax - xmin) * 3
286308
for i := min; i < max; i += 4 {
309+
if d.off+3 > len(d.buf) {
310+
return FormatError("not enough pixel data")
311+
}
287312
img.Pix[i+0] = d.buf[off+0]
288313
img.Pix[i+1] = d.buf[off+1]
289314
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 {
297322
img := dst.(*image.NRGBA64)
298323
for y := ymin; y < rMaxY; y++ {
299324
for x := xmin; x < rMaxX; x++ {
325+
if d.off+8 > len(d.buf) {
326+
return FormatError("not enough pixel data")
327+
}
300328
r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
301329
g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
302330
b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
@@ -310,15 +338,21 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
310338
for y := ymin; y < rMaxY; y++ {
311339
min := img.PixOffset(xmin, y)
312340
max := img.PixOffset(rMaxX, y)
313-
buf := d.buf[(y-ymin)*(xmax-xmin)*4 : (y-ymin+1)*(xmax-xmin)*4]
314-
copy(img.Pix[min:max], buf)
341+
i0, i1 := (y-ymin)*(xmax-xmin)*4, (y-ymin+1)*(xmax-xmin)*4
342+
if i1 > len(d.buf) {
343+
return FormatError("not enough pixel data")
344+
}
345+
copy(img.Pix[min:max], d.buf[i0:i1])
315346
}
316347
}
317348
case mRGBA:
318349
if d.bpp == 16 {
319350
img := dst.(*image.RGBA64)
320351
for y := ymin; y < rMaxY; y++ {
321352
for x := xmin; x < rMaxX; x++ {
353+
if d.off+8 > len(d.buf) {
354+
return FormatError("not enough pixel data")
355+
}
322356
r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
323357
g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
324358
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 {
332366
for y := ymin; y < rMaxY; y++ {
333367
min := img.PixOffset(xmin, y)
334368
max := img.PixOffset(rMaxX, y)
335-
buf := d.buf[(y-ymin)*(xmax-xmin)*4 : (y-ymin+1)*(xmax-xmin)*4]
336-
copy(img.Pix[min:max], buf)
369+
i0, i1 := (y-ymin)*(xmax-xmin)*4, (y-ymin+1)*(xmax-xmin)*4
370+
if i1 > len(d.buf) {
371+
return FormatError("not enough pixel data")
372+
}
373+
copy(img.Pix[min:max], d.buf[i0:i1])
337374
}
338375
}
339376
}

tiff/reader_test.go

+26
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,32 @@ func TestUnpackBits(t *testing.T) {
7575
}
7676
}
7777

78+
func TestShortBlockData(t *testing.T) {
79+
b, err := ioutil.ReadFile("../testdata/bw-uncompressed.tiff")
80+
if err != nil {
81+
t.Fatal(err)
82+
}
83+
// The bw-uncompressed.tiff image is a 153x55 bi-level image. This is 1 bit
84+
// per pixel, or 20 bytes per row, times 55 rows, or 1100 bytes of pixel
85+
// data. 1100 in hex is 0x44c, or "\x4c\x04" in little-endian. We replace
86+
// that byte count (StripByteCounts-tagged data) by something less than
87+
// that, so that there is not enough pixel data.
88+
old := []byte{0x4c, 0x04}
89+
new := []byte{0x01, 0x01}
90+
i := bytes.Index(b, old)
91+
if i < 0 {
92+
t.Fatal(`could not find "\x4c\x04" byte count`)
93+
}
94+
if bytes.Contains(b[i+len(old):], old) {
95+
t.Fatal(`too many occurrences of "\x4c\x04"`)
96+
}
97+
b[i+0] = new[0]
98+
b[i+1] = new[1]
99+
if _, err = Decode(bytes.NewReader(b)); err == nil {
100+
t.Fatal("got nil error, want non-nil")
101+
}
102+
}
103+
78104
func compare(t *testing.T, img0, img1 image.Image) {
79105
b0 := img0.Bounds()
80106
b1 := img1.Bounds()

0 commit comments

Comments
 (0)