GraphicsMagick: coders/bmp.c Read files compressed with BI_PNG.

GraphicsMagick Commits <[email protected]> Fri, 22 Sep 2023 17:07:14 -0500
Newsgroups gmane.comp.video.graphicsmagick.cvs
Message-ID <mailman.2950.1695420446.1961.graphicsmagick-commit@lists.sourceforge.net>
changeset 9382cb6db1be in /hg/GraphicsMagick
details: http://hg.GraphicsMagick.org/hg/GraphicsMagick?cmd=changeset;node=9382cb6db1be
summary: coders/bmp.c Read files compressed with BI_PNG.

diffstat:

 ChangeLog    |   6 ++++++
 coders/bmp.c |  53 +++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 43 insertions(+), 16 deletions(-)

diffs (122 lines):

diff -r c089cb58afdc -r 9382cb6db1be ChangeLog
--- a/ChangeLog	Fri Sep 22 08:05:38 2023 -0500
+++ b/ChangeLog	Sat Sep 23 00:06:45 2023 +0200
@@ -1,3 +1,9 @@
+2023-09-23  Fojtik Jaroslav  <[email protected]>
+
+	* coders/bmp.c Emit error when OS/2 bitmap with compression BI_JPEG
+	or BI_PNG is detected.
+	Read files compressed with BI_PNG.
+
 2023-09-22  Fojtik Jaroslav  <[email protected]>
 
 	* coders/bmp.c: Display bitmasks into optional log.
diff -r c089cb58afdc -r 9382cb6db1be coders/bmp.c
--- a/coders/bmp.c	Fri Sep 22 08:05:38 2023 -0500
+++ b/coders/bmp.c	Sat Sep 23 00:06:45 2023 +0200
@@ -531,7 +531,7 @@
 }
 
 
-static Image *ExtractBlobJPG(Image * image, const ImageInfo * image_info, ExceptionInfo * exception)
+static Image *ExtractNestedBlob(Image * image, const ImageInfo * image_info, int ImgType, ExceptionInfo * exception)
 {
   size_t
     alloc_size;
@@ -553,7 +553,7 @@
 
               /* BlobToFile("/tmp/jnx-tile.jpg", blob,alloc_size,exception); */
 
-         (void) strlcpy(clone_info->filename,"JPEG:",sizeof(clone_info->filename));
+         (void) strlcpy(clone_info->filename, (ImgType==BI_JPEG)?"JPEG:":"PNG:", sizeof(clone_info->filename));
          if ((image2 = BlobToImage(clone_info,blob,alloc_size,exception))
                   != NULL)
          {
@@ -561,19 +561,19 @@
                     Replace current image with new image while copying
                     base image attributes.
                   */
-                  (void) strlcpy(image2->filename, image->filename,
+            (void) strlcpy(image2->filename, image->filename,
                                  sizeof(image2->filename));
-                  (void) strlcpy(image2->magick_filename, image->magick_filename,
+            (void) strlcpy(image2->magick_filename, image->magick_filename,
                                  sizeof(image2->magick_filename));
-                  (void) strlcpy(image2->magick, image->magick,
+            (void) strlcpy(image2->magick, image->magick,
                                  sizeof(image2->magick));
-                  DestroyBlob(image2);
-                  image2->blob = ReferenceBlob(image->blob);
+            DestroyBlob(image2);
+           image2->blob = ReferenceBlob(image->blob);
 
-                  if ((image->rows == 0) || (image->columns == 0))
-                    DeleteImageFromList(&image);
+            if ((image->rows == 0) || (image->columns == 0))
+               DeleteImageFromList(&image);
 
-                  AppendImageToList(&image, image2);
+            AppendImageToList(&image, image2);
          }
          DestroyImageInfo(clone_info);
          clone_info = (ImageInfo *) NULL;
@@ -881,10 +881,10 @@
 
           if(bmp_info.size==64)
             {				/* OS22XBITMAPHEADER */
-              magick_uint16_t   Units;            /* Type of units used to measure resolution */
-              magick_uint16_t   Reserved;         /* Pad structure to 4-byte boundary */
-              magick_uint16_t   Recording;        /* Recording algorithm */
-              magick_uint16_t   Rendering;        /* Halftoning algorithm used */
+              magick_uint16_t  Units;            /* Type of units used to measure resolution */
+              magick_uint16_t  Reserved;         /* Pad structure to 4-byte boundary */
+              magick_uint16_t  Recording;        /* Recording algorithm */
+              magick_uint16_t  Rendering;        /* Halftoning algorithm used */
               magick_uint32_t  Size1;            /* Reserved for halftoning algorithm use */
               magick_uint32_t  Size2;            /* Reserved for halftoning algorithm use */
               magick_uint32_t  ColorEncoding;    /* Color model used in bitmap */
@@ -910,6 +910,9 @@
                               "    Identifier: %u",
                               Units, Reserved, Recording, Rendering,
                               Size1, Size2, ColorEncoding, Identifier);
+                  /* OS/2 does not recognise JPEG nor PNG. */
+              if(bmp_info.compression==BI_JPEG || bmp_info.compression==BI_PNG)
+                  ThrowBMPReaderException(CoderError,CompressionNotValid,image)
             }
 
           if (bmp_info.size>=52 && bmp_info.size!=64)
@@ -1178,14 +1181,32 @@
           {
             MonitorHandler previous_handler;
             previous_handler = SetMonitorHandler(0);
-            image = ExtractBlobJPG(image, image_info, exception);
+            image = ExtractNestedBlob(image, image_info, bmp_info.compression, exception);
             (void) SetMonitorHandler(previous_handler);
             if (exception->severity >= ErrorException)
                 ThrowBMPReaderException(CoderError,JPEGCompressionNotSupported,image)
           }
           goto ExitLoop;	/* I need to break a loop. Other BMPs in a chain are ignorred. */
+
         case BI_PNG:
-          ThrowBMPReaderException(CoderError,PNGCompressionNotSupported,image)
+          offset = start_position + 14 + bmp_info.size;
+          if(logging)
+              (void)LogMagickEvent(CoderEvent,GetMagickModule(),
+                                  "Seek offset %" MAGICK_OFF_F "d",
+                                  (magick_off_t) offset);
+          if((offset < start_position) ||
+              (SeekBlob(image,offset,SEEK_SET) != (magick_off_t) offset))
+              ThrowBMPReaderException(CorruptImageError,ImproperImageHeader,image);
+          {
+            MonitorHandler previous_handler;
+            previous_handler = SetMonitorHandler(0);
+            image = ExtractNestedBlob(image, image_info, bmp_info.compression, exception);
+            (void) SetMonitorHandler(previous_handler);
+            if (exception->severity >= ErrorException)
+                ThrowBMPReaderException(CoderError,PNGCompressionNotSupported,image)
+          }
+          goto ExitLoop;	/* I need to break a loop. Other BMPs in a chain are ignorred. */
+
         default:
           ThrowBMPReaderException(CorruptImageError,UnrecognizedImageCompression,image)
         }