Commit a75aab273 for imagemagick.org

commit a75aab27367c4a0e57e137eb6cc5369001c85aec
Author: Cristy <urban-warrior@imagemagick.org>
Date:   Sat Oct 3 13:53:54 2026 -0400

    https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-4wfv-467j-fqh9

diff --git a/MagickCore/color.c b/MagickCore/color.c
index affac046a..e43f88d3f 100644
--- a/MagickCore/color.c
+++ b/MagickCore/color.c
@@ -2031,21 +2031,36 @@ static MagickBooleanType LoadColorCache(LinkedListInfo *cache,const char *xml,
         int
           bracket_depth = 0,
           quote = 0;
-
+
         /*
-          DOCTYPE element.
+          Parse DOCTYPE element.
         */
         for ( ; *q != '\0'; q++)
         {
+          /*
+            Skip DTD comments.
+          */
+          if ((quote == 0) && (q[0] == '<') && (q[1] == '!') &&
+              (q[2] == '-') && (q[3] == '-'))
+            {
+              q+=4;
+              while ((*q != '\0') && !((q[0] == '-') && (q[1] == '-') &&
+                     (q[2] == '>')))
+                q++;
+              if (*q == '\0')
+                break;
+              q+=2;
+              continue;
+            }
           if (quote != 0)
             {
               if (*q == quote)
-                quote=0;
+                quote = 0;
             }
           else
             {
               if ((*q == '"') || (*q == '\''))
-                quote=(*q);
+                quote = (*q);
               else
                 if (*q == '[')
                   bracket_depth++;
@@ -2058,11 +2073,20 @@ static MagickBooleanType LoadColorCache(LinkedListInfo *cache,const char *xml,
                   else
                     if ((*q == '>') && (bracket_depth == 0))
                       {
-                        q++;   /* consume final '>' */
+                        q++;
                         break;
                       }
             }
         }
+        if (*q == '\0')
+          {
+            /*
+              Detect unterminated DOCTYPE.
+            */
+            (void) ThrowMagickException(exception,GetMagickModule(),
+              ConfigureError,"UnterminatedDOCTYPE","`%s'",filename);
+            break;
+          }
         continue;
       }
     if (LocaleNCompare(keyword,"<!--",4) == 0)
diff --git a/MagickCore/configure.c b/MagickCore/configure.c
index 5d7660e70..90308092e 100644
--- a/MagickCore/configure.c
+++ b/MagickCore/configure.c
@@ -1198,21 +1198,36 @@ static MagickBooleanType LoadConfigureCache(LinkedListInfo *cache,
         int
           bracket_depth = 0,
           quote = 0;
-
+
         /*
-          DOCTYPE element.
+          Parse DOCTYPE element.
         */
         for ( ; *q != '\0'; q++)
         {
+          /*
+            Skip DTD comments.
+          */
+          if ((quote == 0) && (q[0] == '<') && (q[1] == '!') &&
+              (q[2] == '-') && (q[3] == '-'))
+            {
+              q+=4;
+              while ((*q != '\0') && !((q[0] == '-') && (q[1] == '-') &&
+                     (q[2] == '>')))
+                q++;
+              if (*q == '\0')
+                break;
+              q+=2;
+              continue;
+            }
           if (quote != 0)
             {
               if (*q == quote)
-                quote=0;
+                quote = 0;
             }
           else
             {
               if ((*q == '"') || (*q == '\''))
-                quote=(*q);
+                quote = (*q);
               else
                 if (*q == '[')
                   bracket_depth++;
@@ -1225,11 +1240,20 @@ static MagickBooleanType LoadConfigureCache(LinkedListInfo *cache,
                   else
                     if ((*q == '>') && (bracket_depth == 0))
                       {
-                        q++;   /* consume final '>' */
+                        q++;
                         break;
                       }
             }
         }
+        if (*q == '\0')
+          {
+            /*
+              Detect unterminated DOCTYPE.
+            */
+            (void) ThrowMagickException(exception,GetMagickModule(),
+              ConfigureError,"UnterminatedDOCTYPE","`%s'",filename);
+            break;
+          }
         continue;
       }
     if (LocaleNCompare(keyword,"<!--",4) == 0)
diff --git a/MagickCore/delegate.c b/MagickCore/delegate.c
index d8b59cc46..9bdc5c7a7 100644
--- a/MagickCore/delegate.c
+++ b/MagickCore/delegate.c
@@ -2148,21 +2148,36 @@ static MagickBooleanType LoadDelegateCache(LinkedListInfo *cache,
         int
           bracket_depth = 0,
           quote = 0;
-
+
         /*
-          DOCTYPE element.
+          Parse DOCTYPE element.
         */
         for ( ; *q != '\0'; q++)
         {
+          /*
+            Skip DTD comments.
+          */
+          if ((quote == 0) && (q[0] == '<') && (q[1] == '!') &&
+              (q[2] == '-') && (q[3] == '-'))
+            {
+              q+=4;
+              while ((*q != '\0') && !((q[0] == '-') && (q[1] == '-') &&
+                     (q[2] == '>')))
+                q++;
+              if (*q == '\0')
+                break;
+              q+=2;
+              continue;
+            }
           if (quote != 0)
             {
               if (*q == quote)
-                quote=0;
+                quote = 0;
             }
           else
             {
               if ((*q == '"') || (*q == '\''))
-                quote=(*q);
+                quote = (*q);
               else
                 if (*q == '[')
                   bracket_depth++;
@@ -2175,11 +2190,20 @@ static MagickBooleanType LoadDelegateCache(LinkedListInfo *cache,
                   else
                     if ((*q == '>') && (bracket_depth == 0))
                       {
-                        q++;   /* consume final '>' */
+                        q++;
                         break;
                       }
             }
         }
+        if (*q == '\0')
+          {
+            /*
+              Detect unterminated DOCTYPE.
+            */
+            (void) ThrowMagickException(exception,GetMagickModule(),
+              ConfigureError,"UnterminatedDOCTYPE","`%s'",filename);
+            break;
+          }
         continue;
       }
     if (LocaleNCompare(keyword,"<!--",4) == 0)
diff --git a/MagickCore/locale.c b/MagickCore/locale.c
index e94340e67..262d0134c 100644
--- a/MagickCore/locale.c
+++ b/MagickCore/locale.c
@@ -1222,21 +1222,36 @@ static MagickBooleanType LoadLocaleCache(SplayTreeInfo *cache,const char *xml,
         int
           bracket_depth = 0,
           quote = 0;
-
+
         /*
-          DOCTYPE element.
+          Parse DOCTYPE element.
         */
         for ( ; *q != '\0'; q++)
         {
+          /*
+            Skip DTD comments.
+          */
+          if ((quote == 0) && (q[0] == '<') && (q[1] == '!') &&
+              (q[2] == '-') && (q[3] == '-'))
+            {
+              q+=4;
+              while ((*q != '\0') && !((q[0] == '-') && (q[1] == '-') &&
+                     (q[2] == '>')))
+                q++;
+              if (*q == '\0')
+                break;
+              q+=2;
+              continue;
+            }
           if (quote != 0)
             {
               if (*q == quote)
-                quote=0;
+                quote = 0;
             }
           else
             {
               if ((*q == '"') || (*q == '\''))
-                quote=(*q);
+                quote = (*q);
               else
                 if (*q == '[')
                   bracket_depth++;
@@ -1249,11 +1264,20 @@ static MagickBooleanType LoadLocaleCache(SplayTreeInfo *cache,const char *xml,
                   else
                     if ((*q == '>') && (bracket_depth == 0))
                       {
-                        q++;   /* consume final '>' */
+                        q++;
                         break;
                       }
             }
         }
+        if (*q == '\0')
+          {
+            /*
+              Detect unterminated DOCTYPE.
+            */
+            (void) ThrowMagickException(exception,GetMagickModule(),
+              ConfigureError,"UnterminatedDOCTYPE","`%s'",filename);
+            break;
+          }
         continue;
       }
     if (LocaleNCompare(keyword,"<!--",4) == 0)
diff --git a/MagickCore/log.c b/MagickCore/log.c
index f9377e1f8..44392cc7c 100644
--- a/MagickCore/log.c
+++ b/MagickCore/log.c
@@ -949,21 +949,36 @@ static MagickBooleanType LoadLogCache(LinkedListInfo *cache,const char *xml,
         int
           bracket_depth = 0,
           quote = 0;
-
+
         /*
-          DOCTYPE element.
+          Parse DOCTYPE element.
         */
         for ( ; *q != '\0'; q++)
         {
+          /*
+            Skip DTD comments.
+          */
+          if ((quote == 0) && (q[0] == '<') && (q[1] == '!') &&
+              (q[2] == '-') && (q[3] == '-'))
+            {
+              q+=4;
+              while ((*q != '\0') && !((q[0] == '-') && (q[1] == '-') &&
+                     (q[2] == '>')))
+                q++;
+              if (*q == '\0')
+                break;
+              q+=2;
+              continue;
+            }
           if (quote != 0)
             {
               if (*q == quote)
-                quote=0;
+                quote = 0;
             }
           else
             {
               if ((*q == '"') || (*q == '\''))
-                quote=(*q);
+                quote = (*q);
               else
                 if (*q == '[')
                   bracket_depth++;
@@ -976,11 +991,20 @@ static MagickBooleanType LoadLogCache(LinkedListInfo *cache,const char *xml,
                   else
                     if ((*q == '>') && (bracket_depth == 0))
                       {
-                        q++;   /* consume final '>' */
+                        q++;
                         break;
                       }
             }
         }
+        if (*q == '\0')
+          {
+            /*
+              Detect unterminated DOCTYPE.
+            */
+            (void) ThrowMagickException(exception,GetMagickModule(),
+              ConfigureError,"UnterminatedDOCTYPE","`%s'",filename);
+            break;
+          }
         continue;
       }
     if (LocaleNCompare(keyword,"<!--",4) == 0)
diff --git a/MagickCore/opencl.c b/MagickCore/opencl.c
index f1bd70ba9..ba353178d 100644
--- a/MagickCore/opencl.c
+++ b/MagickCore/opencl.c
@@ -804,21 +804,36 @@ static void LoadOpenCLDeviceBenchmark(MagickCLEnv clEnv,const char *xml)
         int
           bracket_depth = 0,
           quote = 0;
-
+
         /*
-          DOCTYPE element.
+          Parse DOCTYPE element.
         */
         for ( ; *q != '\0'; q++)
         {
+          /*
+            Skip DTD comments.
+          */
+          if ((quote == 0) && (q[0] == '<') && (q[1] == '!') &&
+              (q[2] == '-') && (q[3] == '-'))
+            {
+              q+=4;
+              while ((*q != '\0') && !((q[0] == '-') && (q[1] == '-') &&
+                     (q[2] == '>')))
+                q++;
+              if (*q == '\0')
+                break;
+              q+=2;
+              continue;
+            }
           if (quote != 0)
             {
               if (*q == quote)
-                quote=0;
+                quote = 0;
             }
           else
             {
               if ((*q == '"') || (*q == '\''))
-                quote=(*q);
+                quote = (*q);
               else
                 if (*q == '[')
                   bracket_depth++;
@@ -831,11 +846,20 @@ static void LoadOpenCLDeviceBenchmark(MagickCLEnv clEnv,const char *xml)
                   else
                     if ((*q == '>') && (bracket_depth == 0))
                       {
-                        q++;   /* consume final '>' */
+                        q++;
                         break;
                       }
             }
         }
+        if (*q == '\0')
+          {
+            /*
+              Detect unterminated DOCTYPE.
+            */
+            (void) ThrowMagickException(exception,GetMagickModule(),
+              ConfigureError,"UnterminatedDOCTYPE","`%s'",filename);
+            break;
+          }
         continue;
       }
     if (LocaleNCompare(keyword,"<!--",4) == 0)
diff --git a/MagickCore/policy.c b/MagickCore/policy.c
index 85d66468a..721dda247 100644
--- a/MagickCore/policy.c
+++ b/MagickCore/policy.c
@@ -1150,21 +1150,36 @@ static MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,
         int
           bracket_depth = 0,
           quote = 0;
-
+
         /*
-          DOCTYPE element.
+          Parse DOCTYPE element.
         */
         for ( ; *q != '\0'; q++)
         {
+          /*
+            Skip DTD comments.
+          */
+          if ((quote == 0) && (q[0] == '<') && (q[1] == '!') &&
+              (q[2] == '-') && (q[3] == '-'))
+            {
+              q+=4;
+              while ((*q != '\0') && !((q[0] == '-') && (q[1] == '-') &&
+                     (q[2] == '>')))
+                q++;
+              if (*q == '\0')
+                break;
+              q+=2;
+              continue;
+            }
           if (quote != 0)
             {
               if (*q == quote)
-                quote=0;
+                quote = 0;
             }
           else
             {
               if ((*q == '"') || (*q == '\''))
-                quote=(*q);
+                quote = (*q);
               else
                 if (*q == '[')
                   bracket_depth++;
@@ -1177,11 +1192,20 @@ static MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,
                   else
                     if ((*q == '>') && (bracket_depth == 0))
                       {
-                        q++;   /* consume final '>' */
+                        q++;
                         break;
                       }
             }
         }
+        if (*q == '\0')
+          {
+            /*
+              Detect unterminated DOCTYPE.
+            */
+            (void) ThrowMagickException(exception,GetMagickModule(),
+              ConfigureError,"UnterminatedDOCTYPE","`%s'",filename);
+            break;
+          }
         continue;
       }
     if (LocaleNCompare(keyword,"<!--",4) == 0)
diff --git a/MagickCore/type.c b/MagickCore/type.c
index 5830ff19b..eb5464f3c 100644
--- a/MagickCore/type.c
+++ b/MagickCore/type.c
@@ -1123,21 +1123,36 @@ static MagickBooleanType LoadTypeCache(SplayTreeInfo *cache,const char *xml,
         int
           bracket_depth = 0,
           quote = 0;
-
+
         /*
-          DOCTYPE element.
+          Parse DOCTYPE element.
         */
         for ( ; *q != '\0'; q++)
         {
+          /*
+            Skip DTD comments.
+          */
+          if ((quote == 0) && (q[0] == '<') && (q[1] == '!') &&
+              (q[2] == '-') && (q[3] == '-'))
+            {
+              q+=4;
+              while ((*q != '\0') && !((q[0] == '-') && (q[1] == '-') &&
+                     (q[2] == '>')))
+                q++;
+              if (*q == '\0')
+                break;
+              q+=2;
+              continue;
+            }
           if (quote != 0)
             {
               if (*q == quote)
-                quote=0;
+                quote = 0;
             }
           else
             {
               if ((*q == '"') || (*q == '\''))
-                quote=(*q);
+                quote = (*q);
               else
                 if (*q == '[')
                   bracket_depth++;
@@ -1150,11 +1165,20 @@ static MagickBooleanType LoadTypeCache(SplayTreeInfo *cache,const char *xml,
                   else
                     if ((*q == '>') && (bracket_depth == 0))
                       {
-                        q++;   /* consume final '>' */
+                        q++;
                         break;
                       }
             }
         }
+        if (*q == '\0')
+          {
+            /*
+              Detect unterminated DOCTYPE.
+            */
+            (void) ThrowMagickException(exception,GetMagickModule(),
+              ConfigureError,"UnterminatedDOCTYPE","`%s'",filename);
+            break;
+          }
         continue;
       }
     if (LocaleNCompare(keyword,"<!--",4) == 0)