Bug 1334062 - Remove libFuzzer dependencies from fuzzers r=franziskus
authorTim Taubert <ttaubert@mozilla.com>
Thu, 26 Jan 2017 11:11:11 +0100
changeset 13065 4b594ee73b360dbb2489f0246025424f75b36728
parent 13064 4c15f6a36721536a8a6eb2f42823f88a79f29c23
child 13066 5461a96e953916854cfc2768e7b4f58c7dbb12ee
push id1962
push userttaubert@mozilla.com
push dateThu, 26 Jan 2017 10:12:00 +0000
reviewersfranziskus
bugs1334062
Bug 1334062 - Remove libFuzzer dependencies from fuzzers r=franziskus Differential Revision: https://nss-review.dev.mozaws.net/D177
automation/ossfuzz/build.sh
automation/taskcluster/graph/src/extend.js
automation/taskcluster/scripts/fuzz.sh
fuzz/asn1_mutators.cc
fuzz/cert_target.cc
fuzz/fuzz.gyp
fuzz/hash_target.cc
fuzz/initialize.cc
fuzz/pkcs8_target.cc
fuzz/quickder_target.cc
fuzz/shared.h
fuzz/spki_target.cc
--- a/automation/ossfuzz/build.sh
+++ b/automation/ossfuzz/build.sh
@@ -5,18 +5,18 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
 ################################################################################
 
 # List of targets disabled for oss-fuzz.
 declare -A disabled=([pkcs8]=1)
 
 # Build the library.
-CXX="$CXX -stdlib=libc++" CXXFLAGS="$CXXFLAGS -I$SRC/libfuzzer" \
-    LDFLAGS="$CFLAGS" ./build.sh -c -v --fuzz=oss --fuzz=tls --disable-tests
+CXX="$CXX -stdlib=libc++" LDFLAGS="$CFLAGS" \
+    ./build.sh -c -v --fuzz=oss --fuzz=tls --disable-tests
 
 # Find fuzzing targets.
 for fuzzer in $(find ../dist/Debug/bin -name "nssfuzz-*" -printf "%f\n"); do
     name=${fuzzer:8}
     [ -n "${disabled[$name]:-}" ] && continue;
 
     # Copy the binary.
     cp ../dist/Debug/bin/$fuzzer $OUT/$name
--- a/automation/taskcluster/graph/src/extend.js
+++ b/automation/taskcluster/graph/src/extend.js
@@ -320,22 +320,39 @@ async function scheduleFuzzing() {
     tests: "ssl_gtests gtests",
     cycle: "standard",
     symbol: "Gtest",
     kind: "test"
   }));
 
   queue.scheduleTask(merge(base, {
     parent: task_build,
+    name: "Hash",
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/fuzz.sh " +
+        "hash nss/fuzz/corpus/hash -max_total_time=300 -max_len=4096"
+    ],
+    // Need a privileged docker container to remove detect_leaks=0.
+    env: {
+      ASAN_OPTIONS: "allocator_may_return_null=1:detect_leaks=0",
+    },
+    symbol: "Hash",
+    kind: "test"
+  }));
+
+  queue.scheduleTask(merge(base, {
+    parent: task_build,
     name: "QuickDER",
     command: [
       "/bin/bash",
       "-c",
       "bin/checkout.sh && nss/automation/taskcluster/scripts/fuzz.sh " +
-        "quickder nss/fuzz/corpus/quickder -max_total_time=300"
+        "quickder nss/fuzz/corpus/quickder -max_total_time=300 -max_len=10000"
     ],
     // Need a privileged docker container to remove detect_leaks=0.
     env: {
       ASAN_OPTIONS: "allocator_may_return_null=1:detect_leaks=0",
     },
     symbol: "QuickDER",
     kind: "test"
   }));
--- a/automation/taskcluster/scripts/fuzz.sh
+++ b/automation/taskcluster/scripts/fuzz.sh
@@ -6,16 +6,23 @@ type="$1"
 shift
 
 # Fetch artifact if needed.
 fetch_dist
 
 # Clone corpus.
 ./nss/fuzz/clone_corpus.sh
 
-# Ensure we have a directory.
-mkdir -p nss/fuzz/corpus/$type
+# Ensure we have a corpus.
+if [ ! -d "nss/fuzz/corpus/$type" ]; then
+  mkdir -p nss/fuzz/corpus/$type
+
+  # Create a corpus out of what we have.
+  for f in $(find nss/fuzz/corpus -type f); do
+    cp $f "nss/fuzz/corpus/$type"
+  done
+fi
 
 # Fetch objdir name.
 objdir=$(cat dist/latest)
 
 # Run nssfuzz.
 dist/$objdir/bin/nssfuzz-"$type" "$@"
--- a/fuzz/asn1_mutators.cc
+++ b/fuzz/asn1_mutators.cc
@@ -1,17 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <assert.h>
+#include <random>
 #include <string.h>
 #include <tuple>
 
-#include "FuzzerRandom.h"
 #include "asn1_mutators.h"
 
 using namespace std;
 
 static tuple<uint8_t *, size_t> ParseItem(uint8_t *Data, size_t MaxLength) {
   // Short form. Bit 8 has value "0" and bits 7-1 give the length.
   if ((Data[1] & 0x80) == 0) {
     size_t length = min(static_cast<size_t>(Data[1]), MaxLength - 2);
@@ -89,29 +89,34 @@ static vector<uint8_t *> ParseItems(uint
     }
   }
 
   return items;
 }
 
 size_t ASN1MutatorFlipConstructed(uint8_t *Data, size_t Size, size_t MaxSize,
                                   unsigned int Seed) {
-  fuzzer::Random R(Seed);
   auto items = ParseItems(Data, Size);
-  uint8_t *item = items.at(R(items.size()));
+
+  std::mt19937 rng(Seed);
+  std::uniform_int_distribution<size_t> dist(0, items.size() - 1);
+  uint8_t *item = items.at(dist(rng));
 
   // Flip "constructed" type bit.
   item[0] ^= 0x20;
 
   return Size;
 }
 
 size_t ASN1MutatorChangeType(uint8_t *Data, size_t Size, size_t MaxSize,
                              unsigned int Seed) {
-  fuzzer::Random R(Seed);
   auto items = ParseItems(Data, Size);
-  uint8_t *item = items.at(R(items.size()));
 
-  // Change type to a random int [0, 31).
-  item[0] = R(31);
+  std::mt19937 rng(Seed);
+  std::uniform_int_distribution<size_t> dist(0, items.size() - 1);
+  uint8_t *item = items.at(dist(rng));
+
+  // Change type to a random int [0, 30].
+  static std::uniform_int_distribution<size_t> tdist(0, 30);
+  item[0] = tdist(rng);
 
   return Size;
 }
deleted file mode 100644
--- a/fuzz/cert_target.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "FuzzerInternal.h"
-#include "asn1_mutators.h"
-#include "shared.h"
-
-extern const uint16_t DEFAULT_MAX_LENGTH = 3072U;
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
-  CERTCertificate cert;
-  QuickDERDecode(&cert, SEC_SignedCertificateTemplate, Data, Size);
-  return 0;
-}
-
-ADD_CUSTOM_MUTATORS({&ASN1MutatorFlipConstructed, &ASN1MutatorChangeType})
--- a/fuzz/fuzz.gyp
+++ b/fuzz/fuzz.gyp
@@ -87,43 +87,40 @@
         }]
       ],
     },
     {
       'target_name': 'nssfuzz-pkcs8',
       'type': 'executable',
       'sources': [
         'asn1_mutators.cc',
-        'initialize.cc',
         'pkcs8_target.cc',
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
         'fuzz_base',
       ],
     },
     {
       'target_name': 'nssfuzz-quickder',
       'type': 'executable',
       'sources': [
         'asn1_mutators.cc',
-        'initialize.cc',
         'quickder_target.cc',
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
         'fuzz_base',
       ],
     },
     {
       'target_name': 'nssfuzz-hash',
       'type': 'executable',
       'sources': [
         'hash_target.cc',
-        'initialize.cc',
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
         'fuzz_base',
       ],
     },
     {
       'target_name': 'nssfuzz',
--- a/fuzz/hash_target.cc
+++ b/fuzz/hash_target.cc
@@ -1,23 +1,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <memory>
 #include <vector>
 
-#include "FuzzerInternal.h"
 #include "hasht.h"
 #include "pk11pub.h"
 #include "secoidt.h"
 #include "shared.h"
 
-extern const uint16_t DEFAULT_MAX_LENGTH = 4096U;
-
 const std::vector<SECOidTag> algos = {SEC_OID_MD5, SEC_OID_SHA1, SEC_OID_SHA256,
                                       SEC_OID_SHA384, SEC_OID_SHA512};
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   uint8_t hashOut[HASH_LENGTH_MAX];
 
   static std::unique_ptr<NSSDatabase> db(new NSSDatabase());
   assert(db != nullptr);
deleted file mode 100644
--- a/fuzz/initialize.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <string.h>
-#include <algorithm>
-#include <iostream>
-#include <vector>
-
-#include "assert.h"
-
-extern const uint16_t DEFAULT_MAX_LENGTH;
-
-const uint16_t MERGE_MAX_LENGTH = 50000U;
-
-extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
-  std::vector<std::string> args(*argv, *argv + *argc);
-
-  auto hasMaxLenArg = [](std::string &a) { return a.find("-max_len=") == 0; };
-
-  // Nothing to do if a max_len argument is given.
-  if (any_of(args.begin(), args.end(), hasMaxLenArg)) {
-    return 0;
-  }
-
-  auto hasMergeArg = [](std::string &a) { return a.find("-merge=1") == 0; };
-
-  uint16_t max_length = DEFAULT_MAX_LENGTH;
-
-  // Set specific max_len when merging.
-  if (any_of(args.begin(), args.end(), hasMergeArg)) {
-    max_length = MERGE_MAX_LENGTH;
-  }
-
-  std::cerr << "INFO: MaxLen: " << max_length << std::endl;
-  std::string param = "-max_len=" + std::to_string(max_length);
-
-  // Copy original arguments.
-  char **new_args = new char *[*argc + 1];
-  for (int i = 0; i < *argc; i++) {
-    new_args[i] = (*argv)[i];
-  }
-
-  // Append corpus max length.
-  size_t param_len = param.size() + 1;
-  new_args[*argc] = new char[param_len];
-  memcpy(new_args[*argc], param.c_str(), param_len);
-
-  // Update arguments.
-  (*argc)++;
-  *argv = new_args;
-
-  return 0;
-}
--- a/fuzz/pkcs8_target.cc
+++ b/fuzz/pkcs8_target.cc
@@ -3,23 +3,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <memory>
 #include <vector>
 
 #include "keyhi.h"
 #include "pk11pub.h"
 
-#include "FuzzerInternal.h"
 #include "asn1_mutators.h"
 #include "assert.h"
 #include "shared.h"
 
-extern const uint16_t DEFAULT_MAX_LENGTH = 2048U;
-
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
   SECItem data = {siBuffer, (unsigned char *)Data, (unsigned int)Size};
 
   static std::unique_ptr<NSSDatabase> db(new NSSDatabase());
   assert(db != nullptr);
 
   PK11SlotInfo *slot = PK11_GetInternalSlot();
   assert(slot != nullptr);
@@ -30,9 +27,14 @@ extern "C" int LLVMFuzzerTestOneInput(co
                                                nullptr) == SECSuccess) {
     SECKEY_DestroyPrivateKey(key);
   }
 
   PK11_FreeSlot(slot);
   return 0;
 }
 
-ADD_CUSTOM_MUTATORS({&ASN1MutatorFlipConstructed, &ASN1MutatorChangeType})
+extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
+                                          size_t MaxSize, unsigned int Seed) {
+  static Mutators mutators = {&ASN1MutatorFlipConstructed,
+                              &ASN1MutatorChangeType};
+  return CustomMutate(mutators, Data, Size, MaxSize, Seed);
+}
--- a/fuzz/quickder_target.cc
+++ b/fuzz/quickder_target.cc
@@ -1,13 +1,12 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "FuzzerInternal.h"
 #include "asn1_mutators.h"
 #include "shared.h"
 
 const std::vector<const SEC_ASN1Template *> templates = {
     CERT_AttributeTemplate,
     CERT_CertExtensionTemplate,
     CERT_CertificateRequestTemplate,
     CERT_CertificateTemplate,
@@ -57,27 +56,30 @@ const std::vector<const SEC_ASN1Template
     SECKEY_DSAPrivateKeyExportTemplate,
     SECKEY_DSAPublicKeyTemplate,
     SECKEY_PQGParamsTemplate,
     SECKEY_PrivateKeyInfoTemplate,
     SECKEY_RSAPSSParamsTemplate,
     SECKEY_RSAPublicKeyTemplate,
     SECOID_AlgorithmIDTemplate};
 
-extern const uint16_t DEFAULT_MAX_LENGTH = 10000U;
-
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
   char *dest[2048];
 
   for (auto tpl : templates) {
     PORTCheapArenaPool pool;
     SECItem buf = {siBuffer, const_cast<unsigned char *>(Data),
                    static_cast<unsigned int>(Size)};
 
     PORT_InitCheapArena(&pool, DER_DEFAULT_CHUNKSIZE);
     (void)SEC_QuickDERDecodeItem(&pool.arena, dest, tpl, &buf);
     PORT_DestroyCheapArena(&pool);
   }
 
   return 0;
 }
 
-ADD_CUSTOM_MUTATORS({&ASN1MutatorFlipConstructed, &ASN1MutatorChangeType})
+extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
+                                          size_t MaxSize, unsigned int Seed) {
+  static Mutators mutators = {&ASN1MutatorFlipConstructed,
+                              &ASN1MutatorChangeType};
+  return CustomMutate(mutators, Data, Size, MaxSize, Seed);
+}
--- a/fuzz/shared.h
+++ b/fuzz/shared.h
@@ -2,38 +2,39 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef shared_h__
 #define shared_h__
 
-#include "FuzzerRandom.h"
+#include <assert.h>
+#include <random>
 #include "cert.h"
 #include "nss.h"
 
+extern "C" size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize);
+extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
+                                          size_t MaxSize, unsigned int Seed);
+
 class NSSDatabase {
  public:
   NSSDatabase() { assert(NSS_NoDB_Init(nullptr) == SECSuccess); }
   ~NSSDatabase() { assert(NSS_Shutdown() == SECSuccess); }
 };
 
-size_t CustomMutate(std::vector<decltype(LLVMFuzzerCustomMutator) *> mutators,
-                    uint8_t *Data, size_t Size, size_t MaxSize,
-                    unsigned int Seed) {
-  fuzzer::Random R(Seed);
+typedef std::vector<decltype(LLVMFuzzerCustomMutator) *> Mutators;
 
-  if (R.RandBool()) {
-    auto idx = R(mutators.size());
-    return mutators.at(idx)(Data, Size, MaxSize, Seed);
+size_t CustomMutate(Mutators &mutators, uint8_t *Data, size_t Size,
+                    size_t MaxSize, unsigned int Seed) {
+  std::mt19937 rng(Seed);
+  static std::bernoulli_distribution bdist;
+
+  if (bdist(rng)) {
+    std::uniform_int_distribution<size_t> idist(0, mutators.size() - 1);
+    return mutators.at(idist(rng))(Data, Size, MaxSize, Seed);
   }
 
   return LLVMFuzzerMutate(Data, Size, MaxSize);
 }
 
-#define ADD_CUSTOM_MUTATORS(...)                                       \
-  extern "C" size_t LLVMFuzzerCustomMutator(                           \
-      uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed) { \
-    return CustomMutate(__VA_ARGS__, Data, Size, MaxSize, Seed);       \
-  }
-
 #endif  // shared_h__
deleted file mode 100644
--- a/fuzz/spki_target.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "FuzzerInternal.h"
-#include "asn1_mutators.h"
-#include "shared.h"
-
-extern const uint16_t DEFAULT_MAX_LENGTH = 1024U;
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
-  CERTSubjectPublicKeyInfo spki;
-  QuickDERDecode(&spki, CERT_SubjectPublicKeyInfoTemplate, Data, Size);
-  return 0;
-}
-
-ADD_CUSTOM_MUTATORS({&ASN1MutatorFlipConstructed, &ASN1MutatorChangeType})