From f8e21539d66697ab692c5545396243654744a33c Mon Sep 17 00:00:00 2001
From: Dirk Lemstra <dirk@git.imagemagick.org>
Date: Sun, 28 Jan 2018 22:44:43 +0100
Subject: [PATCH] Added interlace initializer for some of the fuzzers.

---
 Magick++/fuzz/build_fuzzers.sh  |  9 +++++++--
 Magick++/fuzz/encoder_fuzzer.cc | 26 ++++++++++++++++++++++++--
 Magick++/fuzz/encoder_list.cc   | 18 +++++++++++++-----
 3 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/Magick++/fuzz/build_fuzzers.sh b/Magick++/fuzz/build_fuzzers.sh
index 11ab51bbe..f61667875 100644
--- a/Magick++/fuzz/build_fuzzers.sh
+++ b/Magick++/fuzz/build_fuzzers.sh
@@ -8,7 +8,7 @@ $MAGICK_COMPILER $MAGICK_COMPILER_FLAGS -std=c++11 -I$MAGICK_INCLUDE "$MAGICK_SR
 for f in $MAGICK_SRC/*_fuzzer.cc; do
     fuzzer=$(basename "$f" _fuzzer.cc)
     # encoder_fuzzer is special
-    if [ "$fuzzer" = "encoder" ]; then
+    if [ "$fuzzer" == "encoder" ]; then
         continue
     fi
     $MAGICK_COMPILER $MAGICK_COMPILER_FLAGS -std=c++11 -I$MAGICK_INCLUDE \
@@ -16,11 +16,16 @@ for f in $MAGICK_SRC/*_fuzzer.cc; do
 done
 
 for item in $("$MAGICK_SRC/encoder_list"); do
-    encoder="${item:1}"
+    info=${item:1}
+    encoder=${info%:*}
+    initializer=${info##*:}
     encoder_flags="-DFUZZ_IMAGEMAGICK_ENCODER=$encoder"
     if [ "${item:0:1}" == "+" ]; then
         encoder_flags="$encoder_flags -DFUZZ_IMAGEMAGICK_ENCODER_WRITE=1"
     fi
+    if [ "$initializer" != "" ]; then
+      encoder_flags="$encoder_flags -DFUZZ_IMAGEMAGICK_ENCODER_INITIALIZER=$initializer"
+    fi
     $MAGICK_COMPILER $MAGICK_COMPILER_FLAGS -std=c++11 -I$MAGICK_INCLUDE \
         "$MAGICK_SRC/encoder_fuzzer.cc" -o "$MAGICK_OUTPUT/encoder_${encoder,,}_fuzzer" \
          $encoder_flags $MAGICK_LIBS
diff --git a/Magick++/fuzz/encoder_fuzzer.cc b/Magick++/fuzz/encoder_fuzzer.cc
index b339721aa..e6eaff450 100644
--- a/Magick++/fuzz/encoder_fuzzer.cc
+++ b/Magick++/fuzz/encoder_fuzzer.cc
@@ -7,16 +7,38 @@
 
 #define FUZZ_ENCODER_STRING_LITERAL_X(name) FUZZ_ENCODER_STRING_LITERAL(name)
 #define FUZZ_ENCODER_STRING_LITERAL(name) #name
+
 #ifndef FUZZ_ENCODER
 #define FUZZ_ENCODER FUZZ_ENCODER_STRING_LITERAL_X(FUZZ_IMAGEMAGICK_ENCODER)
 #endif
 
+#ifndef FUZZ_IMAGEMAGICK_INITIALIZER
+#define FUZZ_IMAGEMAGICK_INITIALIZER ""
+#endif
+#define FUZZ_ENCODER_INITIALIZER FUZZ_ENCODER_STRING_LITERAL_X(FUZZ_IMAGEMAGICK_INITIALIZER)
+
+static ssize_t EncoderInitializer(const uint8_t *Data, const size_t Size, Magick::Image &image)
+{
+  if (FUZZ_ENCODER_INITIALIZER == "interlace") {
+    Magick::InterlaceType interlace = (Magick::InterlaceType) *reinterpret_cast<const char *>(Data);
+    if (interlace > Magick::PNGInterlace)
+      return -1;
+    image.interlaceType(interlace);
+    return 1;
+  }
+
+  return 0;
+}
+
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
-  std::string encoder = FUZZ_ENCODER;
-  const Magick::Blob blob(Data, Size);
   Magick::Image image;
+  const ssize_t offset = EncoderInitializer(Data, Size, image);
+  if (offset < 0)
+    return 0;
+  std::string encoder = FUZZ_ENCODER;
   image.magick(encoder);
   image.fileName(std::string(encoder) + ":");
+  const Magick::Blob blob(Data + offset, Size - offset);
   try {
     image.read(blob);
   }
diff --git a/Magick++/fuzz/encoder_list.cc b/Magick++/fuzz/encoder_list.cc
index 0ce18e436..b367fe5d7 100644
--- a/Magick++/fuzz/encoder_list.cc
+++ b/Magick++/fuzz/encoder_list.cc
@@ -5,6 +5,13 @@
 #include <Magick++/Image.h>
 #include <Magick++/STL.h>
 
+static std::string getInitializer(const std::string module)
+{
+  if ((module == "BGR") || (module == "CMYK") || (module =="RGB") || (module =="YUV"))
+    return "interlace";
+  return "";
+}
+
 int main() {
   std::list<Magick::CoderInfo> coderList;
   coderInfoList(&coderList, Magick::CoderInfo::TrueMatch, Magick::CoderInfo::AnyMatch, Magick::CoderInfo::AnyMatch);
@@ -40,12 +47,13 @@ int main() {
 
   for (std::list<Magick::CoderInfo>::iterator it = coderList.begin(); it != coderList.end(); it++)
   {
-    if (std::find(excludeList.begin(), excludeList.end(), (*it).module()) != excludeList.end())
+    std::string module=(*it).module();
+    if (std::find(excludeList.begin(), excludeList.end(), module) != excludeList.end())
       continue;
 
-    if ((*it).name() == (*it).module())
-      std::cout << ((*it).isWritable() ? "+" : "-") << (*it).module() << std::endl;
-    else if (std::find(allowedNames.begin(), allowedNames.end(), (*it).module()) != allowedNames.end())
-      std::cout << ((*it).isWritable() ? "+" : "-") << (*it).name() << std::endl;
+    if ((*it).name() == module)
+      std::cout << ((*it).isWritable() ? "+" : "-") << module << ":" << getInitializer(module) << std::endl;
+    else if (std::find(allowedNames.begin(), allowedNames.end(), module) != allowedNames.end())
+      std::cout << ((*it).isWritable() ? "+" : "-") << (*it).name() << ":" << getInitializer(module) << std::endl;
   }
 }
-- 
2.40.0