Commit fb5751a65 for imagemagick.org

commit fb5751a65e15dccdd86466fe86d8ae787713d8de
Author: Kevin Stubbings <kwstubbs@github.com>
Date:   Thu Apr 9 17:51:20 2026 +0900

    Increase code determinism when when compiling with fuzzing instrumentation (#8544)

    * Increase code determinism when when compiling with fuzzing instrumentation

    * Use --disable-dpc instead of setting a define.

    * Moved method to private header instead.

    * Use consistent code style.

    * Keep custom signal handler.

    ---------

    Co-authored-by: Dirk Lemstra <dirk@lemstra.org>

diff --git a/MagickCore/image.c b/MagickCore/image.c
index 7bc5ed580..18677a7c7 100644
--- a/MagickCore/image.c
+++ b/MagickCore/image.c
@@ -186,7 +186,11 @@ MagickExport Image *AcquireImage(const ImageInfo *image_info,
   image->channel_mask=AllChannels;
   image->channel_map=AcquirePixelChannelMap();
   image->blob=CloneBlobInfo((BlobInfo *) NULL);
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+  image->timestamp=0;  /* Deterministic for fuzzing */
+#else
   image->timestamp=time((time_t *) NULL);
+#endif
   time_limit=GetMagickResourceLimit(TimeResource);
   if (time_limit != MagickResourceInfinity)
     image->ttl=image->timestamp+(time_t) time_limit;
diff --git a/MagickCore/random.c b/MagickCore/random.c
index 6872afdb5..ab5c9b4be 100644
--- a/MagickCore/random.c
+++ b/MagickCore/random.c
@@ -372,6 +372,19 @@ static StringInfo *GenerateEntropicChaos(RandomInfo *random_info)
   */
   entropy=AcquireStringInfo(0);
   LockSemaphoreInfo(random_info->semaphore);
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+  /* Deterministic entropy for fuzzing */
+  {
+    unsigned char
+      *datum;
+
+    SetStringInfoLength(entropy,MaxEntropyExtent);
+    datum=GetStringInfoDatum(entropy);
+    (void) memset(datum,0x42,MaxEntropyExtent);
+    UnlockSemaphoreInfo(random_info->semaphore);
+    return(entropy);
+  }
+#endif
 #if defined(MAGICKCORE_HAVE_GETENTROPY)
   {
     int
@@ -884,6 +897,11 @@ MagickExport void SetRandomKey(RandomInfo *random_info,const size_t length,
   assert(random_info != (RandomInfo *) NULL);
   if (length == 0)
     return;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+  /* Deterministic random key for fuzzing */
+  (void) memset(key,0x42,length);
+  return;
+#endif
   LockSemaphoreInfo(random_info->semaphore);
   signature_info=random_info->signature_info;
   datum=GetStringInfoDatum(random_info->reservoir);
diff --git a/MagickCore/resource-private.h b/MagickCore/resource-private.h
index 3f0f7df67..abcd143a6 100644
--- a/MagickCore/resource-private.h
+++ b/MagickCore/resource-private.h
@@ -35,6 +35,11 @@ extern MagickPrivate void
 extern MagickExport void
   AsynchronousResourceComponentTerminus(void);

+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+extern MagickExport void
+  ResetMagickResourceCounters(void);
+#endif
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
diff --git a/MagickCore/resource.c b/MagickCore/resource.c
index 903536fb8..ec814a73e 100644
--- a/MagickCore/resource.c
+++ b/MagickCore/resource.c
@@ -1354,6 +1354,43 @@ MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
   return(MagickTrue);
 }

+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   R e s e t M a g i c k R e s o u r c e C o u n t e r s                     %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ResetMagickResourceCounters() resets the current resource usage counters
+%  to zero. This is useful for fuzzing to ensure deterministic behavior
+%  between iterations.
+%
+%  The format of the ResetMagickResourceCounters() method is:
+%
+%      void ResetMagickResourceCounters(void)
+%
+*/
+MagickExport void ResetMagickResourceCounters(void)
+{
+  resource_info.width=0;
+  resource_info.height=0;
+  resource_info.list_length=0;
+  resource_info.area=0;
+  resource_info.memory=0;
+  resource_info.map=0;
+  resource_info.disk=0;
+  resource_info.file=0;
+  resource_info.thread=0;
+  resource_info.throttle=0;
+  resource_info.time=0;
+}
+#endif
+
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                             %
diff --git a/MagickCore/timer.c b/MagickCore/timer.c
index f112927de..988d4a036 100644
--- a/MagickCore/timer.c
+++ b/MagickCore/timer.c
@@ -205,7 +205,9 @@ MagickExport TimerInfo *DestroyTimerInfo(TimerInfo *timer_info)
 */
 static double ElapsedTime(void)
 {
-#if defined(MAGICKCORE_HAVE_CLOCK_GETTIME)
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+  return(1.0);  /* Deterministic for fuzzing */
+#elif defined(MAGICKCORE_HAVE_CLOCK_GETTIME)
 #define NANOSECONDS_PER_SECOND  1000000000.0
 #if defined(CLOCK_HIGHRES)
 #  define CLOCK_ID CLOCK_HIGHRES
@@ -377,10 +379,14 @@ static void InitializeEpoch(void)

 MagickExport time_t GetMagickTime(void)
 {
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+  return((time_t) 1234567890);  /* Deterministic for fuzzing */
+#else
   InitializeEpoch();
   if (magick_epoch != 0)
     return(magick_epoch);
   return(time((time_t *) NULL));
+#endif
 }

 /*
diff --git a/oss-fuzz/build_imagemagick.sh b/oss-fuzz/build_imagemagick.sh
index 4c82ffffc..67bf12489 100755
--- a/oss-fuzz/build_imagemagick.sh
+++ b/oss-fuzz/build_imagemagick.sh
@@ -1,6 +1,6 @@
 #!/bin/bash -eu

 autoreconf -fiv
-./configure --prefix="$WORK" --disable-shared --disable-docs --with-jxl CFLAGS="$CFLAGS -I$WORK/include" LIBS="-L$WORK/lib -lbrotlidec -lbrotlienc -lbrotlicommon -lde265" PKG_CONFIG_PATH="$WORK/lib/pkgconfig"
+./configure --prefix="$WORK" --disable-shared --disable-docs --disable-dpc --with-jxl CFLAGS="$CFLAGS -I$WORK/include" LIBS="-L$WORK/lib -lbrotlidec -lbrotlienc -lbrotlicommon -lde265" PKG_CONFIG_PATH="$WORK/lib/pkgconfig"
 make "-j$(nproc)"
 make install