Rename AVIF_MAX_IMAGE_SIZE to AVIF_DEFAULT_MAX_IMAGE_SIZE, set defaults in avifDecoder, promote some indexing math vars to uint32_t, update some comments
diff --git a/apps/avifdec.c b/apps/avifdec.c
index b4aafbd..497534a 100644
--- a/apps/avifdec.c
+++ b/apps/avifdec.c
@@ -36,8 +36,8 @@
     printf("    -u,--upsampling U : Chroma upsampling (for 420/422). automatic (default), fastest, best, nearest, or bilinear\n");
     printf("    -i,--info         : Decode all frames and display all image information instead of saving to disk\n");
     printf("    --ignore-icc      : If the input file contains an embedded ICC profile, ignore it (no-op if absent)\n");
-    printf("    --size-limit C    : Specifies the image size limit (in total pixels) that the AV1 codec should tolerate.\n");
-    printf("                        Default: %u, set to 0 to disable. Supported codecs: dav1d.\n", AVIF_MAX_IMAGE_SIZE);
+    printf("    --size-limit C    : Specifies the image size limit (in total pixels) that should be tolerated.\n");
+    printf("                        Default: %u, set to 0 to disable.\n", AVIF_DEFAULT_MAX_IMAGE_SIZE);
     printf("\n");
     avifPrintVersions();
 }
@@ -93,7 +93,7 @@
     avifBool infoOnly = AVIF_FALSE;
     avifChromaUpsampling chromaUpsampling = AVIF_CHROMA_UPSAMPLING_AUTOMATIC;
     avifBool ignoreICC = AVIF_FALSE;
-    uint32_t imageSizeLimit = AVIF_MAX_IMAGE_SIZE;
+    uint32_t imageSizeLimit = AVIF_DEFAULT_MAX_IMAGE_SIZE;
 
     if (argc < 2) {
         syntax();
diff --git a/include/avif/avif.h b/include/avif/avif.h
index e8e452a..9e01cdc 100644
--- a/include/avif/avif.h
+++ b/include/avif/avif.h
@@ -76,9 +76,9 @@
 #define AVIF_SPEED_SLOWEST 0
 #define AVIF_SPEED_FASTEST 10
 
-// A maximum image size to avoid out-of-memory errors or integer overflow in
+// A reasonable default for maximum image size to avoid out-of-memory errors or integer overflow in
 // (32-bit) int or unsigned int arithmetic operations.
-#define AVIF_MAX_IMAGE_SIZE (16384 * 16384)
+#define AVIF_DEFAULT_MAX_IMAGE_SIZE (16384 * 16384)
 
 enum avifPlanesFlags
 {
@@ -144,7 +144,8 @@
     AVIF_RESULT_IO_ERROR,
     AVIF_RESULT_WAITING_ON_IO, // similar to EAGAIN/EWOULDBLOCK, this means the avifIO doesn't have necessary data available yet
     AVIF_RESULT_INVALID_ARGUMENT, // an argument passed into this function is invalid
-    AVIF_RESULT_NOT_IMPLEMENTED   // a requested code path is not (yet) implemented
+    AVIF_RESULT_NOT_IMPLEMENTED,  // a requested code path is not (yet) implemented
+    AVIF_RESULT_IMAGE_TOO_LARGE   // The image exceeds the configured imageSizeLimit
 } avifResult;
 
 AVIF_API const char * avifResultToString(avifResult result);
@@ -705,9 +706,10 @@
     avifBool ignoreExif;
     avifBool ignoreXMP;
 
-    // This represents the maximum size of a image (in pixel count) that the underlying AV1 decoder
-    // should attempt to decode. It defaults to AVIF_MAX_IMAGE_SIZE, and can be set to 0 to disable
-    // the limit. Currently supported codecs: dav1d.
+    // This represents the maximum size of a image (in pixel count) that libavif and the underlying
+    // AV1 decoder should attempt to decode. It defaults to AVIF_DEFAULT_MAX_IMAGE_SIZE, and can be
+    // set to 0 to disable the limit.
+    // Note: Only some underlying AV1 codecs support a configurable size limit (such as dav1d).
     uint32_t imageSizeLimit;
 
     // stats from the most recent read, possibly 0s if reading an image sequence
diff --git a/src/avif.c b/src/avif.c
index 18e6734..085e526 100644
--- a/src/avif.c
+++ b/src/avif.c
@@ -93,6 +93,7 @@
         case AVIF_RESULT_WAITING_ON_IO:                 return "Waiting on IO";
         case AVIF_RESULT_INVALID_ARGUMENT:              return "Invalid argument";
         case AVIF_RESULT_NOT_IMPLEMENTED:               return "Not implemented";
+        case AVIF_RESULT_IMAGE_TOO_LARGE:               return "Image too large";
         case AVIF_RESULT_UNKNOWN_ERROR:
         default:
             break;
diff --git a/src/read.c b/src/read.c
index 44ee044..a826a80 100644
--- a/src/read.c
+++ b/src/read.c
@@ -1182,14 +1182,14 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseImageGridBox(avifImageGrid * grid, const uint8_t * raw, size_t rawLen)
+static avifResult avifParseImageGridBox(avifImageGrid * grid, const uint8_t * raw, size_t rawLen, uint32_t imageSizeLimit)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
     uint8_t version, flags;
     CHECK(avifROStreamRead(&s, &version, 1)); // unsigned int(8) version = 0;
     if (version != 0) {
-        return AVIF_FALSE;
+        return AVIF_RESULT_INVALID_IMAGE_GRID;
     }
     uint8_t rowsMinusOne, columnsMinusOne;
     CHECK(avifROStreamRead(&s, &flags, 1));           // unsigned int(8) flags;
@@ -1208,15 +1208,18 @@
     } else {
         if (fieldLength != 32) {
             // This should be impossible
-            return AVIF_FALSE;
+            return AVIF_RESULT_INVALID_IMAGE_GRID;
         }
         CHECK(avifROStreamReadU32(&s, &grid->outputWidth));  // unsigned int(FieldLength) output_width;
         CHECK(avifROStreamReadU32(&s, &grid->outputHeight)); // unsigned int(FieldLength) output_height;
     }
-    if ((grid->outputWidth == 0) || (grid->outputHeight == 0) || (grid->outputWidth > (AVIF_MAX_IMAGE_SIZE / grid->outputHeight))) {
-        return AVIF_FALSE;
+    if ((grid->outputWidth == 0) || (grid->outputHeight == 0) || (avifROStreamRemainingBytes(&s) != 0)) {
+        return AVIF_RESULT_INVALID_IMAGE_GRID;
     }
-    return avifROStreamRemainingBytes(&s) == 0;
+    if (imageSizeLimit && (grid->outputWidth > (imageSizeLimit / grid->outputHeight))) {
+        return AVIF_RESULT_IMAGE_TOO_LARGE;
+    }
+    return AVIF_RESULT_OK;
 }
 
 static avifBool avifParseImageSpatialExtentsProperty(avifProperty * prop, const uint8_t * raw, size_t rawLen)
@@ -2233,6 +2236,7 @@
     avifDecoder * decoder = (avifDecoder *)avifAlloc(sizeof(avifDecoder));
     memset(decoder, 0, sizeof(avifDecoder));
     decoder->maxThreads = 1;
+    decoder->imageSizeLimit = AVIF_DEFAULT_MAX_IMAGE_SIZE;
     return decoder;
 }
 
@@ -2632,8 +2636,9 @@
                 if (readResult != AVIF_RESULT_OK) {
                     return readResult;
                 }
-                if (!avifParseImageGridBox(&data->colorGrid, readData.data, readData.size)) {
-                    return AVIF_RESULT_INVALID_IMAGE_GRID;
+                avifResult parseResult = avifParseImageGridBox(&data->colorGrid, readData.data, readData.size, decoder->imageSizeLimit);
+                if (parseResult != AVIF_RESULT_OK) {
+                    return parseResult;
                 }
             }
 
@@ -2671,8 +2676,10 @@
                     if (readResult != AVIF_RESULT_OK) {
                         return readResult;
                     }
-                    if (!avifParseImageGridBox(&data->alphaGrid, readData.data, readData.size)) {
-                        return AVIF_RESULT_INVALID_IMAGE_GRID;
+                    avifResult parseResult =
+                        avifParseImageGridBox(&data->alphaGrid, readData.data, readData.size, decoder->imageSizeLimit);
+                    if (parseResult != AVIF_RESULT_OK) {
+                        return parseResult;
                     }
                 }
 
@@ -2747,6 +2754,12 @@
         if (ispeProp) {
             decoder->image->width = ispeProp->u.ispe.width;
             decoder->image->height = ispeProp->u.ispe.height;
+            if (!decoder->image->width || !decoder->image->height) {
+                return AVIF_RESULT_BMFF_PARSE_FAILED;
+            }
+            if (decoder->imageSizeLimit && (decoder->image->width > (decoder->imageSizeLimit / decoder->image->height))) {
+                return AVIF_RESULT_IMAGE_TOO_LARGE;
+            }
         } else {
             decoder->image->width = 0;
             decoder->image->height = 0;
diff --git a/src/reformat.c b/src/reformat.c
index be035c4..f1dfbdb 100644
--- a/src/reformat.c
+++ b/src/reformat.c
@@ -180,7 +180,7 @@
     uint32_t * yuvRowBytes = image->yuvRowBytes;
     for (uint32_t outerJ = 0; outerJ < image->height; outerJ += 2) {
         for (uint32_t outerI = 0; outerI < image->width; outerI += 2) {
-            int blockW = 2, blockH = 2;
+            uint32_t blockW = 2, blockH = 2;
             if ((outerI + 1) >= image->width) {
                 blockW = 1;
             }
@@ -189,10 +189,10 @@
             }
 
             // Convert an entire 2x2 block to YUV, and populate any fully sampled channels as we go
-            for (int bJ = 0; bJ < blockH; ++bJ) {
-                for (int bI = 0; bI < blockW; ++bI) {
-                    int i = outerI + bI;
-                    int j = outerJ + bJ;
+            for (uint32_t bJ = 0; bJ < blockH; ++bJ) {
+                for (uint32_t bI = 0; bI < blockW; ++bI) {
+                    uint32_t i = outerI + bI;
+                    uint32_t j = outerJ + bJ;
 
                     // Unpack RGB into normalized float
                     if (state.rgbChannelBytes > 1) {
@@ -297,8 +297,8 @@
 
                 float sumU = 0.0f;
                 float sumV = 0.0f;
-                for (int bJ = 0; bJ < blockH; ++bJ) {
-                    for (int bI = 0; bI < blockW; ++bI) {
+                for (uint32_t bJ = 0; bJ < blockH; ++bJ) {
+                    for (uint32_t bI = 0; bI < blockW; ++bI) {
                         sumU += yuvBlock[bI][bJ].u;
                         sumV += yuvBlock[bI][bJ].v;
                     }
@@ -307,10 +307,10 @@
                 float avgU = sumU / totalSamples;
                 float avgV = sumV / totalSamples;
 
-                const int chromaShiftX = 1;
-                const int chromaShiftY = 1;
-                int uvI = outerI >> chromaShiftX;
-                int uvJ = outerJ >> chromaShiftY;
+                const uint32_t chromaShiftX = 1;
+                const uint32_t chromaShiftY = 1;
+                uint32_t uvI = outerI >> chromaShiftX;
+                uint32_t uvJ = outerJ >> chromaShiftY;
                 if (state.yuvChannelBytes > 1) {
                     uint16_t * pU = (uint16_t *)&yuvPlanes[AVIF_CHAN_U][(uvI * 2) + (uvJ * yuvRowBytes[AVIF_CHAN_U])];
                     *pU = (uint16_t)avifReformatStateUVToUNorm(&state, avgU);
@@ -323,10 +323,10 @@
             } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV422) {
                 // YUV422, average 2 samples (1x2), twice
 
-                for (int bJ = 0; bJ < blockH; ++bJ) {
+                for (uint32_t bJ = 0; bJ < blockH; ++bJ) {
                     float sumU = 0.0f;
                     float sumV = 0.0f;
-                    for (int bI = 0; bI < blockW; ++bI) {
+                    for (uint32_t bI = 0; bI < blockW; ++bI) {
                         sumU += yuvBlock[bI][bJ].u;
                         sumV += yuvBlock[bI][bJ].v;
                     }
@@ -334,9 +334,9 @@
                     float avgU = sumU / totalSamples;
                     float avgV = sumV / totalSamples;
 
-                    const int chromaShiftX = 1;
-                    int uvI = outerI >> chromaShiftX;
-                    int uvJ = outerJ + bJ;
+                    const uint32_t chromaShiftX = 1;
+                    uint32_t uvI = outerI >> chromaShiftX;
+                    uint32_t uvJ = outerJ + bJ;
                     if (state.yuvChannelBytes > 1) {
                         uint16_t * pU = (uint16_t *)&yuvPlanes[AVIF_CHAN_U][(uvI * 2) + (uvJ * yuvRowBytes[AVIF_CHAN_U])];
                         *pU = (uint16_t)avifReformatStateUVToUNorm(&state, avgU);
@@ -488,7 +488,7 @@
                     uint16_t unormU[2][2], unormV[2][2];
 
                     // How many bytes to add to a uint8_t pointer index to get to the adjacent (lesser) sample in a given direction
-                    int uAdjCol, vAdjCol, uAdjRow, vAdjRow;
+                    uint32_t uAdjCol, vAdjCol, uAdjRow, vAdjRow;
                     if ((i == 0) || ((i == (image->width - 1)) && ((i % 2) != 0))) {
                         uAdjCol = 0;
                         vAdjCol = 0;
@@ -538,8 +538,8 @@
                         unormV[1][1] = *((const uint16_t *)&vPlane[(uvJ * vRowBytes) + (uvI * yuvChannelBytes) + vAdjCol + vAdjRow]);
 
                         // clamp incoming data to protect against bad LUT lookups
-                        for (int bJ = 0; bJ < 2; ++bJ) {
-                            for (int bI = 0; bI < 2; ++bI) {
+                        for (uint32_t bJ = 0; bJ < 2; ++bJ) {
+                            for (uint32_t bI = 0; bI < 2; ++bI) {
                                 unormU[bI][bJ] = AVIF_MIN(unormU[bI][bJ], yuvMaxChannel);
                                 unormV[bI][bJ] = AVIF_MIN(unormV[bI][bJ], yuvMaxChannel);
                             }