Validate grid image size and tile size (#272)

Check the restrictions on grid image size and tile size in HEIF and
MIAF.

Fix https://github.com/AOMediaCodec/libavif/issues/262 and
https://github.com/AOMediaCodec/libavif/issues/264.
diff --git a/src/read.c b/src/read.c
index 2229475..bcf1e94 100644
--- a/src/read.c
+++ b/src/read.c
@@ -699,6 +699,39 @@
         }
     }
 
+    // Validate grid image size and tile size.
+    //
+    // HEIF (ISO/IEC 23008-12:2017), Section 6.6.2.3.1:
+    //   The tiled input images shall completely “cover” the reconstructed image grid canvas, ...
+    if (firstTile->image->width * grid->columns < grid->outputWidth || firstTile->image->height * grid->rows < grid->outputHeight) {
+        return AVIF_FALSE;
+    }
+    // Tiles in the rightmost column and bottommost row must overlap the reconstructed image grid canvas. See MIAF (ISO/IEC 23000-22:2019), Section 7.3.11.4.2, Figure 2.
+    if (firstTile->image->width * (grid->columns - 1) >= grid->outputWidth ||
+        firstTile->image->height * (grid->rows - 1) >= grid->outputHeight) {
+        return AVIF_FALSE;
+    }
+    // Check the restrictions in MIAF (ISO/IEC 23000-22:2019), Section 7.3.11.4.2.
+    //
+    // The tile_width shall be greater than or equal to 64, and the tile_height shall be greater than or equal to 64.
+    if (firstTile->image->width < 64 || firstTile->image->height < 64) {
+        return AVIF_FALSE;
+    }
+    if (!alpha) {
+        if (firstTile->image->yuvFormat == AVIF_PIXEL_FORMAT_YUV422 || firstTile->image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420) {
+            // The horizontal tile offsets and widths, and the output width, shall be even numbers.
+            if ((firstTile->image->width & 1) != 0 || (grid->outputWidth & 1) != 0) {
+                return AVIF_FALSE;
+            }
+        }
+        if (firstTile->image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420) {
+            // The vertical tile offsets and heights, and the output height, shall be even numbers.
+            if ((firstTile->image->height & 1) != 0 || (grid->outputHeight & 1) != 0) {
+                return AVIF_FALSE;
+            }
+        }
+    }
+
     // Lazily populate dstImage with the new frame's properties. If we're decoding alpha,
     // these values must already match.
     if ((dstImage->width != grid->outputWidth) || (dstImage->height != grid->outputHeight) ||
@@ -750,13 +783,7 @@
 
             // Y and A channels
             size_t yaColOffset = colIndex * firstTile->image->width;
-            if (yaColOffset >= grid->outputWidth) {
-                return AVIF_FALSE;
-            }
             size_t yaRowOffset = rowIndex * firstTile->image->height;
-            if (yaRowOffset >= grid->outputHeight) {
-                return AVIF_FALSE;
-            }
             size_t yaRowBytes = widthToCopy * pixelBytes;
 
             if (alpha) {