tiff: limit uncompressed data reads

Apply the same limit to reading uncompressed data as
we use for compressed data.

Change-Id: Ib9f9243813659b93c02c9e94567697636a6a6964
Reviewed-on: https://go-review.googlesource.com/c/image/+/790220
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Neal Patel <neal@golang.org>
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Neal Patel <nealpatel@google.com>
diff --git a/tiff/reader.go b/tiff/reader.go
index bb48e8a..d974d79 100644
--- a/tiff/reader.go
+++ b/tiff/reader.go
@@ -764,6 +764,9 @@
 			// but some tools interpret a missing Compression value as none, so we do
 			// the same.
 			case cNone, 0:
+				if n > blockMaxDataSize {
+					return nil, FormatError("block data size too large")
+				}
 				if b, ok := d.r.(*buffer); ok {
 					d.buf, err = b.Slice(offset, n)
 				} else {
diff --git a/tiff/reader_test.go b/tiff/reader_test.go
index 0a6b6c7..bf59fdd 100644
--- a/tiff/reader_test.go
+++ b/tiff/reader_test.go
@@ -723,3 +723,48 @@
 		t.Fatalf("Decode: got %v, want error containing %q", err, want)
 	}
 }
+
+func TestDecodeBlockDataSizeTooLarge(t *testing.T) {
+	t.Run("strip", func(t *testing.T) {
+		// 1x1 image, blockMaxDataSize = 1 * 1 * 8 = 8.
+		// StripByteCounts is set to 9.
+		enc := binary.BigEndian
+		data := newTIFF(enc)
+		data = appendIFD(data, enc, map[uint16]any{
+			tImageWidth:                uint32(1),
+			tImageLength:               uint32(1),
+			tStripOffsets:              []uint32{8},
+			tStripByteCounts:           []uint32{9},
+			tPhotometricInterpretation: uint16(pBlackIsZero),
+			tBitsPerSample:             uint16(8),
+		})
+
+		_, err := Decode(bytes.NewReader(data))
+		if want := "block data size too large"; err == nil || !strings.Contains(err.Error(), want) {
+			t.Fatalf("Decode: got %v, want error containing %q", err, want)
+		}
+	})
+
+	t.Run("tile", func(t *testing.T) {
+		// 16x16 image with 16x16 tiles.
+		// blockMaxDataSize = 16 * 16 * 8 = 2048.
+		// TileByteCounts is set to 2049.
+		enc := binary.BigEndian
+		data := newTIFF(enc)
+		data = appendIFD(data, enc, map[uint16]any{
+			tImageWidth:                uint32(16),
+			tImageLength:               uint32(16),
+			tTileWidth:                 uint32(16),
+			tTileLength:                uint32(16),
+			tTileOffsets:               []uint32{8},
+			tTileByteCounts:            []uint32{2049},
+			tPhotometricInterpretation: uint16(pBlackIsZero),
+			tBitsPerSample:             uint16(8),
+		})
+
+		_, err := Decode(bytes.NewReader(data))
+		if want := "block data size too large"; err == nil || !strings.Contains(err.Error(), want) {
+			t.Fatalf("Decode: got %v, want error containing %q", err, want)
+		}
+	})
+}