x/image/tiff: fix division by zero when decoding empty image

Return a zero width or zero height image of the appropriate type.

Fixes golang/go#10393.

Change-Id: I3aa7b6125447726600fb072ce1e8682373ce2a57
Reviewed-on: https://go-review.googlesource.com/9182
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/tiff/reader.go b/tiff/reader.go
index 66acb0d..0b24c53 100644
--- a/tiff/reader.go
+++ b/tiff/reader.go
@@ -488,6 +488,13 @@
 	blocksAcross := 1
 	blocksDown := 1
 
+	if d.config.Width == 0 {
+		blocksAcross = 0
+	}
+	if d.config.Height == 0 {
+		blocksDown = 0
+	}
+
 	var blockOffsets, blockCounts []uint
 
 	if int(d.firstVal(tTileWidth)) != 0 {
@@ -496,8 +503,12 @@
 		blockWidth = int(d.firstVal(tTileWidth))
 		blockHeight = int(d.firstVal(tTileLength))
 
-		blocksAcross = (d.config.Width + blockWidth - 1) / blockWidth
-		blocksDown = (d.config.Height + blockHeight - 1) / blockHeight
+		if blockWidth != 0 {
+			blocksAcross = (d.config.Width + blockWidth - 1) / blockWidth
+		}
+		if blockHeight != 0 {
+			blocksDown = (d.config.Height + blockHeight - 1) / blockHeight
+		}
 
 		blockCounts = d.features[tTileByteCounts]
 		blockOffsets = d.features[tTileOffsets]
@@ -507,7 +518,9 @@
 			blockHeight = int(d.firstVal(tRowsPerStrip))
 		}
 
-		blocksDown = (d.config.Height + blockHeight - 1) / blockHeight
+		if blockHeight != 0 {
+			blocksDown = (d.config.Height + blockHeight - 1) / blockHeight
+		}
 
 		blockOffsets = d.features[tStripOffsets]
 		blockCounts = d.features[tStripByteCounts]
diff --git a/tiff/reader_test.go b/tiff/reader_test.go
index cceb7aa..5bd5ee2 100644
--- a/tiff/reader_test.go
+++ b/tiff/reader_test.go
@@ -5,6 +5,7 @@
 package tiff
 
 import (
+	"bytes"
 	"image"
 	"io/ioutil"
 	"os"
@@ -162,6 +163,31 @@
 	}
 }
 
+// Do not panic when image dimensions are zero, return zero-sized
+// image instead.
+// Issue 10393.
+func TestZeroSizedImages(t *testing.T) {
+	testsizes := []struct {
+		w, h int
+	}{
+		{0, 0},
+		{1, 0},
+		{0, 1},
+		{1, 1},
+	}
+	for _, r := range testsizes {
+		img := image.NewRGBA(image.Rect(0, 0, r.w, r.h))
+		var buf bytes.Buffer
+		if err := Encode(&buf, img, nil); err != nil {
+			t.Errorf("encode w=%d h=%d: %v", r.w, r.h, err)
+			continue
+		}
+		if _, err := Decode(&buf); err != nil {
+			t.Errorf("decode w=%d h=%d: %v", r.w, r.h, err)
+		}
+	}
+}
+
 // benchmarkDecode benchmarks the decoding of an image.
 func benchmarkDecode(b *testing.B, filename string) {
 	b.StopTimer()