image/tiff: fix a panic with invalid tile sizes

Fuzzing detected that an invalid tile size could cause a
panic. Fix a typo in the range check to solve it.

Fixes golang/go#10712.

Change-Id: I88a5a7884d98f622cc89ed6e394becebb07c6e60
Reviewed-on: https://go-review.googlesource.com/11020
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/tiff/reader.go b/tiff/reader.go
index cf9b5e1..19baee9 100644
--- a/tiff/reader.go
+++ b/tiff/reader.go
@@ -321,7 +321,7 @@
 				max := img.PixOffset(rMaxX, y)
 				off := (y - ymin) * (xmax - xmin) * 3
 				for i := min; i < max; i += 4 {
-					if d.off+3 > len(d.buf) {
+					if off+3 > len(d.buf) {
 						return FormatError("not enough pixel data")
 					}
 					img.Pix[i+0] = d.buf[off+0]
diff --git a/tiff/reader_test.go b/tiff/reader_test.go
index f3d7128..3dd412d 100644
--- a/tiff/reader_test.go
+++ b/tiff/reader_test.go
@@ -211,6 +211,45 @@
 	}
 }
 
+// TestTileTooBig checks that we do not panic when a tile is too big compared
+// to the data available.
+// Issue 10712
+func TestTileTooBig(t *testing.T) {
+	contents, err := ioutil.ReadFile(testdataDir + "video-001-tile-64x64.tiff")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Mutate the loaded image to have the problem.
+	//
+	// 0x42 01: tag number (tTileWidth)
+	// 03 00: data type (short, or uint16)
+	// 01 00 00 00: count
+	// xx 00 00 00: value (0x40 -> 0x44: a wider tile consumes more data
+	// than is available)
+	find := []byte{0x42, 0x01, 3, 0, 1, 0, 0, 0, 0x40, 0, 0, 0}
+	repl := []byte{0x42, 0x01, 3, 0, 1, 0, 0, 0, 0x44, 0, 0, 0}
+	contents = bytes.Replace(contents, find, repl, 1)
+
+	// Turn off the predictor, which makes it possible to hit the
+	// place with the defect. Without this patch to the image, we run
+	// out of data too early, and do not hit the part of the code where
+	// the original panic was.
+	//
+	// 42 01: tag number (tPredictor)
+	// 03 00: data type (short, or uint16)
+	// 01 00 00 00: count
+	// xx 00 00 00: value (2 -> 1: 2 = horizontal, 1 = none)
+	find = []byte{0x3d, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0}
+	repl = []byte{0x3d, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0}
+	contents = bytes.Replace(contents, find, repl, 1)
+
+	_, err = Decode(bytes.NewReader(contents))
+	if err == nil {
+		t.Fatal("did not expect nil error")
+	}
+}
+
 // Do not panic when image dimensions are zero, return zero-sized
 // image instead.
 // Issue 10393.