GraphicsMagick: JXL: Fix version identification. Add error trac...

GraphicsMagick Commits <[email protected]> Wed, 20 Dec 2023 11:02:34 -0600
Newsgroups gmane.comp.video.graphicsmagick.cvs
Message-ID <mailman.14347.1703091769.7794.graphicsmagick-commit@lists.sourceforge.net>
changeset 0225ad819b0d in /hg/GraphicsMagick
details: http://hg.GraphicsMagick.org/hg/GraphicsMagick?cmd=changeset;node=0225ad819b0d
summary: JXL: Fix version identification.  Add error tracing.

diffstat:

 ChangeLog                              |    9 +
 VisualMagick/installer/inc/version.isx |    4 +-
 coders/jxl.c                           |  416 +++++++++++++++++++++-----------
 fuzzing/oss-fuzz-build.sh              |    9 +-
 magick/version.h                       |    4 +-
 www/Changelog.html                     |   30 ++
 6 files changed, 312 insertions(+), 160 deletions(-)

diffs (truncated from 754 to 500 lines):

diff -r 9eb113adfb7b -r 0225ad819b0d ChangeLog
--- a/ChangeLog	Mon Dec 18 01:58:21 2023 +0100
+++ b/ChangeLog	Wed Dec 20 11:02:29 2023 -0600
@@ -1,3 +1,12 @@
+2023-12-20  Bob Friesenhahn  <[email protected]>
+
+	* fuzzing/oss-fuzz-build.sh: Remove unnecessary space in include
+	path argument.
+
+	* coders/jxl.c (RegisterJXLImage): Fix version identification.
+	(ReadJXLImage): Add error tracing.
+	(WriteJXLImage): Add error tracing.
+
 2023-12-18  Fojtik Jaroslav  <[email protected]>
 
 	* coders/tiff.c Check for NULL in EXIF tag name being logged.
diff -r 9eb113adfb7b -r 0225ad819b0d VisualMagick/installer/inc/version.isx
--- a/VisualMagick/installer/inc/version.isx	Mon Dec 18 01:58:21 2023 +0100
+++ b/VisualMagick/installer/inc/version.isx	Wed Dec 20 11:02:29 2023 -0600
@@ -10,5 +10,5 @@
 
 #define public MagickPackageName "GraphicsMagick"
 #define public MagickPackageVersion "1.4"
-#define public MagickPackageVersionAddendum ".020231211"
-#define public MagickPackageReleaseDate "snapshot-20231211"
+#define public MagickPackageVersionAddendum ".020231220"
+#define public MagickPackageReleaseDate "snapshot-20231220"
diff -r 9eb113adfb7b -r 0225ad819b0d coders/jxl.c
--- a/coders/jxl.c	Mon Dec 18 01:58:21 2023 +0100
+++ b/coders/jxl.c	Wed Dec 20 11:02:29 2023 -0600
@@ -441,23 +441,52 @@
   MyJxlMemoryManagerInit(&mm,image,exception);
   jxl_decoder=JxlDecoderCreate(&mm.super);
   if (jxl_decoder == (JxlDecoder *) NULL)
-    ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+    {
+      if (image->logging)
+        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                              "JxlDecoderCreate() failed");
+      ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+    }
 
   /* Deliver image as-is. We provide autoOrient function if user requires it */
   if (JxlDecoderSetKeepOrientation(jxl_decoder, JXL_TRUE) != JXL_DEC_SUCCESS)
-    ThrowJXLReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+    {
+      if (image->logging)
+        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                              "JxlDecoderSetKeepOrientation() failed");
+      ThrowJXLReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+    }
 
   /* Apply any pre-multiplied alpha for us so we don't need to do it. */
-  (void) JxlDecoderSetUnpremultiplyAlpha(jxl_decoder, JXL_TRUE);
+  if (JxlDecoderSetUnpremultiplyAlpha(jxl_decoder, JXL_TRUE) != JXL_DEC_SUCCESS)
+    {
+      if (image->logging)
+        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                              "JxlDecoderSetUnpremultiplyAlpha() failed");
+      ThrowJXLReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+    }
 
   if(!image_info->ping)
     {
-      jxl_thread_runner=JxlThreadParallelRunnerCreate(NULL,(size_t) GetMagickResourceLimit(ThreadsResource));
+      size_t num_worker_threads = (size_t) GetMagickResourceLimit(ThreadsResource);
+      jxl_thread_runner=JxlThreadParallelRunnerCreate(NULL, num_worker_threads);
       if (jxl_thread_runner == (void *) NULL)
-        ThrowJXLReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+        {
+          if (image->logging)
+            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                  "JxlThreadParallelRunnerCreate() failed (%"MAGICK_SIZE_T_F"u threads)",
+                                  num_worker_threads);
+          ThrowJXLReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+        }
       if (JxlDecoderSetParallelRunner(jxl_decoder, JxlThreadParallelRunner, jxl_thread_runner)
           != JXL_DEC_SUCCESS)
-        ThrowJXLReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+        {
+          if (image->logging)
+            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                  "JxlDecoderSetParallelRunner() failed (%"MAGICK_SIZE_T_F"u) threads",
+                                  num_worker_threads);
+          ThrowJXLReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+        }
     }
 
   if (JxlDecoderSubscribeEvents(jxl_decoder,
@@ -469,7 +498,12 @@
                                                       JXL_DEC_COLOR_ENCODING |
                                                       JXL_DEC_BOX))
                                 ) != JXL_DEC_SUCCESS)
-    ThrowJXLReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+    {
+      if (image->logging)
+        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                              "JxlDecoderSubscribeEvents() failed");
+      ThrowJXLReaderException(ResourceLimitError,MemoryAllocationFailed,image);
+    }
 
   in_buf=MagickAllocateResourceLimitedArray(unsigned char *,in_len,sizeof(*in_buf));
   if (in_buf == (unsigned char *) NULL)
@@ -513,7 +547,12 @@
 
             status=JxlDecoderGetBasicInfo(jxl_decoder,&basic_info);
             if (status != JXL_DEC_SUCCESS)
-              break;
+              {
+                if (image->logging)
+                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                        "JxlDecoderGetBasicInfo() failed");
+                break;
+              }
 
             if (image->logging)
               {
@@ -554,7 +593,7 @@
                                             "    alpha_premultiplied=%s\n"
                                             "    spot_color=%f,%f,%f,%f\n"
                                             "    cfa_channel=%u"
-                                          ,
+                                            ,
                                             (unsigned long) index,
                                             JxlExtraChannelTypeAsString(ecip->type),
                                             ecip->bits_per_sample,
@@ -565,6 +604,10 @@
                                             ecip->spot_color[0],ecip->spot_color[1],
                                             ecip->spot_color[2],ecip->spot_color[3],
                                             ecip->cfa_channel);
+                    else
+                      if (image->logging)
+                        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                              "JxlDecoderGetExtraChannelInfo() failed");
                   }
               }
 
@@ -598,15 +641,15 @@
                 grayscale=MagickTrue;
                 pixel_format.num_channels=1;
                 pixel_format.data_type=(basic_info.bits_per_sample <= 8 ? JXL_TYPE_UINT8 :
-                                  (basic_info.bits_per_sample <= 16 ? JXL_TYPE_UINT16 :
-                                   JXL_TYPE_FLOAT));
+                                        (basic_info.bits_per_sample <= 16 ? JXL_TYPE_UINT16 :
+                                         JXL_TYPE_FLOAT));
               }
             else if (basic_info.num_color_channels == 3)
               {
                 pixel_format.num_channels=image->matte ? 4 : 3;
                 pixel_format.data_type=(basic_info.bits_per_sample <= 8 ? JXL_TYPE_UINT8 :
-                                  (basic_info.bits_per_sample <= 16 ? JXL_TYPE_UINT16 :
-                                   JXL_TYPE_FLOAT));
+                                        (basic_info.bits_per_sample <= 16 ? JXL_TYPE_UINT16 :
+                                         JXL_TYPE_FLOAT));
               }
             else
               {
@@ -651,7 +694,7 @@
               {
                 /*
                   Transfer function if have_gamma is 0
-                 */
+                */
                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                       "Color Transfer Function: %s",
                                       JxlTransferFunctionAsString(color_encoding.transfer_function));
@@ -691,7 +734,7 @@
 
                 /*
                   Color space of the image data.
-                 */
+                */
                 switch (color_encoding.color_space) {
                 case JXL_COLOR_SPACE_RGB:
                   if (color_encoding.white_point == JXL_WHITE_POINT_D65 &&
@@ -748,6 +791,11 @@
                   unsigned char
                     *profile;
 
+                  if (image->logging)
+                    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                          "ICC profile size %"MAGICK_SIZE_T_F"u",
+                                          profile_size);
+
                   if ((profile=MagickAllocateResourceLimitedMemory(unsigned char *,profile_size))
                       != NULL)
                     {
@@ -760,6 +808,9 @@
                                                          profile_size)
                           == JXL_DEC_SUCCESS)
                         {
+                          if (image->logging)
+                            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                                  "JxlDecoderGetColorAsICCProfile() success");
                           (void) SetImageProfile(image,"ICM",profile,profile_size);
                         }
                       MagickFreeResourceLimitedMemory(profile);
@@ -775,7 +826,12 @@
 
             status=JxlDecoderImageOutBufferSize(jxl_decoder,&pixel_format,&out_len);
             if (status != JXL_DEC_SUCCESS)
-              break;
+              {
+                if (image->logging)
+                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                        "JxlDecoderImageOutBufferSize() failure");
+                break;
+              }
 
             out_buf=MagickAllocateResourceLimitedArray(unsigned char *,out_len,sizeof(*out_buf));
             if (out_buf == (unsigned char *) NULL)
@@ -826,7 +882,7 @@
                 else
                   quantum_type = GrayQuantum;
               }
-            #if 0
+#if 0
             else if (cmyk)
               {
                 if (image->matte)
@@ -834,7 +890,7 @@
                 else
                   quantum_type = CMYKQuantum;
               }
-            #endif
+#endif
             else
               {
                 if (image->matte)
@@ -895,76 +951,76 @@
               status=JXL_DEC_ERROR;
             break;
           }
-          case JXL_DEC_BOX:
-            {
-              do
-                {
-                  JxlBoxType
-                    type; /* A 4 character string which is not null terminated! */
+        case JXL_DEC_BOX:
+          {
+            do
+              {
+                JxlBoxType
+                  type; /* A 4 character string which is not null terminated! */
 
-                  magick_uint64_t
-                    profile_size = 0;
+                magick_uint64_t
+                  profile_size = 0;
 
-                  unsigned char
-                    *profile;
+                unsigned char
+                  *profile;
 
-                  /* Release buffer to get box data */
-                  (void) JxlDecoderReleaseBoxBuffer(jxl_decoder);
+                /* Release buffer to get box data */
+                (void) JxlDecoderReleaseBoxBuffer(jxl_decoder);
 
-                  /* Get the 4-character box typename */
-                  if (JxlDecoderGetBoxType(jxl_decoder,type,JXL_FALSE) != JXL_DEC_SUCCESS)
-                    break;
+                /* Get the 4-character box typename */
+                if (JxlDecoderGetBoxType(jxl_decoder,type,JXL_FALSE) != JXL_DEC_SUCCESS)
+                  break;
 
-                  /* Get the size of the box as it appears in the container file, not decompressed. */
-                  if (JxlDecoderGetBoxSizeRaw(jxl_decoder, &profile_size) != JXL_DEC_SUCCESS)
-                    break;
+                /* Get the size of the box as it appears in the container file, not decompressed. */
+                if (JxlDecoderGetBoxSizeRaw(jxl_decoder, &profile_size) != JXL_DEC_SUCCESS)
+                  break;
 
-                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                                        "JXL Box of type \"%c%c%c%c\" and %lu bytes",
-                                        type[0],type[1],type[2],type[3], (unsigned long) profile_size);
+                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                      "JXL Box of type \"%c%c%c%c\" and %lu bytes",
+                                      type[0],type[1],type[2],type[3], (unsigned long) profile_size);
 
-                  /* Ignore tiny profiles */
-                  if (profile_size < 12)
-                    break;
+                /* Ignore tiny profiles */
+                if (profile_size < 12)
+                  break;
 
-                  /* Discard raw box size and type bytes */
-                  profile_size -= 8;
+                /* Discard raw box size and type bytes */
+                profile_size -= 8;
 
-                  if (LocaleNCompare(type,"Exif",sizeof(type)) == 0)
-                    {
-                      /*
-                        Allocate EXIF profile box buffer (plus a bit more)
-                      */
-                      if ((profile=MagickAllocateResourceLimitedClearedMemory(unsigned char *,
-                                                                              profile_size+exif_pad))
-                          != NULL)
-                        {
-                          if (JxlDecoderSetBoxBuffer(jxl_decoder,profile+exif_pad,profile_size)
-                              == JXL_DEC_SUCCESS)
-                            {
-                              exif_profile=profile;
-                              exif_size=profile_size;
-                            }
-                        }
-                    }
-                  if (LocaleNCompare(type,"xml ",sizeof(type)) == 0)
-                    {
-                      /*
-                        Allocate XMP profile box buffer
-                      */
-                      if ((profile=MagickAllocateResourceLimitedMemory(unsigned char *,profile_size))
-                          != NULL)
-                        {
-                          if (JxlDecoderSetBoxBuffer(jxl_decoder,profile,profile_size) == JXL_DEC_SUCCESS)
-                            {
-                              xmp_profile=profile;
-                              xmp_size=profile_size;
-                            }
-                        }
-                    }
-                } while(0);
-              break;
-            }
+                if (LocaleNCompare(type,"Exif",sizeof(type)) == 0)
+                  {
+                    /*
+                      Allocate EXIF profile box buffer (plus a bit more)
+                    */
+                    if ((profile=MagickAllocateResourceLimitedClearedMemory(unsigned char *,
+                                                                            profile_size+exif_pad))
+                        != NULL)
+                      {
+                        if (JxlDecoderSetBoxBuffer(jxl_decoder,profile+exif_pad,profile_size)
+                            == JXL_DEC_SUCCESS)
+                          {
+                            exif_profile=profile;
+                            exif_size=profile_size;
+                          }
+                      }
+                  }
+                if (LocaleNCompare(type,"xml ",sizeof(type)) == 0)
+                  {
+                    /*
+                      Allocate XMP profile box buffer
+                    */
+                    if ((profile=MagickAllocateResourceLimitedMemory(unsigned char *,profile_size))
+                        != NULL)
+                      {
+                        if (JxlDecoderSetBoxBuffer(jxl_decoder,profile,profile_size) == JXL_DEC_SUCCESS)
+                          {
+                            xmp_profile=profile;
+                            xmp_size=profile_size;
+                          }
+                      }
+                  }
+              } while(0);
+            break;
+          }
         default:
           /* unexpected status is error.
            * - JXL_DEC_SUCCESS should never happen here so it's also an error
@@ -997,9 +1053,9 @@
 
       /* Big-endian offset decoding */
       exif_profile_offset = p[exif_pad+0] << 24 |
-                            p[exif_pad+1] << 16 |
-                            p[exif_pad+2] << 8 |
-                            p[exif_pad+3];
+        p[exif_pad+1] << 16 |
+        p[exif_pad+2] << 8 |
+        p[exif_pad+3];
 
 #if 0
       fprintf(stderr,
@@ -1007,9 +1063,10 @@
               p[0], p[1],p[2], p[3], p[4], p[5], p[6], p[7],  p[8],  p[9],  p[10],  p[11]);
 #endif
 
-      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-                            "EXIF Box: Size %lu, Offset %u",
-                            (unsigned long) exif_size, exif_profile_offset);
+      if (image->logging)
+        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                              "EXIF Box: Size %lu, Offset %u",
+                              (unsigned long) exif_size, exif_profile_offset);
 
       /*
         If the TIFF header offset is not zero, then need to
@@ -1187,17 +1244,36 @@
   MyJxlMemoryManagerInit(&memory_manager,image,&image->exception);
   jxl_encoder=JxlEncoderCreate(&memory_manager.super);
   if (jxl_encoder == (JxlEncoder *) NULL)
-    ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
+    {
+      if (image->logging)
+        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                              "JxlEncoderCreate() failure");
+      ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
+    }
 
   /* Use the same number of threads as used for OpenMP */
-  jxl_thread_runner=
-    JxlThreadParallelRunnerCreate(NULL,
-                                  (size_t) GetMagickResourceLimit(ThreadsResource));
-  if (jxl_thread_runner == (void *) NULL)
-    ThrowJXLWriterException(ResourceLimitError,MemoryAllocationFailed,image);
-  if (JxlEncoderSetParallelRunner(jxl_encoder, JxlThreadParallelRunner, jxl_thread_runner)
-      != JXL_ENC_SUCCESS)
-    ThrowJXLWriterException(ResourceLimitError,MemoryAllocationFailed,image);
+  {
+    size_t num_worker_threads = (size_t) GetMagickResourceLimit(ThreadsResource);
+    jxl_thread_runner=
+      JxlThreadParallelRunnerCreate(NULL,num_worker_threads);
+    if (jxl_thread_runner == (void *) NULL)
+      {
+        if (image->logging)
+          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                "JxlThreadParallelRunnerCreate() failed (%"MAGICK_SIZE_T_F"u) threads",
+                                num_worker_threads);
+        ThrowJXLWriterException(ResourceLimitError,MemoryAllocationFailed,image);
+      }
+    if (JxlEncoderSetParallelRunner(jxl_encoder, JxlThreadParallelRunner, jxl_thread_runner)
+        != JXL_ENC_SUCCESS)
+      {
+        if (image->logging)
+          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                "JxlDecoderSetParallelRunner() failed (%"MAGICK_SIZE_T_F"u) threads",
+                                num_worker_threads);
+        ThrowJXLWriterException(ResourceLimitError,MemoryAllocationFailed,image);
+      }
+  }
 
   /* Use one color channel for grayscale image */
   if (characteristics.grayscale)
@@ -1316,13 +1392,23 @@
   basic_info.uses_original_profile = JXL_TRUE;
   JxlColorEncodingSetToSRGB(&color_encoding, pixel_format.num_channels < 3);
   if (JxlEncoderSetColorEncoding(jxl_encoder, &color_encoding) != JXL_ENC_SUCCESS)
-    ThrowJXLWriterException(CoderFatalError,Default,image);
+    {
+      if (image->logging)
+        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                              "JxlEncoderSetColorEncoding() failed");
+      ThrowJXLWriterException(CoderFatalError,Default,image);
+    }
 
   frame_settings = JxlEncoderFrameSettingsCreate(jxl_encoder, NULL);
   if (image_info->quality == 100)
     {
       if (JxlEncoderSetFrameLossless(frame_settings,JXL_TRUE) != JXL_ENC_SUCCESS)
-        ThrowJXLWriterException(CoderFatalError,Default,image);
+        {
+          if (image->logging)
+            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                  "JxlEncoderSetFrameLossless() failed");
+          ThrowJXLWriterException(CoderFatalError,Default,image);
+        }
     }
   else
     {
@@ -1330,14 +1416,26 @@
       if (image_info->quality >= 30)
         {
           if (JxlEncoderSetFrameDistance(frame_settings,
-                                         0.1 + (100 - image_info->quality) * 0.09) != JXL_ENC_SUCCESS)
-            ThrowJXLWriterException(CoderFatalError,Default,image);
+                                         0.1 + (100 - image_info->quality) * 0.09)
+              != JXL_ENC_SUCCESS)
+            {
+              if (image->logging)
+                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                      "JxlEncoderSetFrameDistance() failed");
+              ThrowJXLWriterException(CoderFatalError,Default,image);
+            }
         }
       else
         {
           if (JxlEncoderSetFrameDistance(frame_settings,
-                                         6.4 + pow(2.5, (30 - image_info->quality) / 5.0f) / 6.25f) != JXL_ENC_SUCCESS)
-            ThrowJXLWriterException(CoderFatalError,Default,image);
+                                         6.4 + pow(2.5, (30 - image_info->quality) / 5.0f) / 6.25f)
+              != JXL_ENC_SUCCESS)
+            {
+              if (image->logging)
+                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                                      "JxlEncoderSetFrameDistance() failed");
+              ThrowJXLWriterException(CoderFatalError,Default,image);
+            }
         }
     }
   /*
@@ -1365,7 +1463,8 @@
         if ((value=AccessDefinition(image_info,"jxl",key)))
           {