Commit 10a1a2285 for imagemagick.org

commit 10a1a2285659fe1f8978f338319727dfda19500d
Author: Cristy <urban-warrior@imagemagick.org>
Date:   Mon May 11 19:14:38 2026 -0400

    https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-g5mf-wqq5-vwg6

diff --git a/coders/png.c b/coders/png.c
index 027e7b73d..9d0c94278 100644
--- a/coders/png.c
+++ b/coders/png.c
@@ -464,6 +464,8 @@ static SemaphoreInfo
   waste more memory.
 */
 #define MNG_MAX_OBJECTS 256
+#define MNG_MAX_LOOP_NESTING 256
+#define MNG_MAX_LOOP_OPS 1000000

 /*
   Maximum valid size_t in PNG/MNG chunks is (2^31)-1
@@ -578,7 +580,7 @@ typedef struct _MngReadInfo
     have_global_srgb;

   MagickOffsetType
-    loop_jump[256];
+    loop_jump[MNG_MAX_LOOP_NESTING];

   MngBox
     clip,
@@ -613,8 +615,8 @@ typedef struct _MngReadInfo

   ssize_t
     image_found,
-    loop_count[256],
-    loop_iteration[256],
+    loop_count[MNG_MAX_LOOP_NESTING],
+    loop_iteration[MNG_MAX_LOOP_NESTING],
     scenes_found,
     x_off[MNG_MAX_OBJECTS],
     y_off[MNG_MAX_OBJECTS];
@@ -623,7 +625,7 @@ typedef struct _MngReadInfo
     /* These flags could be combined into one byte */
     exists[MNG_MAX_OBJECTS],
     frozen[MNG_MAX_OBJECTS],
-    loop_active[256],
+    loop_active[MNG_MAX_LOOP_NESTING],
     invisible[MNG_MAX_OBJECTS],
     viewable[MNG_MAX_OBJECTS];

@@ -5053,7 +5055,7 @@ static Image *ReadOneMNGImage(MngReadInfo* mng_info,
     final_image_delay,
     frame_delay,
     insert_layers,
-    number_loops=0,
+    number_loop_ops=0,
     mng_iterations=1,
     simplicity=0,
     subframe_height=0,
@@ -5837,6 +5839,8 @@ static Image *ReadOneMNGImage(MngReadInfo* mng_info,
         if (memcmp(type,mng_LOOP,4) == 0)
           {
             ssize_t loop_iters=1;
+            if (number_loop_ops++ > MNG_MAX_LOOP_OPS)
+              ThrowReaderException(ResourceLimitError,"too many LOOP/ENDL ops");
             if (length > 4)
               {
                 loop_level=chunk[0];
@@ -5855,9 +5859,6 @@ static Image *ReadOneMNGImage(MngReadInfo* mng_info,

                 else
                   {
-                    if ((MagickSizeType) number_loops+loop_iters > GetMagickResourceLimit(ListLengthResource))
-                      ThrowReaderException(ResourceLimitError,
-                        "ListLengthExceedsLimit");
                     if (loop_iters >= 2147483647L)
                       loop_iters=2147483647L;
                     if (image_info->number_scenes != 0)
@@ -5865,7 +5866,6 @@ static Image *ReadOneMNGImage(MngReadInfo* mng_info,
                         loop_iters=(ssize_t) image_info->number_scenes;
                     mng_info->loop_jump[loop_level]=TellBlob(image);
                     mng_info->loop_count[loop_level]=loop_iters;
-                    number_loops+=loop_iters;
                   }

                 mng_info->loop_iteration[loop_level]=0;
@@ -5876,6 +5876,8 @@ static Image *ReadOneMNGImage(MngReadInfo* mng_info,

         if (memcmp(type,mng_ENDL,4) == 0)
           {
+            if (number_loop_ops++ > MNG_MAX_LOOP_OPS)
+              ThrowReaderException(ResourceLimitError,"too many LOOP/ENDL ops");
             if (length > 0)
               {
                 loop_level=chunk[0];
@@ -5907,9 +5909,8 @@ static Image *ReadOneMNGImage(MngReadInfo* mng_info,

                         if (mng_info->loop_count[loop_level] > 0)
                           {
-                            offset=
-                              SeekBlob(image,mng_info->loop_jump[loop_level],
-                              SEEK_SET);
+                            offset=SeekBlob(image,
+                              mng_info->loop_jump[loop_level],SEEK_SET);

                             if (offset < 0)
                               {