Commit 504231bb2 for imagemagick.org

commit 504231bb26021ba66d9633f34ba15ded32637b5e
Author: Dirk Lemstra <dirk@lemstra.org>
Date:   Mon Oct 5 21:17:46 2026 +0200

    Improved skipping of comments and return a failure when comments or doctype are not terminated.

diff --git a/MagickCore/color.c b/MagickCore/color.c
index 69b03f88a..0bc8c9836 100644
--- a/MagickCore/color.c
+++ b/MagickCore/color.c
@@ -837,7 +837,7 @@ static LinkedListInfo *AcquireColorCache(const char *filename,
   LinkedListInfo
     *cache;

-  MagickStatusType
+  MagickBooleanType
     status;

   ssize_t
@@ -860,8 +860,9 @@ static LinkedListInfo *AcquireColorCache(const char *filename,
     option=(const StringInfo *) GetNextValueInLinkedList(options);
     while (option != (const StringInfo *) NULL)
     {
-      status&=(MagickStatusType) LoadColorCache(cache,(const char *)
-        GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
+      if (LoadColorCache(cache,(const char *) GetStringInfoDatum(option),
+          GetStringInfoPath(option),0,exception) == MagickFalse)
+        status=MagickFalse;
       option=(const StringInfo *) GetNextValueInLinkedList(options);
     }
     options=DestroyConfigureOptions(options);
@@ -899,7 +900,8 @@ static LinkedListInfo *AcquireColorCache(const char *filename,
     color_info->compliance=(ComplianceType) p->compliance;
     color_info->exempt=MagickTrue;
     color_info->signature=MagickCoreSignature;
-    status&=(MagickStatusType) AppendValueToLinkedList(cache,color_info);
+    if (AppendValueToLinkedList(cache,color_info) == MagickFalse)
+      status=MagickFalse;
     if (status == MagickFalse)
       (void) ThrowMagickException(exception,GetMagickModule(),
         ResourceLimitError,"MemoryAllocationFailed","`%s'",color_info->name);
@@ -2000,7 +2002,7 @@ static MagickBooleanType LoadColorCache(LinkedListInfo *cache,const char *xml,
   const char
     *q;

-  MagickStatusType
+  MagickBooleanType
     status;

   size_t
@@ -2022,6 +2024,13 @@ static MagickBooleanType LoadColorCache(LinkedListInfo *cache,const char *xml,
     /*
       Interpret XML.
     */
+    if (SkipXMLComment(&q) == MagickFalse)
+      {
+        (void) ThrowMagickException(exception,GetMagickModule(),
+          ConfigureError,"UnterminatedComment","`%s'",filename);
+        status=MagickFalse;
+        break;
+      }
     (void) GetNextToken(q,&q,extent,token);
     if (*token == '\0')
       break;
@@ -2035,18 +2044,11 @@ static MagickBooleanType LoadColorCache(LinkedListInfo *cache,const char *xml,
             */
             (void) ThrowMagickException(exception,GetMagickModule(),
               ConfigureError,"UnterminatedDOCTYPE","`%s'",filename);
+            status=MagickFalse;
             break;
           }
         continue;
       }
-    if (LocaleNCompare(keyword,"<!--",4) == 0)
-      {
-        /*
-          Comment element.
-        */
-        SkipXMLComment(&q);
-        continue;
-      }
     if (LocaleCompare(keyword,"<include") == 0)
       {
         /*
@@ -2081,8 +2083,8 @@ static MagickBooleanType LoadColorCache(LinkedListInfo *cache,const char *xml,
                   file_xml=FileToXML(path,~0UL);
                   if (file_xml != (char *) NULL)
                     {
-                      status&=(MagickStatusType) LoadColorCache(cache,file_xml,
-                        path,depth+1,exception);
+                      if (LoadColorCache(cache,file_xml,path,depth+1,exception) == MagickFalse)
+                        status=MagickFalse;
                       file_xml=DestroyString(file_xml);
                     }
                 }
@@ -2173,7 +2175,7 @@ static MagickBooleanType LoadColorCache(LinkedListInfo *cache,const char *xml,
     }
   }
   token=(char *) RelinquishMagickMemory(token);
-  return(status != 0 ? MagickTrue : MagickFalse);
+  return(status);
 }
 #endif

diff --git a/MagickCore/configure.c b/MagickCore/configure.c
index 2ac9dd29f..ea7675e5b 100644
--- a/MagickCore/configure.c
+++ b/MagickCore/configure.c
@@ -1169,7 +1169,7 @@ static MagickBooleanType LoadConfigureCache(LinkedListInfo *cache,
   const char
     *q;

-  MagickStatusType
+  MagickBooleanType
     status;

   size_t
@@ -1189,6 +1189,13 @@ static MagickBooleanType LoadConfigureCache(LinkedListInfo *cache,
     /*
       Interpret XML.
     */
+    if (SkipXMLComment(&q) == MagickFalse)
+      {
+        (void) ThrowMagickException(exception,GetMagickModule(),
+          ConfigureError,"UnterminatedComment","`%s'",filename);
+        status=MagickFalse;
+        break;
+      }
     (void) GetNextToken(q,&q,extent,token);
     if (*token == '\0')
       break;
@@ -1202,18 +1209,11 @@ static MagickBooleanType LoadConfigureCache(LinkedListInfo *cache,
             */
             (void) ThrowMagickException(exception,GetMagickModule(),
               ConfigureError,"UnterminatedDOCTYPE","`%s'",filename);
+            status=MagickFalse;
             break;
           }
         continue;
       }
-    if (LocaleNCompare(keyword,"<!--",4) == 0)
-      {
-        /*
-          Comment element.
-        */
-        SkipXMLComment(&q);
-        continue;
-      }
     if (LocaleCompare(keyword,"<include") == 0)
       {
         /*
@@ -1248,8 +1248,8 @@ static MagickBooleanType LoadConfigureCache(LinkedListInfo *cache,
                   file_xml=FileToXML(path,~0UL);
                   if (file_xml != (char *) NULL)
                     {
-                      status&=(MagickStatusType) LoadConfigureCache(cache,
-                        file_xml,path,depth+1,exception);
+                      if (LoadConfigureCache(cache,file_xml,path,depth+1,exception) == MagickFalse)
+                        status=MagickFalse;
                       file_xml=DestroyString(file_xml);
                     }
                 }
@@ -1328,6 +1328,6 @@ static MagickBooleanType LoadConfigureCache(LinkedListInfo *cache,
     }
   }
   token=(char *) RelinquishMagickMemory(token);
-  return(status != 0 ? MagickTrue : MagickFalse);
+  return(status);
 }
 #endif
diff --git a/MagickCore/delegate.c b/MagickCore/delegate.c
index 1b8178fde..deba86dd8 100644
--- a/MagickCore/delegate.c
+++ b/MagickCore/delegate.c
@@ -2117,7 +2117,7 @@ static MagickBooleanType LoadDelegateCache(LinkedListInfo *cache,
   DelegateInfo
     *delegate_info;

-  MagickStatusType
+  MagickBooleanType
     status;

   size_t
@@ -2139,6 +2139,13 @@ static MagickBooleanType LoadDelegateCache(LinkedListInfo *cache,
     /*
       Interpret XML.
     */
+    if (SkipXMLComment(&q) == MagickFalse)
+      {
+        (void) ThrowMagickException(exception,GetMagickModule(),
+          ConfigureError,"UnterminatedComment","`%s'",filename);
+        status=MagickFalse;
+        break;
+      }
     (void) GetNextToken(q,&q,extent,token);
     if (*token == '\0')
       break;
@@ -2152,18 +2159,11 @@ static MagickBooleanType LoadDelegateCache(LinkedListInfo *cache,
             */
             (void) ThrowMagickException(exception,GetMagickModule(),
               ConfigureError,"UnterminatedDOCTYPE","`%s'",filename);
+            status=MagickFalse;
             break;
           }
         continue;
       }
-    if (LocaleNCompare(keyword,"<!--",4) == 0)
-      {
-        /*
-          Comment element.
-        */
-        SkipXMLComment(&q);
-        continue;
-      }
     if (LocaleCompare(keyword,"<include") == 0)
       {
         /*
@@ -2198,8 +2198,8 @@ static MagickBooleanType LoadDelegateCache(LinkedListInfo *cache,
                   file_xml=FileToXML(path,~0UL);
                   if (file_xml != (char *) NULL)
                     {
-                      status&=(MagickStatusType) LoadDelegateCache(cache,
-                        file_xml,path,depth+1,exception);
+                      if (LoadDelegateCache(cache,file_xml,path,depth+1,exception) == MagickFalse)
+                        status=MagickFalse;
                       file_xml=DestroyString(file_xml);
                     }
                 }
@@ -2342,5 +2342,5 @@ static MagickBooleanType LoadDelegateCache(LinkedListInfo *cache,
     }
   }
   token=(char *) RelinquishMagickMemory(token);
-  return(status != 0 ? MagickTrue : MagickFalse);
+  return(status);
 }
diff --git a/MagickCore/locale.c b/MagickCore/locale.c
index 65a25e2c0..77c445e48 100644
--- a/MagickCore/locale.c
+++ b/MagickCore/locale.c
@@ -1184,7 +1184,7 @@ static MagickBooleanType LoadLocaleCache(SplayTreeInfo *cache,const char *xml,
   LocaleInfo
     *locale_info;

-  MagickStatusType
+  MagickBooleanType
     status;

   char
@@ -1213,6 +1213,13 @@ static MagickBooleanType LoadLocaleCache(SplayTreeInfo *cache,const char *xml,
     /*
       Interpret XML.
     */
+    if (SkipXMLComment(&q) == MagickFalse)
+      {
+        (void) ThrowMagickException(exception,GetMagickModule(),
+          ConfigureError,"UnterminatedComment","`%s'",filename);
+        status=MagickFalse;
+        break;
+      }
     (void) GetNextToken(q,&q,extent,token);
     if (*token == '\0')
       break;
@@ -1226,18 +1233,11 @@ static MagickBooleanType LoadLocaleCache(SplayTreeInfo *cache,const char *xml,
             */
             (void) ThrowMagickException(exception,GetMagickModule(),
               ConfigureError,"UnterminatedDOCTYPE","`%s'",filename);
+            status=MagickFalse;
             break;
           }
         continue;
       }
-    if (LocaleNCompare(keyword,"<!--",4) == 0)
-      {
-        /*
-          Comment element.
-        */
-        SkipXMLComment(&q);
-        continue;
-      }
     if (LocaleCompare(keyword,"<include") == 0)
       {
         /*
@@ -1279,8 +1279,8 @@ static MagickBooleanType LoadLocaleCache(SplayTreeInfo *cache,const char *xml,
                   file_xml=FileToXML(path,~0UL);
                   if (file_xml != (char *) NULL)
                     {
-                      status&=(MagickStatusType) LoadLocaleCache(cache,file_xml,
-                        path,locale,depth+1,exception);
+                      if (LoadLocaleCache(cache,file_xml,path,locale,depth+1,exception) == MagickFalse)
+                        status=MagickFalse;
                       file_xml=DestroyString(file_xml);
                     }
                 }
@@ -1387,7 +1387,7 @@ static MagickBooleanType LoadLocaleCache(SplayTreeInfo *cache,const char *xml,
   }
   token=(char *) RelinquishMagickMemory(token);
   (void) SetFatalErrorHandler(fatal_handler);
-  return(status != 0 ? MagickTrue : MagickFalse);
+  return(status);
 }

 /*
diff --git a/MagickCore/log.c b/MagickCore/log.c
index c3b777834..c409f9e77 100644
--- a/MagickCore/log.c
+++ b/MagickCore/log.c
@@ -271,7 +271,7 @@ static LinkedListInfo *AcquireLogCache(const char *filename,
   LinkedListInfo
     *cache;

-  MagickStatusType
+  MagickBooleanType
     status;

   ssize_t
@@ -294,8 +294,9 @@ static LinkedListInfo *AcquireLogCache(const char *filename,
     option=(const StringInfo *) GetNextValueInLinkedList(options);
     while (option != (const StringInfo *) NULL)
     {
-      status&=(MagickStatusType) LoadLogCache(cache,(const char *)
-        GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
+      if (LoadLogCache(cache,(const char *) GetStringInfoDatum(option),
+          GetStringInfoPath(option),0,exception) == MagickFalse)
+        status=MagickFalse;
       option=(const StringInfo *) GetNextValueInLinkedList(options);
     }
     options=DestroyConfigureOptions(options);
@@ -330,7 +331,8 @@ static LinkedListInfo *AcquireLogCache(const char *filename,
     log_info->filename=ConstantString(p->filename);
     log_info->format=ConstantString(p->format);
     log_info->signature=MagickCoreSignature;
-    status&=(MagickStatusType) AppendValueToLinkedList(cache,log_info);
+    if (AppendValueToLinkedList(cache,log_info) == MagickFalse)
+      status=MagickFalse;
     if (status == MagickFalse)
       (void) ThrowMagickException(exception,GetMagickModule(),
         ResourceLimitError,"MemoryAllocationFailed","`%s'",log_info->name);
@@ -921,7 +923,7 @@ static MagickBooleanType LoadLogCache(LinkedListInfo *cache,const char *xml,
   LogInfo
     *log_info = (LogInfo *) NULL;

-  MagickStatusType
+  MagickBooleanType
     status;

   size_t
@@ -940,6 +942,13 @@ static MagickBooleanType LoadLogCache(LinkedListInfo *cache,const char *xml,
     /*
       Interpret XML.
     */
+    if (SkipXMLComment(&q) == MagickFalse)
+      {
+        (void) ThrowMagickException(exception,GetMagickModule(),
+          ConfigureError,"UnterminatedComment","`%s'",filename);
+        status=MagickFalse;
+        break;
+      }
     (void) GetNextToken(q,&q,extent,token);
     if (*token == '\0')
       break;
@@ -953,18 +962,11 @@ static MagickBooleanType LoadLogCache(LinkedListInfo *cache,const char *xml,
             */
             (void) ThrowMagickException(exception,GetMagickModule(),
               ConfigureError,"UnterminatedDOCTYPE","`%s'",filename);
+            status=MagickFalse;
             break;
           }
         continue;
       }
-    if (LocaleNCompare(keyword,"<!--",4) == 0)
-      {
-        /*
-          Comment element.
-        */
-        SkipXMLComment(&q);
-        continue;
-      }
     if (LocaleCompare(keyword,"<include") == 0)
       {
         /*
@@ -999,8 +1001,8 @@ static MagickBooleanType LoadLogCache(LinkedListInfo *cache,const char *xml,
                   file_xml=FileToXML(path,~0UL);
                   if (file_xml != (char *) NULL)
                     {
-                      status&=(MagickStatusType) LoadLogCache(cache,file_xml,
-                        path,depth+1,exception);
+                      if (LoadLogCache(cache,file_xml,path,depth+1,exception) == MagickFalse)
+                        status=MagickFalse;
                       file_xml=DestroyString(file_xml);
                     }
                 }
@@ -1120,7 +1122,7 @@ static MagickBooleanType LoadLogCache(LinkedListInfo *cache,const char *xml,
   token=DestroyString(token);
   if (cache == (LinkedListInfo *) NULL)
     return(MagickFalse);
-  return(status != 0 ? MagickTrue : MagickFalse);
+  return(status);
 }
 #endif

diff --git a/MagickCore/opencl.c b/MagickCore/opencl.c
index 39ed0ea8e..f5e9722be 100644
--- a/MagickCore/opencl.c
+++ b/MagickCore/opencl.c
@@ -796,6 +796,8 @@ static void LoadOpenCLDeviceBenchmark(MagickCLEnv clEnv,const char *xml)
     /*
       Interpret XML.
     */
+    if (SkipXMLComment(&q) == MagickFalse)
+      break;
     (void) GetNextToken(q,&q,extent,token);
     if (*token == '\0')
       break;
@@ -806,14 +808,6 @@ static void LoadOpenCLDeviceBenchmark(MagickCLEnv clEnv,const char *xml)
           break;
         continue;
       }
-    if (LocaleNCompare(keyword,"<!--",4) == 0)
-      {
-        /*
-          Comment element.
-        */
-        SkipXMLComment(&q);
-        continue;
-      }
     if (LocaleCompare(keyword,"<device") == 0)
       {
         /*
diff --git a/MagickCore/policy.c b/MagickCore/policy.c
index d314ace49..b183a3cde 100644
--- a/MagickCore/policy.c
+++ b/MagickCore/policy.c
@@ -1111,7 +1111,7 @@ static MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,
   const char
     *q;

-  MagickStatusType
+  MagickBooleanType
     status;

   PolicyInfo
@@ -1136,6 +1136,13 @@ static MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,
     /*
       Interpret XML.
     */
+    if (SkipXMLComment(&q) == MagickFalse)
+      {
+        (void) ThrowMagickException(exception,GetMagickModule(),
+          ConfigureError,"UnterminatedComment","`%s'",filename);
+        status=MagickFalse;
+        break;
+      }
     (void) GetNextToken(q,&q,extent,token);
     if (*token == '\0')
       break;
@@ -1149,18 +1156,11 @@ static MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,
             */
             (void) ThrowMagickException(exception,GetMagickModule(),
               ConfigureError,"UnterminatedDOCTYPE","`%s'",filename);
+            status=MagickFalse;
             break;
           }
         continue;
       }
-    if (LocaleNCompare(keyword,"<!--",4) == 0)
-      {
-        /*
-          Comment element.
-        */
-        SkipXMLComment(&q);
-        continue;
-      }
     if (LocaleCompare(keyword,"<include") == 0)
       {
         /*
@@ -1195,8 +1195,8 @@ static MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,
                   file_xml=FileToXML(path,~0UL);
                   if (file_xml != (char *) NULL)
                     {
-                      status&=(MagickStatusType) LoadPolicyCache(cache,file_xml,
-                        path,depth+1,exception);
+                      if (LoadPolicyCache(cache,file_xml,path,depth+1,exception) == MagickFalse)
+                        status=MagickFalse;
                       file_xml=DestroyString(file_xml);
                     }
                 }
@@ -1303,7 +1303,7 @@ static MagickBooleanType LoadPolicyCache(LinkedListInfo *cache,
     }
   }
   token=(char *) RelinquishMagickMemory(token);
-  return(status != 0 ? MagickTrue : MagickFalse);
+  return(status);
 }

 /*
diff --git a/MagickCore/type.c b/MagickCore/type.c
index 9fc9c5cda..08aea4b0d 100644
--- a/MagickCore/type.c
+++ b/MagickCore/type.c
@@ -1080,7 +1080,7 @@ static MagickBooleanType LoadTypeCache(SplayTreeInfo *cache,const char *xml,
   const char
     *q;

-  MagickStatusType
+  MagickBooleanType
     status;

   size_t
@@ -1115,6 +1115,13 @@ static MagickBooleanType LoadTypeCache(SplayTreeInfo *cache,const char *xml,
     /*
       Interpret XML.
     */
+    if (SkipXMLComment(&q) == MagickFalse)
+      {
+        (void) ThrowMagickException(exception,GetMagickModule(),
+          ConfigureError,"UnterminatedComment","`%s'",filename);
+        status=MagickFalse;
+        break;
+      }
     (void) GetNextToken(q,&q,extent,token);
     if (*token == '\0')
       break;
@@ -1128,18 +1135,11 @@ static MagickBooleanType LoadTypeCache(SplayTreeInfo *cache,const char *xml,
             */
             (void) ThrowMagickException(exception,GetMagickModule(),
               ConfigureError,"UnterminatedDOCTYPE","`%s'",filename);
+            status=MagickFalse;
             break;
           }
         continue;
       }
-    if (LocaleNCompare(keyword,"<!--",4) == 0)
-      {
-        /*
-          Comment element.
-        */
-        SkipXMLComment(&q);
-        continue;
-      }
     if (LocaleCompare(keyword,"<include") == 0)
       {
         /*
@@ -1180,8 +1180,8 @@ static MagickBooleanType LoadTypeCache(SplayTreeInfo *cache,const char *xml,
                   sans_exception=DestroyExceptionInfo(sans_exception);
                   if (file_xml != (char *) NULL)
                     {
-                      status&=(MagickStatusType) LoadTypeCache(cache,file_xml,
-                        path,depth+1,exception);
+                      if (LoadTypeCache(cache,file_xml,path,depth+1,exception) == MagickFalse)
+                        status=MagickFalse;
                       file_xml=(char *) RelinquishMagickMemory(file_xml);
                     }
                 }
@@ -1334,7 +1334,7 @@ static MagickBooleanType LoadTypeCache(SplayTreeInfo *cache,const char *xml,
     }
   }
   token=(char *) RelinquishMagickMemory(token);
-  return(status != 0 ? MagickTrue : MagickFalse);
+  return(status);
 }

 /*
diff --git a/MagickCore/xml-tree-private.h b/MagickCore/xml-tree-private.h
index 7223a5c0a..fea07a1ba 100644
--- a/MagickCore/xml-tree-private.h
+++ b/MagickCore/xml-tree-private.h
@@ -32,11 +32,9 @@ extern MagickPrivate char
   *FileToXML(const char *,const size_t);

 extern MagickPrivate MagickBooleanType
+  SkipXMLComment(const char **),
   SkipXMLDocType(const char **);

-extern MagickPrivate void
-  SkipXMLComment(const char **);
-
 extern MagickExport char
   *SubstituteXMLEntities(const char *,const MagickBooleanType);

diff --git a/MagickCore/xml-tree.c b/MagickCore/xml-tree.c
index 194108d20..c1b5cfa66 100644
--- a/MagickCore/xml-tree.c
+++ b/MagickCore/xml-tree.c
@@ -2111,21 +2111,29 @@ MagickExport XMLTreeInfo *SetXMLTreeContent(XMLTreeInfo *xml_info,
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  SkipXMLComment() advances past an XML comment.
+%  SkipXMLComment() skips leading whitespace and XML comments, leaving the
+%  next token untouched.  It returns MagickFalse for an unterminated comment.
 %
 */
-MagickPrivate void SkipXMLComment(const char **xml)
+MagickPrivate MagickBooleanType SkipXMLComment(const char **xml)
 {
   const char
     *p;

-  for (p=*xml; *p != '\0'; p++)
-    if ((p[0] == '-') && (p[1] == '-') && (p[2] == '>'))
-      {
-        *xml=p+3;
-        return;
-      }
+  for (p=*xml; ; )
+  {
+    while (isspace((int) ((unsigned char) *p)) != 0)
+      p++;
+    if (strncmp(p,"<!--",4) != 0)
+      break;
+    *xml=p;
+    p=strstr(p+4,"-->");
+    if (p == (const char *) NULL)
+      return(MagickFalse);
+    p+=3;
+  }
   *xml=p;
+  return(MagickTrue);
 }

 /*
@@ -2153,18 +2161,12 @@ MagickPrivate MagickBooleanType SkipXMLDocType(const char **xml)

   bracket_depth=0;
   quote=0;
-  for (p=*xml; *p != '\0'; p++)
+  for (p=*xml; *p != '\0'; )
   {
-    if ((quote == 0) && (p[0] == '<') && (p[1] == '!') &&
-        (p[2] == '-') && (p[3] == '-'))
+    if ((quote == 0) && (strncmp(p,"<!--",4) == 0))
       {
-        p+=4;
-        while ((*p != '\0') && !((p[0] == '-') && (p[1] == '-') &&
-               (p[2] == '>')))
-          p++;
-        if (*p == '\0')
+        if (SkipXMLComment(&p) == MagickFalse)
           break;
-        p+=2;
         continue;
       }
     if (quote != 0)
@@ -2192,6 +2194,7 @@ MagickPrivate MagickBooleanType SkipXMLDocType(const char **xml)
                   return(MagickTrue);
                 }
       }
+    p++;
   }
   *xml=p;
   return(MagickFalse);