tiff: reject 0-size images

Refuse to encode or decode images where the width or height is 0.
It's not clear that this is ever valid, and mostly exists as a
way to cause surprising behavior when w*h == 0 but w+h is large.

Fixes #78773

Change-Id: I6184e9eb60fdf732a2e81d4fc6bb426b6a6a6964
Reviewed-on: https://go-review.googlesource.com/c/image/+/767401
Reviewed-by: Nicholas Husin <husin@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Nicholas Husin <nsh@golang.org>
diff --git a/tiff/reader.go b/tiff/reader.go
index 4c1de45..882899d 100644
--- a/tiff/reader.go
+++ b/tiff/reader.go
@@ -11,6 +11,7 @@
 	"bytes"
 	"compress/zlib"
 	"encoding/binary"
+	"errors"
 	"fmt"
 	"image"
 	"image/color"
@@ -500,6 +501,9 @@
 
 	d.config.Width = int(d.firstVal(tImageWidth))
 	d.config.Height = int(d.firstVal(tImageLength))
+	if d.config.Width == 0 || d.config.Height == 0 {
+		return nil, errors.New("tiff: zero-size image")
+	}
 
 	if _, ok := d.features[tBitsPerSample]; !ok {
 		// Default is 1 per specification.
diff --git a/tiff/reader_test.go b/tiff/reader_test.go
index c34ac01..4709b0d 100644
--- a/tiff/reader_test.go
+++ b/tiff/reader_test.go
@@ -380,16 +380,19 @@
 		{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)
+		if err := Encode(io.Discard, img, nil); err == nil {
+			t.Errorf("encode w=%d h=%d: success (want error)", r.w, r.h)
+		}
+
+		enc, err := os.ReadFile(fmt.Sprintf("testdata/%vx%v.tiff", r.w, r.h))
+		if err != nil {
+			t.Error(err)
 			continue
 		}
-		if _, err := Decode(&buf); err != nil {
+		if _, err := Decode(bytes.NewReader(enc)); err == nil {
 			t.Errorf("decode w=%d h=%d: %v", r.w, r.h, err)
 		}
 	}
diff --git a/tiff/testdata/0x0.tiff b/tiff/testdata/0x0.tiff
new file mode 100644
index 0000000..3c4fd34
--- /dev/null
+++ b/tiff/testdata/0x0.tiff
Binary files differ
diff --git a/tiff/testdata/0x1.tiff b/tiff/testdata/0x1.tiff
new file mode 100644
index 0000000..2fd2367
--- /dev/null
+++ b/tiff/testdata/0x1.tiff
Binary files differ
diff --git a/tiff/testdata/1x0.tiff b/tiff/testdata/1x0.tiff
new file mode 100644
index 0000000..e7eec41
--- /dev/null
+++ b/tiff/testdata/1x0.tiff
Binary files differ
diff --git a/tiff/writer.go b/tiff/writer.go
index 5d46184..b7b47a1 100644
--- a/tiff/writer.go
+++ b/tiff/writer.go
@@ -292,6 +292,10 @@
 func Encode(w io.Writer, m image.Image, opt *Options) error {
 	d := m.Bounds().Size()
 
+	if d.X == 0 || d.Y == 0 {
+		return errors.New("tiff: zero-size image")
+	}
+
 	compression := uint32(cNone)
 	predictor := false
 	if opt != nil {