Commit 0c76bb631 for imagemagick.org

commit 0c76bb631db4ede005d4eeef7714d6d7951b40ce
Author: Dirk Lemstra <dirk@lemstra.org>
Date:   Sat Nov 7 12:06:57 2026 +0100

    Use a small stack buffer when writing bytes for padding instead of writing them separately.

diff --git a/MagickCore/blob-private.h b/MagickCore/blob-private.h
index 7e08e6884..b3c6cd64e 100644
--- a/MagickCore/blob-private.h
+++ b/MagickCore/blob-private.h
@@ -126,6 +126,7 @@ extern MagickExport ssize_t
   WriteBlobMSBLong(Image *,const unsigned int),
   WriteBlobMSBShort(Image *,const unsigned short),
   WriteBlobMSBSignedShort(Image *,const signed short),
+  WriteBlobPadding(Image *,const size_t,const unsigned char),
   WriteBlobString(Image *,const char *);

 extern MagickExport unsigned int
diff --git a/MagickCore/blob.c b/MagickCore/blob.c
index cdd8eb4a5..c93b0d4bc 100644
--- a/MagickCore/blob.c
+++ b/MagickCore/blob.c
@@ -6193,6 +6193,74 @@ MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
   }
   return(count);
 }
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++   W r i t e B l o b P a d d i n g                                           %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  WriteBlobPadding() writes length copies of a byte value to a blob.  It
+%  returns the number of bytes written, stopping on a short or failed write.
+%  Lengths greater than MAGICK_SSIZE_MAX return zero and set errno to EOVERFLOW.
+%
+%  The format of the WriteBlobPadding method is:
+%
+%      ssize_t WriteBlobPadding(Image *image,const size_t length,
+%        const unsigned char value)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+%    o length: the number of bytes to write.
+%
+%    o value: the byte value to repeat.
+%
+*/
+MagickExport ssize_t WriteBlobPadding(Image *image,const size_t length,
+  const unsigned char value)
+{
+  size_t
+    extent;
+
+  ssize_t
+    count,
+    total;
+
+  unsigned char
+    padding[1024];
+
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickCoreSignature);
+  assert(image->blob != (BlobInfo *) NULL);
+  assert(image->blob->type != UndefinedStream);
+  if (length == 0)
+    return(0);
+  if (length > (size_t) MAGICK_SSIZE_MAX)
+    {
+      errno=EOVERFLOW;
+      return(0);
+    }
+  (void) memset(padding,value,sizeof(padding));
+  total=0;
+  while ((size_t) total < length)
+  {
+    extent=MagickMin(sizeof(padding),length-(size_t) total);
+    count=WriteBlob(image,extent,padding);
+    if (count <= 0)
+      break;
+    total+=count;
+    if (count != (ssize_t) extent)
+      break;
+  }
+  return(total);
+}

 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/coders/ase.c b/coders/ase.c
index b2678ed07..8c37a2b4c 100644
--- a/coders/ase.c
+++ b/coders/ase.c
@@ -1393,8 +1393,7 @@ static MagickBooleanType WriteASEImage(const ImageInfo *image_info,
   (void) WriteBlobByte(image,0);
   (void) WriteBlobLSBShort(image,1);
   (void) WriteBlobLSBShort(image,1);
-  for (i=0; i < 46; i++)
-    (void) WriteBlobLSBShort(image,0);  /* grid x/y/width/height + reserved[84] */
+  (void) WriteBlobPadding(image,92,'\0');  /* grid x/y/width/height + reserved[84] */
   pixel_count=image->columns*image->rows;
   pixels=(uint8_t *) AcquireQuantumMemory(pixel_count,bytes_per_pixel);
   if (pixels == (uint8_t *) NULL)
diff --git a/coders/cals.c b/coders/cals.c
index 416d71b57..70c8d06ed 100644
--- a/coders/cals.c
+++ b/coders/cals.c
@@ -403,9 +403,6 @@ ModuleExport void UnregisterCALSImage(void)

 static ssize_t WriteCALSRecord(Image *image,const char *data)
 {
-  char
-    pad[128];
-
   const char
     *p;

@@ -426,8 +423,7 @@ static ssize_t WriteCALSRecord(Image *image,const char *data)
   if (i < 128)
     {
       i=128-i;
-      (void) memset(pad,' ',(size_t) i);
-      count=WriteBlob(image,(size_t) i,(const unsigned char *) pad);
+      count=WriteBlobPadding(image,(size_t) i,' ');
     }
   return(count);
 }
diff --git a/coders/dpx.c b/coders/dpx.c
index 3fa79037e..853c20acc 100644
--- a/coders/dpx.c
+++ b/coders/dpx.c
@@ -1979,15 +1979,14 @@ static MagickBooleanType WriteDPXImage(const ImageInfo *image_info,Image *image,
   if (profile != (StringInfo *) NULL)
     offset+=WriteBlob(image,GetStringInfoLength(profile),
       GetStringInfoDatum(profile));
-  while (offset < (MagickOffsetType) dpx.image.image_element[0].data_offset)
+  if (offset < (MagickOffsetType) dpx.image.image_element[0].data_offset)
   {
-    count=WriteBlobByte(image,0x00);
-    if (count != 1)
-      {
-        ThrowFileException(exception,FileOpenError,"UnableToWriteFile",
-          image->filename);
-        break;
-      }
+    extent=(size_t) ((MagickOffsetType)
+      dpx.image.image_element[0].data_offset-offset);
+    count=WriteBlobPadding(image,extent,'\0');
+    if (count != (ssize_t) extent)
+      ThrowFileException(exception,FileOpenError,"UnableToWriteFile",
+        image->filename);
     offset+=count;
   }
   /*
diff --git a/coders/icon.c b/coders/icon.c
index 8be917ef6..b08721c5d 100644
--- a/coders/icon.c
+++ b/coders/icon.c
@@ -1514,8 +1514,7 @@ static MagickBooleanType WriteICONImage(const ImageInfo *image_info,
           }
           if (bit != 0)
             (void) WriteBlobByte(image,(unsigned char) (byte << (8-bit)));
-          for (i=0; i < (ssize_t) scanline_pad; i++)
-            (void) WriteBlobByte(image,(unsigned char) 0);
+          (void) WriteBlobPadding(image,scanline_pad,'\0');
         }
       }
     if (GetNextImageInList(frame) == (Image *) NULL)
diff --git a/coders/mat.c b/coders/mat.c
index c7d90e39f..fd16ad89f 100644
--- a/coders/mat.c
+++ b/coders/mat.c
@@ -1777,8 +1777,7 @@ static MagickBooleanType WriteMATImage(const ImageInfo *image_info,Image *image,
       if (SyncAuthenticPixels(image,exception) == MagickFalse)
         break;
     } while (z-- >= 2);
-    while (padding-- > 0)
-      (void) WriteBlobByte(image,0);
+    (void) WriteBlobPadding(image,padding,'\0');
     quantum_info=DestroyQuantumInfo(quantum_info);
     if (GetNextImageInList(image) == (Image *) NULL)
       break;
diff --git a/coders/palm.c b/coders/palm.c
index b09ae0939..ef65ac83f 100644
--- a/coders/palm.c
+++ b/coders/palm.c
@@ -701,9 +701,6 @@ static MagickBooleanType WritePALMImage(const ImageInfo *image_info,
     offset,
     scene;

-  MagickSizeType
-    cc;
-
   PixelInfo
     transpix;

@@ -1018,8 +1015,7 @@ static MagickBooleanType WritePALMImage(const ImageInfo *image_info,
     if (GetNextImageInList(image) == (Image *) NULL)
       break;
     /* padding to 4 byte word */
-    for (cc=(GetBlobSize(image)) % 4; cc > 0; cc--)
-      (void) WriteBlobByte(image,0);
+    (void) WriteBlobPadding(image,(size_t) (GetBlobSize(image) % 4),'\0');
     /* write nextDepthOffset and return to end of image */
     offset=SeekBlob(image,currentOffset+10,SEEK_SET);
     nextDepthOffset=(size_t) (((MagickOffsetType) GetBlobSize(image)-
diff --git a/coders/pcd.c b/coders/pcd.c
index 37df0adfd..98af6ea86 100644
--- a/coders/pcd.c
+++ b/coders/pcd.c
@@ -1004,7 +1004,6 @@ static MagickBooleanType WritePCDTile(Image *image,const char *page_geometry,
     *q;

   ssize_t
-    i,
     x;

   ssize_t
@@ -1106,8 +1105,7 @@ static MagickBooleanType WritePCDTile(Image *image,const char *page_geometry,
     if (status == MagickFalse)
       break;
   }
-  for (i=0; i < 0x800; i++)
-    (void) WriteBlobByte(image,'\0');
+  (void) WriteBlobPadding(image,0x800,'\0');
   downsample_image=DestroyImage(downsample_image);
   tile_image=DestroyImage(tile_image);
   return(MagickTrue);
@@ -1122,9 +1120,6 @@ static MagickBooleanType WritePCDImage(const ImageInfo *image_info,Image *image,
   MagickBooleanType
     status;

-  ssize_t
-    i;
-
   assert(image_info != (const ImageInfo *) NULL);
   assert(image_info->signature == MagickCoreSignature);
   assert(image != (Image *) NULL);
@@ -1162,36 +1157,24 @@ static MagickBooleanType WritePCDImage(const ImageInfo *image_info,Image *image,
   /*
     Write PCD image header.
   */
-  for (i=0; i < 32; i++)
-    (void) WriteBlobByte(pcd_image,0xff);
-  for (i=0; i < 4; i++)
-    (void) WriteBlobByte(pcd_image,0x0e);
-  for (i=0; i < 8; i++)
-    (void) WriteBlobByte(pcd_image,'\0');
-  for (i=0; i < 4; i++)
-    (void) WriteBlobByte(pcd_image,0x01);
-  for (i=0; i < 4; i++)
-    (void) WriteBlobByte(pcd_image,0x05);
-  for (i=0; i < 8; i++)
-    (void) WriteBlobByte(pcd_image,'\0');
-  for (i=0; i < 4; i++)
-    (void) WriteBlobByte(pcd_image,0x0A);
-  for (i=0; i < 36; i++)
-    (void) WriteBlobByte(pcd_image,'\0');
-  for (i=0; i < 4; i++)
-    (void) WriteBlobByte(pcd_image,0x01);
-  for (i=0; i < 1944; i++)
-    (void) WriteBlobByte(pcd_image,'\0');
+  (void) WriteBlobPadding(pcd_image,32,'\xff');
+  (void) WriteBlobPadding(pcd_image,4,'\x0e');
+  (void) WriteBlobPadding(pcd_image,8,'\0');
+  (void) WriteBlobPadding(pcd_image,4,'\x01');
+  (void) WriteBlobPadding(pcd_image,4,'\x05');
+  (void) WriteBlobPadding(pcd_image,8,'\0');
+  (void) WriteBlobPadding(pcd_image,4,'\x0a');
+  (void) WriteBlobPadding(pcd_image,36,'\0');
+  (void) WriteBlobPadding(pcd_image,4,'\x01');
+  (void) WriteBlobPadding(pcd_image,1944,'\0');
   (void) WriteBlob(pcd_image,7,(const unsigned char *) "PCD_IPI");
   (void) WriteBlobByte(pcd_image,0x06);
-  for (i=0; i < 1530; i++)
-    (void) WriteBlobByte(pcd_image,'\0');
+  (void) WriteBlobPadding(pcd_image,1530,'\0');
   if (image->columns < image->rows)
     (void) WriteBlobByte(pcd_image,'\1');
   else
     (void) WriteBlobByte(pcd_image,'\0');
-  for (i=0; i < (3*0x800-1539); i++)
-    (void) WriteBlobByte(pcd_image,'\0');
+  (void) WriteBlobPadding(pcd_image,3*0x800-1539,'\0');
   /*
     Write PCD tiles.
   */
diff --git a/coders/pcx.c b/coders/pcx.c
index 3bae83a8d..8f8e13d15 100644
--- a/coders/pcx.c
+++ b/coders/pcx.c
@@ -1037,8 +1037,7 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image,
     (void) WriteBlobByte(image,pcx_info.planes);
     (void) WriteBlobLSBShort(image,pcx_info.bytes_per_line);
     (void) WriteBlobLSBShort(image,pcx_info.palette_info);
-    for (i=0; i < 58; i++)
-      (void) WriteBlobByte(image,'\0');
+    (void) WriteBlobPadding(image,58,'\0');
     length=(size_t) pcx_info.bytes_per_line;
     pixel_info=AcquireVirtualMemory(length,pcx_info.planes*sizeof(*pixels));
     if (pixel_info == (MemoryInfo *) NULL)
diff --git a/coders/psd.c b/coders/psd.c
index 2b0ea6c4c..bf467ef68 100644
--- a/coders/psd.c
+++ b/coders/psd.c
@@ -3427,8 +3427,7 @@ static size_t WritePascalString(Image *image,const char *value,size_t padding)
     length;

   ssize_t
-    count,
-    i;
+    count;

   /*
     Max length is 255.
@@ -3445,8 +3444,7 @@ static size_t WritePascalString(Image *image,const char *value,size_t padding)
   length++;
   if ((length % padding) == 0)
     return((size_t) count);
-  for (i=0; i < (ssize_t) (padding-(length % padding)); i++)
-    count+=WriteBlobByte(image,0);
+  count+=WriteBlobPadding(image,padding-(length % padding),'\0');
   return((size_t) count);
 }

@@ -3979,8 +3977,7 @@ static MagickBooleanType WritePSDImage(const ImageInfo *image_info,
     psd_info.version=2;
   (void) WriteBlob(image,4,(const unsigned char *) "8BPS");
   (void) WriteBlobMSBShort(image,psd_info.version);  /* version */
-  for (i=1; i <= 6; i++)
-    (void) WriteBlobByte(image, 0);  /* 6 bytes of reserved */
+  (void) WriteBlobPadding(image,6,'\0');  /* 6 bytes of reserved */
   if ((GetImageProfile(image,"icc") == (StringInfo *) NULL) &&
       (SetImageGray(image,exception) != MagickFalse))
     num_channels=1;
@@ -4050,18 +4047,15 @@ static MagickBooleanType WritePSDImage(const ImageInfo *image_info,
       for (i=0; i < (ssize_t) image->colors; i++)
         (void) WriteBlobByte(image,ScaleQuantumToChar(ClampToQuantum(
           image->colormap[i].red)));
-      for ( ; i < 256; i++)
-        (void) WriteBlobByte(image,0);
+      (void) WriteBlobPadding(image,256-image->colors,'\0');
       for (i=0; i < (ssize_t) image->colors; i++)
         (void) WriteBlobByte(image,ScaleQuantumToChar(ClampToQuantum(
           image->colormap[i].green)));
-      for ( ; i < 256; i++)
-        (void) WriteBlobByte(image,0);
+      (void) WriteBlobPadding(image,256-image->colors,'\0');
       for (i=0; i < (ssize_t) image->colors; i++)
         (void) WriteBlobByte(image,ScaleQuantumToChar(ClampToQuantum(
           image->colormap[i].blue)));
-      for ( ; i < 256; i++)
-        (void) WriteBlobByte(image,0);
+      (void) WriteBlobPadding(image,256-image->colors,'\0');
     }
   /*
     Image resource block.
diff --git a/coders/qoi.c b/coders/qoi.c
index 43cc4db2c..b78a3870d 100644
--- a/coders/qoi.c
+++ b/coders/qoi.c
@@ -598,8 +598,7 @@ static MagickBooleanType WriteQOIImage(const ImageInfo *image_info,Image *image,
   /*
     Write the QOI end marker: seven 0x00 bytes followed by 0x01.
   */
-  for (i=0; i < 7; i++)
-    (void) WriteBlobByte(image,0x00);
+  (void) WriteBlobPadding(image,7,'\0');
   (void) WriteBlobByte(image,0x01);
   if (CloseBlob(image) == MagickFalse)
     status=MagickFalse;
diff --git a/coders/viff.c b/coders/viff.c
index 806b6d98c..bda8fa3b4 100644
--- a/coders/viff.c
+++ b/coders/viff.c
@@ -1088,8 +1088,7 @@ static MagickBooleanType WriteVIFFImage(const ImageInfo *image_info,
     (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_enable);
     (void) WriteBlobMSBLong(image,(unsigned int) viff_info.maps_per_cycle);
     (void) WriteBlobMSBLong(image,(unsigned int) viff_info.color_space_model);
-    for (i=0; i < 420; i++)
-      (void) WriteBlobByte(image,'\0');
+    (void) WriteBlobPadding(image,420,'\0');
     /*
       Convert MIFF to VIFF raster pixels.
     */
diff --git a/coders/vips.c b/coders/vips.c
index d54bca1cb..3dc455d2f 100644
--- a/coders/vips.c
+++ b/coders/vips.c
@@ -726,8 +726,7 @@ static MagickBooleanType WriteVIPSImage(const ImageInfo *image_info,
   /*
     Legacy, offsets, future.
   */
-  for (y=0; y < 24; y++)
-    (void) WriteBlobByte(image,0);
+  (void) WriteBlobPadding(image,24,'\0');
   for (y=0; y < (ssize_t) image->rows; y++)
   {
     p=GetVirtualPixels(image,0,y,image->columns,1,exception);