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