[libcxx-commits] [libcxx] b4bd194 - [libc++] Refactor the fuzzing tests

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Mon Oct 19 09:12:11 PDT 2020


Author: Louis Dionne
Date: 2020-10-19T12:11:50-04:00
New Revision: b4bd194378851c2f421477d4147019d10f2420ac

URL: https://github.com/llvm/llvm-project/commit/b4bd194378851c2f421477d4147019d10f2420ac
DIFF: https://github.com/llvm/llvm-project/commit/b4bd194378851c2f421477d4147019d10f2420ac.diff

LOG: [libc++] Refactor the fuzzing tests

Define all the fuzzing tests in libcxx/test/libcxx/fuzzing, and get
rid of the ad-hoc libcxx/fuzzing directory, which wasn't properly
integrated with the build system or test suite.

As a fly-by change, this also reduces the dependencies of fuzzing tests
on large library components like <iostream>, to make them work on more
platforms.

Added: 
    libcxx/test/libcxx/fuzzing/fuzz.h
    libcxx/test/libcxx/fuzzing/make_heap.pass.cpp
    libcxx/test/libcxx/fuzzing/pop_heap.pass.cpp
    libcxx/test/libcxx/fuzzing/push_heap.pass.cpp
    libcxx/test/libcxx/fuzzing/random.pass.cpp
    libcxx/test/libcxx/fuzzing/regex.pass.cpp
    libcxx/test/libcxx/fuzzing/search.pass.cpp

Modified: 
    libcxx/test/libcxx/fuzzing/nth_element.pass.cpp
    libcxx/test/libcxx/fuzzing/partial_sort.pass.cpp
    libcxx/test/libcxx/fuzzing/partial_sort_copy.pass.cpp
    libcxx/test/libcxx/fuzzing/partition.pass.cpp
    libcxx/test/libcxx/fuzzing/partition_copy.pass.cpp
    libcxx/test/libcxx/fuzzing/sort.pass.cpp
    libcxx/test/libcxx/fuzzing/stable_partition.pass.cpp
    libcxx/test/libcxx/fuzzing/stable_sort.pass.cpp
    libcxx/test/libcxx/fuzzing/unique.pass.cpp
    libcxx/test/libcxx/fuzzing/unique_copy.pass.cpp
    libcxx/utils/ci/oss-fuzz.sh

Removed: 
    libcxx/fuzzing/RoutineNames.txt
    libcxx/fuzzing/fuzz_test.cpp
    libcxx/fuzzing/fuzz_test_template.cpp
    libcxx/fuzzing/fuzzing.cpp
    libcxx/fuzzing/fuzzing.h
    libcxx/test/libcxx/fuzzing/fuzzer_test.h
    libcxx/test/libcxx/fuzzing/geometric_distribution.pass.cpp
    libcxx/test/libcxx/fuzzing/regex_ECMAScript.pass.cpp
    libcxx/test/libcxx/fuzzing/regex_POSIX.pass.cpp
    libcxx/test/libcxx/fuzzing/regex_awk.pass.cpp
    libcxx/test/libcxx/fuzzing/regex_egrep.pass.cpp
    libcxx/test/libcxx/fuzzing/regex_extended.pass.cpp
    libcxx/test/libcxx/fuzzing/regex_grep.pass.cpp


################################################################################
diff  --git a/libcxx/fuzzing/RoutineNames.txt b/libcxx/fuzzing/RoutineNames.txt
deleted file mode 100644
index a853c87e1f73..000000000000
--- a/libcxx/fuzzing/RoutineNames.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-sort
-stable_sort
-partition
-partition_copy
-stable_partition
-unique
-unique_copy
-nth_element
-partial_sort
-partial_sort_copy
-make_heap
-push_heap
-pop_heap
-regex_ECMAScript
-regex_POSIX
-regex_extended
-regex_awk
-regex_grep
-regex_egrep
-search
-uniform_int_distribution
-uniform_real_distribution
-bernoulli_distribution
-poisson_distribution
-geometric_distribution
-binomial_distribution
-negative_binomial_distribution
-exponential_distribution
-gamma_distribution
-weibull_distribution
-extreme_value_distribution
-normal_distribution
-lognormal_distribution
-chi_squared_distribution
-cauchy_distribution
-fisher_f_distribution
-student_t_distribution
-discrete_distribution
-piecewise_constant_distribution
-piecewise_linear_distribution

diff  --git a/libcxx/fuzzing/fuzz_test.cpp b/libcxx/fuzzing/fuzz_test.cpp
deleted file mode 100644
index 508c3b65f2df..000000000000
--- a/libcxx/fuzzing/fuzz_test.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-// -*- C++ -*-
-//===------------------------- fuzz_test.cpp ------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-//  A simple program for running regressions on the fuzzing routines.
-//  This code is not part of any shipping product.
-//
-//  To build:
-//      clang++ -std=c++11 fuzz_test.cpp fuzzing.cpp
-//
-//  To use:
-//      fuzz_test -r partial_sort [-v] files...
-//
-//  Each file should contain a test case.
-
-//  TODO: should add some memory tracking, too.
-
-
-#include <iostream>
-#include <fstream>
-#include <iterator>
-#include <vector>
-#include <map>
-#include <chrono>
-
-#include "fuzzing.h"
-
-//  ==== Count memory allocations ====
-
-struct MemoryCounters {
-    size_t totalAllocationCount;
-    size_t netAllocationCount;
-    size_t totalBytesAllocated;
-    };
-
-MemoryCounters gMemoryCounters;
-
-void ZeroMemoryCounters() {
-    gMemoryCounters.totalAllocationCount = 0;
-    gMemoryCounters.netAllocationCount = 0;
-    gMemoryCounters.totalBytesAllocated = 0;
-}
-
-void* operator new(std::size_t size)
-{
-    if (size == 0) size = 1;
-    void *p = ::malloc(size);
-    if (p == NULL)
-        throw std::bad_alloc();
-    gMemoryCounters.totalAllocationCount += 1;
-    gMemoryCounters.netAllocationCount  += 1;
-    gMemoryCounters.totalBytesAllocated += size;
-    return p;
-}
-
-void* operator new(std::size_t size, const std::nothrow_t&) noexcept
-{
-    try { return operator new(size); }
-    catch (const std::bad_alloc &) {}
-    return nullptr;
-}
-
-void* operator new[](std::size_t size)
-{
-    return ::operator new(size);
-}
-
-void* operator new[](std::size_t size, const std::nothrow_t&) noexcept
-{
-    try { return operator new(size); }
-    catch (const std::bad_alloc &) {}
-    return nullptr;
-}
-
-void  operator delete(void* ptr) noexcept
-{
-    if (ptr)
-        ::free(ptr);
-    gMemoryCounters.netAllocationCount -= 1;
-}
-
-void  operator delete(void* ptr, const std::nothrow_t&) noexcept
-{
-    ::operator delete(ptr);
-}
-
-void  operator delete[](void* ptr) noexcept
-{
-    ::operator delete(ptr);
-}
-
-void  operator delete[](void* ptr, const std::nothrow_t&) noexcept
-{
-    ::operator delete(ptr);
-}
-
-//  ==== End count memory allocations ====
-
-
-typedef int (*FuzzProc) (const uint8_t *data, size_t size);
-
-const std::map<std::string, FuzzProc> procs = {
-    {"sort",                fuzzing::sort},
-    {"stable_sort",         fuzzing::stable_sort},
-    {"partition",           fuzzing::partition},
-    {"partition_copy",      fuzzing::partition_copy},
-    {"stable_partition",    fuzzing::stable_partition},
-    {"unique",              fuzzing::unique},
-    {"unique_copy",         fuzzing::unique_copy},
-    {"nth_element",         fuzzing::nth_element},
-    {"partial_sort",        fuzzing::partial_sort},
-    {"partial_sort_copy",   fuzzing::partial_sort_copy},
-    {"make_heap",           fuzzing::make_heap},
-    {"push_heap",           fuzzing::push_heap},
-    {"pop_heap",            fuzzing::pop_heap},
-    {"regex_ECMAScript",    fuzzing::regex_ECMAScript},
-    {"regex_POSIX",         fuzzing::regex_POSIX},
-    {"regex_extended",      fuzzing::regex_extended},
-    {"regex_awk",           fuzzing::regex_awk},
-    {"regex_grep",          fuzzing::regex_grep},
-    {"regex_egrep",         fuzzing::regex_egrep},
-    {"search",              fuzzing::search}
-};
-
-
-
-bool verbose = false;
-
-void test_one(const char *filename, FuzzProc fp)
-{
-    std::vector<uint8_t> v;
-    std::ifstream f (filename, std::ios::binary);
-    if (!f.is_open())
-        std::cerr << "## Can't open '" << filename << "'" << std::endl;
-    else
-    {
-        typedef std::istream_iterator<uint8_t> Iter;
-        std::copy(Iter(f), Iter(), std::back_inserter(v));
-        if (verbose)
-            std::cout << "File '" << filename << "' contains " << v.size() << " entries" << std::endl;
-        ZeroMemoryCounters();
-        const auto start_time = std::chrono::high_resolution_clock::now();
-        int ret = fp (v.data(), v.size());
-        const auto finish_time = std::chrono::high_resolution_clock::now();
-        MemoryCounters mc = gMemoryCounters;
-        if (ret != 0)
-            std::cerr << "## Failure code: " << ret << std::endl;
-        if (verbose)
-        {
-            std::cout << "Execution time: "
-                << std::chrono::duration_cast<std::chrono::milliseconds>(finish_time - start_time).count()
-                << " milliseconds" << std::endl;
-            std::cout << "Memory: "
-                      << mc.totalBytesAllocated  << " bytes allocated ("
-                      << mc.totalAllocationCount << " allocations); "
-                      << mc.netAllocationCount   << " allocations remain" << std::endl;
-        }
-    }
-}
-
-void usage (const char *name)
-{
-    std::cout << "Usage: " << name << " -r proc [-v] files..." << std::endl;
-    std::cout << "Supported routines:" << std::endl;
-    for (const auto &p : procs)
-        std::cout << "    " << p.first << std::endl;
-    std::cout << std::endl;
-}
-
-// Poor man's command-line options
-const std::string dashR("-r");
-const std::string dashV("-v");
-
-int main(int argc, char *argv[])
-{
-    if (argc < 4 || dashR != argv[1] || procs.find(argv[2]) == procs.end())
-        usage(argv[0]);
-    else {
-        FuzzProc fp = procs.find(argv[2])->second;
-        int firstFile = 3;
-        if (dashV == argv[firstFile])
-        {
-            verbose = true;
-            ++firstFile;
-        }
-        for (int i = firstFile; i < argc; ++i)
-            test_one(argv[i], fp);
-        }
-}

diff  --git a/libcxx/fuzzing/fuzz_test_template.cpp b/libcxx/fuzzing/fuzz_test_template.cpp
deleted file mode 100644
index ba44eef7891d..000000000000
--- a/libcxx/fuzzing/fuzz_test_template.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-//===------------------------- fuzz_test.cpp ------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "fuzzing/fuzzing.h"
-#ifdef NDEBUG
-#undef NDEBUG
-#endif
-#include <cassert>
-
-#ifndef TEST_FUNCTION
-#error TEST_FUNCTION must be defined
-#endif
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  int result = fuzzing::TEST_FUNCTION(data, size);
-  assert(result == 0); return 0;
-}

diff  --git a/libcxx/fuzzing/fuzzing.cpp b/libcxx/fuzzing/fuzzing.cpp
deleted file mode 100644
index 1840c26d4b95..000000000000
--- a/libcxx/fuzzing/fuzzing.cpp
+++ /dev/null
@@ -1,846 +0,0 @@
-// -*- C++ -*-
-//===------------------------- fuzzing.cpp -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-//  A set of routines to use when fuzzing the algorithms in libc++
-//  Each one tests a single algorithm.
-//
-//  They all have the form of:
-//      int `algorithm`(const uint8_t *data, size_t size);
-//
-//  They perform the operation, and then check to see if the results are correct.
-//  If so, they return zero, and non-zero otherwise.
-//
-//  For example, sort calls std::sort, then checks two things:
-//      (1) The resulting vector is sorted
-//      (2) The resulting vector contains the same elements as the original data.
-
-
-
-#include "fuzzing.h"
-#include <vector>
-#include <algorithm>
-#include <functional>
-#include <regex>
-#include <random>
-#include <cassert>
-#include <cmath>
-
-#include <iostream>
-
-#ifdef NDEBUG
-#undef NDEBUG
-#endif
-#include <cassert>
-//  If we had C++14, we could use the four iterator version of is_permutation and equal
-
-#ifndef _LIBCPP_VERSION
-#error These test should be built with libc++ only.
-#endif
-
-namespace fuzzing {
-
-//  This is a struct we can use to test the stable_XXX algorithms.
-//  perform the operation on the key, then check the order of the payload.
-
-struct stable_test {
-    uint8_t key;
-    size_t payload;
-
-    stable_test(uint8_t k) : key(k), payload(0) {}
-    stable_test(uint8_t k, size_t p) : key(k), payload(p) {}
-    };
-
-void swap(stable_test &lhs, stable_test &rhs)
-{
-    using std::swap;
-    swap(lhs.key,     rhs.key);
-    swap(lhs.payload, rhs.payload);
-}
-
-struct key_less
-{
-    bool operator () (const stable_test &lhs, const stable_test &rhs) const
-    {
-        return lhs.key < rhs.key;
-    }
-};
-
-struct payload_less
-{
-    bool operator () (const stable_test &lhs, const stable_test &rhs) const
-    {
-        return lhs.payload < rhs.payload;
-    }
-};
-
-struct total_less
-{
-    bool operator () (const stable_test &lhs, const stable_test &rhs) const
-    {
-        return lhs.key == rhs.key ? lhs.payload < rhs.payload : lhs.key < rhs.key;
-    }
-};
-
-bool operator==(const stable_test &lhs, const stable_test &rhs)
-{
-    return lhs.key == rhs.key && lhs.payload == rhs.payload;
-}
-
-
-template<typename T>
-struct is_even
-{
-    bool operator () (const T &t) const
-    {
-        return t % 2 == 0;
-    }
-};
-
-
-template<>
-struct is_even<stable_test>
-{
-    bool operator () (const stable_test &t) const
-    {
-        return t.key % 2 == 0;
-    }
-};
-
-typedef std::vector<uint8_t> Vec;
-typedef std::vector<stable_test> StableVec;
-typedef StableVec::const_iterator SVIter;
-
-//  Cheap version of is_permutation
-//  Builds a set of buckets for each of the key values.
-//  Sums all the payloads.
-//  Not 100% perfect, but _way_ faster
-bool is_permutation(SVIter first1, SVIter last1, SVIter first2)
-{
-    size_t xBuckets[256]  = {0};
-    size_t xPayloads[256] = {0};
-    size_t yBuckets[256]  = {0};
-    size_t yPayloads[256] = {0};
-
-    for (; first1 != last1; ++first1, ++first2)
-    {
-        xBuckets [first1->key]++;
-        xPayloads[first1->key] += first1->payload;
-
-        yBuckets [first2->key]++;
-        yPayloads[first2->key] += first2->payload;
-    }
-
-    for (size_t i = 0; i < 256; ++i)
-    {
-        if (xBuckets[i]  != yBuckets[i])
-            return false;
-        if (xPayloads[i] != yPayloads[i])
-            return false;
-    }
-
-    return true;
-}
-
-template <typename Iter1, typename Iter2>
-bool is_permutation(Iter1 first1, Iter1 last1, Iter2 first2)
-{
-    static_assert((std::is_same<typename std::iterator_traits<Iter1>::value_type, uint8_t>::value), "");
-    static_assert((std::is_same<typename std::iterator_traits<Iter2>::value_type, uint8_t>::value), "");
-
-    size_t xBuckets[256]  = {0};
-    size_t yBuckets[256]  = {0};
-
-    for (; first1 != last1; ++first1, ++first2)
-    {
-        xBuckets [*first1]++;
-        yBuckets [*first2]++;
-    }
-
-    for (size_t i = 0; i < 256; ++i)
-        if (xBuckets[i]  != yBuckets[i])
-            return false;
-
-    return true;
-}
-
-//  == sort ==
-int sort(const uint8_t *data, size_t size)
-{
-    Vec working(data, data + size);
-    std::sort(working.begin(), working.end());
-
-    if (!std::is_sorted(working.begin(), working.end())) return 1;
-    if (!fuzzing::is_permutation(data, data + size, working.cbegin())) return 99;
-    return 0;
-}
-
-
-//  == stable_sort ==
-int stable_sort(const uint8_t *data, size_t size)
-{
-    StableVec input;
-    for (size_t i = 0; i < size; ++i)
-        input.push_back(stable_test(data[i], i));
-    StableVec working = input;
-    std::stable_sort(working.begin(), working.end(), key_less());
-
-    if (!std::is_sorted(working.begin(), working.end(), key_less()))   return 1;
-    auto iter = working.begin();
-    while (iter != working.end())
-    {
-        auto range = std::equal_range(iter, working.end(), *iter, key_less());
-        if (!std::is_sorted(range.first, range.second, total_less())) return 2;
-        iter = range.second;
-    }
-    if (!fuzzing::is_permutation(input.cbegin(), input.cend(), working.cbegin())) return 99;
-    return 0;
-}
-
-//  == partition ==
-int partition(const uint8_t *data, size_t size)
-{
-    Vec working(data, data + size);
-    auto iter = std::partition(working.begin(), working.end(), is_even<uint8_t>());
-
-    if (!std::all_of (working.begin(), iter, is_even<uint8_t>())) return 1;
-    if (!std::none_of(iter,   working.end(), is_even<uint8_t>())) return 2;
-    if (!fuzzing::is_permutation(data, data + size, working.cbegin())) return 99;
-    return 0;
-}
-
-
-//  == partition_copy ==
-int partition_copy(const uint8_t *data, size_t size)
-{
-    Vec v1, v2;
-    auto iter = std::partition_copy(data, data + size,
-        std::back_inserter<Vec>(v1), std::back_inserter<Vec>(v2),
-        is_even<uint8_t>());
-  ((void)iter);
-//  The two vectors should add up to the original size
-    if (v1.size() + v2.size() != size) return 1;
-
-//  All of the even values should be in the first vector, and none in the second
-    if (!std::all_of (v1.begin(), v1.end(), is_even<uint8_t>())) return 2;
-    if (!std::none_of(v2.begin(), v2.end(), is_even<uint8_t>())) return 3;
-
-//  Every value in both vectors has to be in the original
-
-//	Make a copy of the input, and sort it
-    Vec v0{data, data + size};
-    std::sort(v0.begin(), v0.end());
-
-//	Sort each vector and ensure that all of the elements appear in the original input
-    std::sort(v1.begin(), v1.end());
-    if (!std::includes(v0.begin(), v0.end(), v1.begin(), v1.end())) return 4;
-
-    std::sort(v2.begin(), v2.end());
-    if (!std::includes(v0.begin(), v0.end(), v2.begin(), v2.end())) return 5;
-
-//  This, while simple, is really slow - 20 seconds on a 500K element input.
-//     for (auto v: v1)
-//         if (std::find(data, data + size, v) == data + size) return 4;
-//
-//     for (auto v: v2)
-//         if (std::find(data, data + size, v) == data + size) return 5;
-
-    return 0;
-}
-
-//  == stable_partition ==
-int stable_partition (const uint8_t *data, size_t size)
-{
-    StableVec input;
-    for (size_t i = 0; i < size; ++i)
-        input.push_back(stable_test(data[i], i));
-    StableVec working = input;
-    auto iter = std::stable_partition(working.begin(), working.end(), is_even<stable_test>());
-
-    if (!std::all_of (working.begin(), iter, is_even<stable_test>())) return 1;
-    if (!std::none_of(iter,   working.end(), is_even<stable_test>())) return 2;
-    if (!std::is_sorted(working.begin(), iter, payload_less()))   return 3;
-    if (!std::is_sorted(iter,   working.end(), payload_less()))   return 4;
-    if (!fuzzing::is_permutation(input.cbegin(), input.cend(), working.cbegin())) return 99;
-    return 0;
-}
-
-//  == nth_element ==
-//  use the first element as a position into the data
-int nth_element (const uint8_t *data, size_t size)
-{
-    if (size <= 1) return 0;
-    const size_t partition_point = data[0] % size;
-    Vec working(data + 1, data + size);
-    const auto partition_iter = working.begin() + partition_point;
-    std::nth_element(working.begin(), partition_iter, working.end());
-
-//  nth may be the end iterator, in this case nth_element has no effect.
-    if (partition_iter == working.end())
-    {
-        if (!std::equal(data + 1, data + size, working.begin())) return 98;
-    }
-    else
-    {
-        const uint8_t nth = *partition_iter;
-        if (!std::all_of(working.begin(), partition_iter, [=](uint8_t v) { return v <= nth; }))
-            return 1;
-        if (!std::all_of(partition_iter, working.end(),   [=](uint8_t v) { return v >= nth; }))
-            return 2;
-        if (!fuzzing::is_permutation(data + 1, data + size, working.cbegin())) return 99;
-        }
-
-    return 0;
-}
-
-//  == partial_sort ==
-//  use the first element as a position into the data
-int partial_sort (const uint8_t *data, size_t size)
-{
-    if (size <= 1) return 0;
-    const size_t sort_point = data[0] % size;
-    Vec working(data + 1, data + size);
-    const auto sort_iter = working.begin() + sort_point;
-    std::partial_sort(working.begin(), sort_iter, working.end());
-
-    if (sort_iter != working.end())
-    {
-        const uint8_t nth = *std::min_element(sort_iter, working.end());
-        if (!std::all_of(working.begin(), sort_iter, [=](uint8_t v) { return v <= nth; }))
-            return 1;
-        if (!std::all_of(sort_iter, working.end(),   [=](uint8_t v) { return v >= nth; }))
-            return 2;
-    }
-    if (!std::is_sorted(working.begin(), sort_iter)) return 3;
-    if (!fuzzing::is_permutation(data + 1, data + size, working.cbegin())) return 99;
-
-    return 0;
-}
-
-
-//  == partial_sort_copy ==
-//  use the first element as a count
-int partial_sort_copy (const uint8_t *data, size_t size)
-{
-    if (size <= 1) return 0;
-    const size_t num_results = data[0] % size;
-    Vec results(num_results);
-    (void) std::partial_sort_copy(data + 1, data + size, results.begin(), results.end());
-
-//  The results have to be sorted
-    if (!std::is_sorted(results.begin(), results.end())) return 1;
-//  All the values in results have to be in the original data
-    for (auto v: results)
-        if (std::find(data + 1, data + size, v) == data + size) return 2;
-
-//  The things in results have to be the smallest N in the original data
-    Vec sorted(data + 1, data + size);
-    std::sort(sorted.begin(), sorted.end());
-    if (!std::equal(results.begin(), results.end(), sorted.begin())) return 3;
-    return 0;
-}
-
-//  The second sequence has been "uniqued"
-template <typename Iter1, typename Iter2>
-static bool compare_unique(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2)
-{
-    assert(first1 != last1 && first2 != last2);
-    if (*first1 != *first2) return false;
-
-    uint8_t last_value = *first1;
-    ++first1; ++first2;
-    while(first1 != last1 && first2 != last2)
-    {
-    //  Skip over dups in the first sequence
-        while (*first1 == last_value)
-            if (++first1 == last1) return false;
-        if (*first1 != *first2) return false;
-        last_value = *first1;
-        ++first1; ++first2;
-    }
-
-//  Still stuff left in the 'uniqued' sequence - oops
-    if (first1 == last1 && first2 != last2) return false;
-
-//  Still stuff left in the original sequence - better be all the same
-    while (first1 != last1)
-    {
-        if (*first1 != last_value) return false;
-        ++first1;
-    }
-    return true;
-}
-
-//  == unique ==
-int unique (const uint8_t *data, size_t size)
-{
-    Vec working(data, data + size);
-    std::sort(working.begin(), working.end());
-    Vec results = working;
-    Vec::iterator new_end = std::unique(results.begin(), results.end());
-    Vec::iterator it;   // scratch iterator
-
-//  Check the size of the unique'd sequence.
-//  it should only be zero if the input sequence was empty.
-    if (results.begin() == new_end)
-        return working.size() == 0 ? 0 : 1;
-
-//  'results' is sorted
-    if (!std::is_sorted(results.begin(), new_end)) return 2;
-
-//  All the elements in 'results' must be 
diff erent
-    it = results.begin();
-    uint8_t prev_value = *it++;
-    for (; it != new_end; ++it)
-    {
-        if (*it == prev_value) return 3;
-        prev_value = *it;
-    }
-
-//  Every element in 'results' must be in 'working'
-    for (it = results.begin(); it != new_end; ++it)
-        if (std::find(working.begin(), working.end(), *it) == working.end())
-            return 4;
-
-//  Every element in 'working' must be in 'results'
-    for (auto v : working)
-        if (std::find(results.begin(), new_end, v) == new_end)
-            return 5;
-
-    return 0;
-}
-
-//  == unique_copy ==
-int unique_copy (const uint8_t *data, size_t size)
-{
-    Vec working(data, data + size);
-    std::sort(working.begin(), working.end());
-    Vec results;
-    (void) std::unique_copy(working.begin(), working.end(),
-                            std::back_inserter<Vec>(results));
-    Vec::iterator it;   // scratch iterator
-
-//  Check the size of the unique'd sequence.
-//  it should only be zero if the input sequence was empty.
-    if (results.size() == 0)
-        return working.size() == 0 ? 0 : 1;
-
-//  'results' is sorted
-    if (!std::is_sorted(results.begin(), results.end())) return 2;
-
-//  All the elements in 'results' must be 
diff erent
-    it = results.begin();
-    uint8_t prev_value = *it++;
-    for (; it != results.end(); ++it)
-    {
-        if (*it == prev_value) return 3;
-        prev_value = *it;
-    }
-
-//  Every element in 'results' must be in 'working'
-    for (auto v : results)
-        if (std::find(working.begin(), working.end(), v) == working.end())
-            return 4;
-
-//  Every element in 'working' must be in 'results'
-    for (auto v : working)
-        if (std::find(results.begin(), results.end(), v) == results.end())
-            return 5;
-
-    return 0;
-}
-
-
-// --   regex fuzzers
-static int regex_helper(const uint8_t *data, size_t size, std::regex::flag_type flag)
-{
-    if (size > 0)
-    {
-#ifndef _LIBCPP_NO_EXCEPTIONS
-        try
-        {
-            std::string s((const char *)data, size);
-            std::regex re(s, flag);
-            return std::regex_match(s, re) ? 1 : 0;
-        }
-        catch (std::regex_error &ex) {}
-#else
-      ((void)data);
-      ((void)size);
-      ((void)flag);
-#endif
-    }
-    return 0;
-}
-
-
-int regex_ECMAScript (const uint8_t *data, size_t size)
-{
-    (void) regex_helper(data, size, std::regex_constants::ECMAScript);
-    return 0;
-}
-
-int regex_POSIX (const uint8_t *data, size_t size)
-{
-    (void) regex_helper(data, size, std::regex_constants::basic);
-    return 0;
-}
-
-int regex_extended (const uint8_t *data, size_t size)
-{
-    (void) regex_helper(data, size, std::regex_constants::extended);
-    return 0;
-}
-
-int regex_awk (const uint8_t *data, size_t size)
-{
-    (void) regex_helper(data, size, std::regex_constants::awk);
-    return 0;
-}
-
-int regex_grep (const uint8_t *data, size_t size)
-{
-    (void) regex_helper(data, size, std::regex_constants::grep);
-    return 0;
-}
-
-int regex_egrep (const uint8_t *data, size_t size)
-{
-    (void) regex_helper(data, size, std::regex_constants::egrep);
-    return 0;
-}
-
-// --   heap fuzzers
-int make_heap (const uint8_t *data, size_t size)
-{
-    Vec working(data, data + size);
-    std::make_heap(working.begin(), working.end());
-
-    if (!std::is_heap(working.begin(), working.end())) return 1;
-    if (!fuzzing::is_permutation(data, data + size, working.cbegin())) return 99;
-    return 0;
-}
-
-int push_heap (const uint8_t *data, size_t size)
-{
-    if (size < 2) return 0;
-
-//  Make a heap from the first half of the data
-    Vec working(data, data + size);
-    auto iter = working.begin() + (size / 2);
-    std::make_heap(working.begin(), iter);
-    if (!std::is_heap(working.begin(), iter)) return 1;
-
-//  Now push the rest onto the heap, one at a time
-    ++iter;
-    for (; iter != working.end(); ++iter) {
-        std::push_heap(working.begin(), iter);
-        if (!std::is_heap(working.begin(), iter)) return 2;
-        }
-
-    if (!fuzzing::is_permutation(data, data + size, working.cbegin())) return 99;
-    return 0;
-}
-
-int pop_heap (const uint8_t *data, size_t size)
-{
-    if (size < 2) return 0;
-    Vec working(data, data + size);
-    std::make_heap(working.begin(), working.end());
-
-//  Pop things off, one at a time
-    auto iter = --working.end();
-    while (iter != working.begin()) {
-        std::pop_heap(working.begin(), iter);
-        if (!std::is_heap(working.begin(), --iter)) return 2;
-        }
-
-    return 0;
-}
-
-
-// --   search fuzzers
-int search (const uint8_t *data, size_t size)
-{
-    if (size < 2) return 0;
-
-    const size_t pat_size = data[0] * (size - 1) / std::numeric_limits<uint8_t>::max();
-    assert(pat_size <= size - 1);
-    const uint8_t *pat_begin = data + 1;
-    const uint8_t *pat_end   = pat_begin + pat_size;
-    const uint8_t *data_end  = data + size;
-    assert(pat_end <= data_end);
-//  std::cerr << "data[0] = " << size_t(data[0]) << " ";
-//  std::cerr << "Pattern size = " << pat_size << "; corpus is " << size - 1 << std::endl;
-    auto it = std::search(pat_end, data_end, pat_begin, pat_end);
-    if (it != data_end) // not found
-        if (!std::equal(pat_begin, pat_end, it))
-            return 1;
-    return 0;
-}
-
-template <typename S>
-static int search_helper (const uint8_t *data, size_t size)
-{
-    if (size < 2) return 0;
-
-    const size_t pat_size = data[0] * (size - 1) / std::numeric_limits<uint8_t>::max();
-    const uint8_t *pat_begin = data + 1;
-    const uint8_t *pat_end   = pat_begin + pat_size;
-    const uint8_t *data_end  = data + size;
-
-    auto it = std::search(pat_end, data_end, S(pat_begin, pat_end));
-    if (it != data_end) // not found
-        if (!std::equal(pat_begin, pat_end, it))
-            return 1;
-    return 0;
-}
-
-//  These are still in std::experimental
-// int search_boyer_moore (const uint8_t *data, size_t size)
-// {
-//  return search_helper<std::boyer_moore_searcher<const uint8_t *>>(data, size);
-// }
-//
-// int search_boyer_moore_horspool (const uint8_t *data, size_t size)
-// {
-//  return search_helper<std::boyer_moore_horspool_searcher<const uint8_t *>>(data, size);
-// }
-
-
-// --   set operation fuzzers
-template <typename S>
-static void set_helper (const uint8_t *data, size_t size, Vec &v1, Vec &v2)
-{
-    assert(size > 1);
-
-    const size_t pat_size = data[0] * (size - 1) / std::numeric_limits<uint8_t>::max();
-    const uint8_t *pat_begin = data + 1;
-    const uint8_t *pat_end   = pat_begin + pat_size;
-    const uint8_t *data_end  = data + size;
-    v1.assign(pat_begin, pat_end);
-    v2.assign(pat_end, data_end);
-
-    std::sort(v1.begin(), v1.end());
-    std::sort(v2.begin(), v2.end());
-}
-
-enum class ParamKind {
-  OneValue,
-  TwoValues,
-  PointerRange
-};
-
-template <class IntT>
-std::vector<IntT> GetValues(const uint8_t *data, size_t size) {
-  std::vector<IntT> result;
-  while (size >= sizeof(IntT)) {
-    IntT tmp;
-    memcpy(&tmp, data, sizeof(IntT));
-    size -= sizeof(IntT);
-    data += sizeof(IntT);
-    result.push_back(tmp);
-  }
-  return result;
-}
-
-enum InitKind {
-  Default,
-  DoubleOnly,
-  VectorDouble,
-  VectorResultType
-};
-
-
-
-template <class Dist>
-struct ParamTypeHelper {
-  using ParamT = typename Dist::param_type;
-  using ResultT = typename Dist::result_type;
-  static_assert(std::is_same<ResultT, typename ParamT::distribution_type::result_type>::value, "");
-  static  ParamT Create(const uint8_t* data, size_t size, bool &OK) {
-
-    constexpr bool select_vector_result = std::is_constructible<ParamT, ResultT*, ResultT*, ResultT*>::value;
-    constexpr bool select_vector_double = std::is_constructible<ParamT, double*, double*>::value;
-    constexpr int selector = select_vector_result ? 0 : (select_vector_double ? 1 : 2);
-    return DispatchAndCreate(std::integral_constant<int, selector>{}, data, size, OK);
-
-  }
-
-  static ParamT DispatchAndCreate(std::integral_constant<int, 0>, const uint8_t *data, size_t size, bool &OK) {
-    return CreateVectorResult(data, size, OK);
-  }
-  static ParamT DispatchAndCreate(std::integral_constant<int, 1>, const uint8_t *data, size_t size, bool &OK) {
-    return CreateVectorDouble(data, size, OK);
-  }
-  static ParamT DispatchAndCreate(std::integral_constant<int, 2>, const uint8_t *data, size_t size, bool &OK) {
-    return CreateDefault(data, size, OK);
-  }
-
-static ParamT
-CreateVectorResult(const uint8_t *data, size_t size, bool &OK) {
-  auto Input = GetValues<ResultT>(data, size);
-  OK = false;
-  if (Input.size() < 10)
-    return ParamT{};
-  OK = true;
-  auto Beg = Input.begin();
-  auto End = Input.end();
-  auto Mid = Beg + ((End - Beg) / 2);
-
-  assert(Mid - Beg <= (End  -  Mid));
-  ParamT p(Beg, Mid, Mid);
-  return p;
-}
-
-  static ParamT
-  CreateVectorDouble(const uint8_t *data, size_t size, bool &OK) {
-    auto Input = GetValues<double>(data, size);
-
-    OK = true;
-    auto Beg = Input.begin();
-    auto End = Input.end();
-
-    ParamT p(Beg, End);
-    return p;
-  }
-
-
-  static ParamT
-  CreateDefault(const uint8_t *data, size_t size, bool &OK) {
-    OK = false;
-    if (size < sizeof(ParamT))
-      return ParamT{};
-    OK = true;
-    ParamT input;
-    memcpy(&input, data, sizeof(ParamT));
-    return input;
-  }
-
-};
-
-
-
-
-template <class IntT>
-struct ParamTypeHelper<std::poisson_distribution<IntT>> {
-    using Dist = std::poisson_distribution<IntT>;
-      using ParamT = typename Dist::param_type;
-    using ResultT = typename Dist::result_type;
-
-     static ParamT Create(const uint8_t *data, size_t size, bool& OK) {
-        OK = false;
-        auto vals = GetValues<double>(data, size);
-        if (vals.empty() || std::isnan(vals[0]) || std::isnan(std::abs(vals[0])) || vals[0] < 0 )
-          return ParamT{};
-        OK = true;
-        //std::cerr << "Value: " << vals[0] << std::endl;
-        return ParamT{vals[0]};
-     }
-};
-
-
-template <class IntT>
-struct ParamTypeHelper<std::geometric_distribution<IntT>> {
-    using Dist = std::geometric_distribution<IntT>;
-      using ParamT = typename Dist::param_type;
-    using ResultT = typename Dist::result_type;
-
-     static ParamT Create(const uint8_t *data, size_t size, bool& OK) {
-        OK = false;
-        auto vals = GetValues<double>(data, size);
-        if (vals.empty() || std::isnan(vals[0]) || vals[0] < 0 )
-          return ParamT{};
-        OK = true;
-       // std::cerr << "Value: " << vals[0] << std::endl;
-        return ParamT{vals[0]};
-     }
-};
-
-
-template <class IntT>
-struct ParamTypeHelper<std::lognormal_distribution<IntT>> {
-    using Dist = std::lognormal_distribution<IntT>;
-      using ParamT = typename Dist::param_type;
-    using ResultT = typename Dist::result_type;
-
-     static ParamT Create(const uint8_t *data, size_t size, bool& OK) {
-        OK = false;
-        auto vals = GetValues<ResultT>(data, size);
-        if (vals.size() < 2 )
-          return ParamT{};
-        OK = true;
-        return ParamT{vals[0], vals[1]};
-     }
-};
-
-
-template <>
-struct ParamTypeHelper<std::bernoulli_distribution> {
-    using Dist = std::bernoulli_distribution;
-      using ParamT = typename Dist::param_type;
-    using ResultT = typename Dist::result_type;
-
-     static ParamT Create(const uint8_t *data, size_t size, bool& OK) {
-        OK = false;
-        auto vals = GetValues<double>(data, size);
-        if (vals.empty())
-          return ParamT{};
-        OK = true;
-        return ParamT{vals[0]};
-     }
-};
-
-template <class Distribution>
-int random_distribution_helper(const uint8_t *data, size_t size) {
-
-  std::mt19937 engine;
-  using ParamT = typename Distribution::param_type;
-  bool OK;
-  ParamT p = ParamTypeHelper<Distribution>::Create(data, size, OK);
-  if (!OK)
-    return 0;
-  Distribution d(p);
-  volatile auto res = d(engine);
-  if (std::isnan(res)) {
-    // FIXME(llvm.org/PR44289):
-    // Investigate why these distributions are returning NaN and decide
-    // if that's what we want them to be doing.
-    //
-    // Make this assert false (or return non-zero).
-    return 0;
-  }
-  return 0;
-}
-
-#define DEFINE_RANDOM_TEST(name, ...) \
-int name(const uint8_t *data, size_t size) { \
-  return random_distribution_helper< std::name __VA_ARGS__ >(data, size); \
-}
-DEFINE_RANDOM_TEST(uniform_int_distribution,<std::int16_t>)
-DEFINE_RANDOM_TEST(uniform_real_distribution,<float>)
-DEFINE_RANDOM_TEST(bernoulli_distribution)
-DEFINE_RANDOM_TEST(poisson_distribution,<std::int16_t>)
-DEFINE_RANDOM_TEST(geometric_distribution,<std::int16_t>)
-DEFINE_RANDOM_TEST(binomial_distribution, <std::int16_t>)
-DEFINE_RANDOM_TEST(negative_binomial_distribution, <std::int16_t>)
-DEFINE_RANDOM_TEST(exponential_distribution, <float>)
-DEFINE_RANDOM_TEST(gamma_distribution, <float>)
-DEFINE_RANDOM_TEST(weibull_distribution, <float>)
-DEFINE_RANDOM_TEST(extreme_value_distribution, <float>)
-DEFINE_RANDOM_TEST(normal_distribution, <float>)
-DEFINE_RANDOM_TEST(lognormal_distribution, <float>)
-DEFINE_RANDOM_TEST(chi_squared_distribution, <float>)
-DEFINE_RANDOM_TEST(cauchy_distribution, <float>)
-DEFINE_RANDOM_TEST(fisher_f_distribution, <float>)
-DEFINE_RANDOM_TEST(student_t_distribution, <float>)
-DEFINE_RANDOM_TEST(discrete_distribution, <std::int16_t>)
-DEFINE_RANDOM_TEST(piecewise_constant_distribution, <float>)
-DEFINE_RANDOM_TEST(piecewise_linear_distribution, <float>)
-
-} // namespace fuzzing

diff  --git a/libcxx/fuzzing/fuzzing.h b/libcxx/fuzzing/fuzzing.h
deleted file mode 100644
index 99a3aa14a777..000000000000
--- a/libcxx/fuzzing/fuzzing.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// -*- C++ -*-
-//===-------------------------- fuzzing.h --------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _LIBCPP_FUZZING
-#define _LIBCPP_FUZZING
-
-#include <cstddef> // for size_t
-#include <cstdint> // for uint8_t
-
-namespace fuzzing {
-
-//  These all return 0 on success; != 0 on failure
-    int sort             (const uint8_t *data, size_t size);
-    int stable_sort      (const uint8_t *data, size_t size);
-    int partition        (const uint8_t *data, size_t size);
-    int partition_copy   (const uint8_t *data, size_t size);
-    int stable_partition (const uint8_t *data, size_t size);
-	int unique           (const uint8_t *data, size_t size);
-	int unique_copy      (const uint8_t *data, size_t size);
-
-//  partition and stable_partition take Bi-Di iterators.
-//  Should test those, too
-    int nth_element       (const uint8_t *data, size_t size);
-    int partial_sort      (const uint8_t *data, size_t size);
-    int partial_sort_copy (const uint8_t *data, size_t size);
-
-//  Heap operations
-    int make_heap        (const uint8_t *data, size_t size);
-    int push_heap        (const uint8_t *data, size_t size);
-    int pop_heap         (const uint8_t *data, size_t size);
-
-//  Various flavors of regex
-    int regex_ECMAScript (const uint8_t *data, size_t size);
-    int regex_POSIX      (const uint8_t *data, size_t size);
-    int regex_extended   (const uint8_t *data, size_t size);
-    int regex_awk        (const uint8_t *data, size_t size);
-    int regex_grep       (const uint8_t *data, size_t size);
-    int regex_egrep      (const uint8_t *data, size_t size);
-
-//	Searching
-	int search                      (const uint8_t *data, size_t size);
-// 	int search_boyer_moore          (const uint8_t *data, size_t size);
-// 	int search_boyer_moore_horspool (const uint8_t *data, size_t size);
-
-//	Set operations
-// 	int includes                 (const uint8_t *data, size_t size);
-// 	int set_union                (const uint8_t *data, size_t size);
-// 	int set_intersection         (const uint8_t *data, size_t size);
-// 	int set_
diff erence           (const uint8_t *data, size_t size);
-// 	int set_symmetric_
diff erence (const uint8_t *data, size_t size);
-// 	int merge                    (const uint8_t *data, size_t size);
-
-// Random numbers
-  int uniform_int_distribution(const uint8_t*, size_t);
-  int uniform_real_distribution(const uint8_t*, size_t);
-  int bernoulli_distribution(const uint8_t*, size_t);
-  int poisson_distribution(const uint8_t*, size_t);
-  int geometric_distribution(const uint8_t*, size_t);
-  int binomial_distribution(const uint8_t*, size_t);
-  int negative_binomial_distribution(const uint8_t*, size_t);
-  int exponential_distribution(const uint8_t*, size_t);
-  int gamma_distribution(const uint8_t*, size_t);
-  int weibull_distribution(const uint8_t*, size_t);
-  int extreme_value_distribution(const uint8_t*, size_t);
-  int normal_distribution(const uint8_t*, size_t);
-  int lognormal_distribution(const uint8_t*, size_t);
-  int chi_squared_distribution(const uint8_t*, size_t);
-  int cauchy_distribution(const uint8_t*, size_t);
-  int fisher_f_distribution(const uint8_t*, size_t);
-  int student_t_distribution(const uint8_t*, size_t);
-  int discrete_distribution(const uint8_t*, size_t);
-  int piecewise_constant_distribution(const uint8_t*, size_t);
-  int piecewise_linear_distribution(const uint8_t*, size_t);
-
-} // namespace fuzzing
-
-#endif // _LIBCPP_FUZZING

diff  --git a/libcxx/test/libcxx/fuzzing/fuzz.h b/libcxx/test/libcxx/fuzzing/fuzz.h
new file mode 100644
index 000000000000..1281879c536c
--- /dev/null
+++ b/libcxx/test/libcxx/fuzzing/fuzz.h
@@ -0,0 +1,144 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_LIBCXX_FUZZING_FUZZ_H
+#define TEST_LIBCXX_FUZZING_FUZZ_H
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring> // std::strlen
+#include <type_traits>
+#include <utility> // std::swap
+
+
+// This is a struct we can use to test the stable_XXX algorithms.
+// Perform the operation on the key, then check the order of the payload.
+struct ByteWithPayload {
+  std::uint8_t key;
+  std::size_t payload;
+
+  ByteWithPayload(std::uint8_t k) : key(k), payload(0) { }
+  ByteWithPayload(std::uint8_t k, std::size_t p) : key(k), payload(p) { }
+
+  friend bool operator==(ByteWithPayload const& x, ByteWithPayload const& y) {
+    return x.key == y.key && x.payload == y.payload;
+  }
+
+  friend bool operator!=(ByteWithPayload const& x, ByteWithPayload const& y) {
+    return !(x == y);
+  }
+
+  struct key_less {
+    bool operator()(ByteWithPayload const& x, ByteWithPayload const& y) const
+    { return x.key < y.key; }
+  };
+
+  struct payload_less {
+    bool operator()(ByteWithPayload const& x, ByteWithPayload const& y) const
+    { return x.payload < y.payload; }
+  };
+
+  struct total_less {
+    bool operator()(ByteWithPayload const& x, ByteWithPayload const& y) const {
+      return x.key == y.key ? x.payload < y.payload : x.key < y.key;
+    }
+  };
+
+  friend void swap(ByteWithPayload& lhs, ByteWithPayload& rhs) {
+      std::swap(lhs.key, rhs.key);
+      std::swap(lhs.payload, rhs.payload);
+  }
+};
+
+// Faster version of std::is_permutation
+//
+// Builds a set of buckets for each of the key values, and sums all the payloads.
+// Not 100% perfect, but _way_ faster.
+template <typename Iter1, typename Iter2, typename = typename std::enable_if<
+  std::is_same<typename std::iterator_traits<Iter1>::value_type, ByteWithPayload>::value &&
+  std::is_same<typename std::iterator_traits<Iter2>::value_type, ByteWithPayload>::value
+>::type>
+bool fast_is_permutation(Iter1 first1, Iter1 last1, Iter2 first2) {
+  std::size_t xBuckets[256]  = {0};
+  std::size_t xPayloads[256] = {0};
+  std::size_t yBuckets[256]  = {0};
+  std::size_t yPayloads[256] = {0};
+
+  for (; first1 != last1; ++first1, ++first2) {
+    xBuckets[first1->key]++;
+    xPayloads[first1->key] += first1->payload;
+
+    yBuckets[first2->key]++;
+    yPayloads[first2->key] += first2->payload;
+  }
+
+  for (std::size_t i = 0; i < 256; ++i) {
+    if (xBuckets[i] != yBuckets[i])
+      return false;
+    if (xPayloads[i] != yPayloads[i])
+      return false;
+  }
+
+  return true;
+}
+
+template <typename Iter1, typename Iter2, typename = void, typename = typename std::enable_if<
+  std::is_same<typename std::iterator_traits<Iter1>::value_type, std::uint8_t>::value &&
+  std::is_same<typename std::iterator_traits<Iter2>::value_type, std::uint8_t>::value
+>::type>
+bool fast_is_permutation(Iter1 first1, Iter1 last1, Iter2 first2) {
+  std::size_t xBuckets[256] = {0};
+  std::size_t yBuckets[256] = {0};
+
+  for (; first1 != last1; ++first1, ++first2) {
+    xBuckets[*first1]++;
+    yBuckets[*first2]++;
+  }
+
+  for (std::size_t i = 0; i < 256; ++i)
+    if (xBuckets[i] != yBuckets[i])
+      return false;
+
+  return true;
+}
+
+// When running inside OSS-Fuzz, we link against a fuzzing library that defines
+// main() and calls LLVMFuzzerTestOneInput.
+//
+// Otherwise, when e.g. running the Lit tests, we define main() to run fuzzing
+// tests on a few inputs.
+#if !defined(LIBCPP_OSS_FUZZ)
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t*, std::size_t);
+
+int main(int, char**) {
+  const char* test_cases[] = {
+    "",
+    "s",
+    "bac",
+    "bacasf",
+    "lkajseravea",
+    "adsfkajdsfjkas;lnc441324513,34535r34525234",
+    "b*c",
+    "ba?sf",
+    "lka*ea",
+    "adsf*kas;lnc441[0-9]1r34525234"
+  };
+
+  for (const char* tc : test_cases) {
+    const std::size_t size = std::strlen(tc);
+    const std::uint8_t* data = reinterpret_cast<const std::uint8_t*>(tc);
+    int result = LLVMFuzzerTestOneInput(data, size);
+    assert(result == 0);
+  }
+
+  return 0;
+}
+#endif // !LIBCPP_OSS_FUZZ
+
+#endif // TEST_LIBCXX_FUZZING_FUZZ_H

diff  --git a/libcxx/test/libcxx/fuzzing/fuzzer_test.h b/libcxx/test/libcxx/fuzzing/fuzzer_test.h
deleted file mode 100644
index 1fafd2385a5c..000000000000
--- a/libcxx/test/libcxx/fuzzing/fuzzer_test.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef TEST_LIBCXX_FUZZER_TEST_H
-#define TEST_LIBCXX_FUZZER_TEST_H
-
-#include <cstddef>
-#include <cassert>
-
-#include "../../../fuzzing/fuzzing.h"
-#include "../../../fuzzing/fuzzing.cpp"
-
-const char* TestCaseSetOne[] = {"", "s", "bac",
-                            "bacasf",
-                            "lkajseravea",
-                            "adsfkajdsfjkas;lnc441324513,34535r34525234",
-                            "b*c",
-                            "ba?sf",
-                            "lka*ea",
-                            "adsf*kas;lnc441[0-9]1r34525234"};
-
-using FuzzerFuncType = int(const uint8_t*, size_t);
-
-template <size_t NumCases>
-inline void RunFuzzingTest(FuzzerFuncType *to_test, const char* (&test_cases)[NumCases]) {
-  for (const char* TC : test_cases) {
-    const size_t size = std::strlen(TC);
-    const uint8_t* data = (const uint8_t*)TC;
-    int result = to_test(data, size);
-    assert(result == 0);
-  }
-}
-
-#define FUZZER_TEST(FuncName) \
-int main() { \
-  RunFuzzingTest(FuncName, TestCaseSetOne); \
-} \
-extern int require_semi
-
-#endif // TEST_LIBCXX_FUZZER_TEST_H

diff  --git a/libcxx/test/libcxx/fuzzing/geometric_distribution.pass.cpp b/libcxx/test/libcxx/fuzzing/geometric_distribution.pass.cpp
deleted file mode 100644
index 5a5839a11a55..000000000000
--- a/libcxx/test/libcxx/fuzzing/geometric_distribution.pass.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-// -*- C++ -*-
-//===------------------------ unique_copy.cpp -----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03
-
-#include <random>
-#include <cstdint>
-
-#include "fuzzer_test.h"
-
-template <class Distribution>
-int random_distribution_helper(const uint8_t *data, size_t size) {
-  std::mt19937 engine;
-  using ParamT = typename Distribution::param_type;
-  if (size < sizeof(double))
-    return 0;
-  double Arg;
-  memcpy(&Arg, data, sizeof(double));
-  ParamT p(Arg);
-  Distribution d(p);
-  for (int I=0; I < 1000; ++I) {
-    volatile auto res = d(engine);
-    ((void)res);
-  }
-  return 0;
-}
-
-int FuzzRandom(const uint8_t *Data, size_t Size) {
-  return random_distribution_helper<std::geometric_distribution<std::int16_t>>(Data, Size);
-}
-FUZZER_TEST(FuzzRandom);
-
-

diff  --git a/libcxx/test/libcxx/fuzzing/make_heap.pass.cpp b/libcxx/test/libcxx/fuzzing/make_heap.pass.cpp
new file mode 100644
index 000000000000..ede82c288b06
--- /dev/null
+++ b/libcxx/test/libcxx/fuzzing/make_heap.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+#include "fuzz.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+    std::vector<std::uint8_t> working(data, data + size);
+    std::make_heap(working.begin(), working.end());
+
+    if (!std::is_heap(working.begin(), working.end()))
+        return 1;
+    if (!fast_is_permutation(data, data + size, working.cbegin()))
+        return 99;
+    return 0;
+}

diff  --git a/libcxx/test/libcxx/fuzzing/nth_element.pass.cpp b/libcxx/test/libcxx/fuzzing/nth_element.pass.cpp
index e3ad5bbf8d2b..5e491e76dfa2 100644
--- a/libcxx/test/libcxx/fuzzing/nth_element.pass.cpp
+++ b/libcxx/test/libcxx/fuzzing/nth_element.pass.cpp
@@ -1,5 +1,4 @@
-// -*- C++ -*-
-//===----------------------- nth_element.cpp ------------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,7 +6,37 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03
+// UNSUPPORTED: c++03, c++11
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+#include "fuzz.h"
+
+// Use the first element as a position into the data
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+    if (size <= 1) return 0;
+    const size_t partition_point = data[0] % size;
+    std::vector<std::uint8_t> working(data + 1, data + size);
+    const auto partition_iter = working.begin() + partition_point;
+    std::nth_element(working.begin(), partition_iter, working.end());
+
+    // nth may be the end iterator, in this case nth_element has no effect.
+    if (partition_iter == working.end()) {
+        if (!std::equal(data + 1, data + size, working.begin()))
+            return 98;
+    }
+    else {
+        const std::uint8_t nth = *partition_iter;
+        if (!std::all_of(working.begin(), partition_iter, [=](std::uint8_t v) { return v <= nth; }))
+            return 1;
+        if (!std::all_of(partition_iter, working.end(),   [=](std::uint8_t v) { return v >= nth; }))
+            return 2;
+        if (!fast_is_permutation(data + 1, data + size, working.cbegin()))
+            return 99;
+    }
 
-#include "fuzzer_test.h"
-FUZZER_TEST(fuzzing::nth_element);
+    return 0;
+}

diff  --git a/libcxx/test/libcxx/fuzzing/partial_sort.pass.cpp b/libcxx/test/libcxx/fuzzing/partial_sort.pass.cpp
index 3f6fef1de90d..c179846b6ff6 100644
--- a/libcxx/test/libcxx/fuzzing/partial_sort.pass.cpp
+++ b/libcxx/test/libcxx/fuzzing/partial_sort.pass.cpp
@@ -1,5 +1,4 @@
-// -*- C++ -*-
-//===-------------------------- partial_sort.cpp --------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,26 +6,35 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03
+// UNSUPPORTED: c++03, c++11
 
-#include <cassert>
-#include <cstring> // for strlen
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <vector>
 
-#include "../../../fuzzing/fuzzing.h"
-#include "../../../fuzzing/fuzzing.cpp"
+#include "fuzz.h"
 
-const char* test_cases[] = {"", "s", "bac",
-                            "bacasf",
-                            "lkajseravea",
-                            "adsfkajdsfjkas;lnc441324513,34535r34525234"};
+// Use the first element as a position into the data
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+    if (size <= 1)
+        return 0;
+    const std::size_t sort_point = data[0] % size;
+    std::vector<std::uint8_t> working(data + 1, data + size);
+    const auto sort_iter = working.begin() + sort_point;
+    std::partial_sort(working.begin(), sort_iter, working.end());
 
-const size_t k_num_tests = sizeof(test_cases) / sizeof(test_cases[0]);
+    if (sort_iter != working.end()) {
+        const std::uint8_t nth = *std::min_element(sort_iter, working.end());
+        if (!std::all_of(working.begin(), sort_iter, [=](std::uint8_t v) { return v <= nth; }))
+            return 1;
+        if (!std::all_of(sort_iter, working.end(),   [=](std::uint8_t v) { return v >= nth; }))
+            return 2;
+    }
+    if (!std::is_sorted(working.begin(), sort_iter))
+        return 3;
+    if (!fast_is_permutation(data + 1, data + size, working.cbegin()))
+        return 99;
 
-int main(int, char**) {
-  for (size_t i = 0; i < k_num_tests; ++i) {
-    const size_t size = std::strlen(test_cases[i]);
-    const uint8_t* data = (const uint8_t*)test_cases[i];
-    assert(0 == fuzzing::partial_sort(data, size));
-  }
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/libcxx/fuzzing/partial_sort_copy.pass.cpp b/libcxx/test/libcxx/fuzzing/partial_sort_copy.pass.cpp
index b5d47c55b0db..530ab0d162c4 100644
--- a/libcxx/test/libcxx/fuzzing/partial_sort_copy.pass.cpp
+++ b/libcxx/test/libcxx/fuzzing/partial_sort_copy.pass.cpp
@@ -1,5 +1,4 @@
-// -*- C++ -*-
-//===----------------------- partial_sort_copy.cpp ------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,7 +6,36 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03
+// UNSUPPORTED: c++03, c++11
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+#include "fuzz.h"
+
+// Use the first element as a count
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+    if (size <= 1)
+        return 0;
+    const std::size_t num_results = data[0] % size;
+    std::vector<std::uint8_t> results(num_results);
+    (void)std::partial_sort_copy(data + 1, data + size, results.begin(), results.end());
+
+    // The results have to be sorted
+    if (!std::is_sorted(results.begin(), results.end()))
+        return 1;
+    // All the values in results have to be in the original data
+    for (auto v: results)
+        if (std::find(data + 1, data + size, v) == data + size)
+            return 2;
+
+    // The things in results have to be the smallest N in the original data
+    std::vector<std::uint8_t> sorted(data + 1, data + size);
+    std::sort(sorted.begin(), sorted.end());
+    if (!std::equal(results.begin(), results.end(), sorted.begin()))
+        return 3;
 
-#include "fuzzer_test.h"
-FUZZER_TEST(fuzzing::partial_sort_copy);
+    return 0;
+}

diff  --git a/libcxx/test/libcxx/fuzzing/partition.pass.cpp b/libcxx/test/libcxx/fuzzing/partition.pass.cpp
index dda506d82121..203e45bb8bdd 100644
--- a/libcxx/test/libcxx/fuzzing/partition.pass.cpp
+++ b/libcxx/test/libcxx/fuzzing/partition.pass.cpp
@@ -1,5 +1,4 @@
-// -*- C++ -*-
-//===--------------------------- partition.cpp ----------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,7 +6,25 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03
+// UNSUPPORTED: c++03, c++11
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+#include "fuzz.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+    auto is_even = [](auto x) { return x % 2 == 0; };
+    std::vector<std::uint8_t> working(data, data + size);
+    auto iter = std::partition(working.begin(), working.end(), is_even);
 
-#include "fuzzer_test.h"
-FUZZER_TEST(fuzzing::partition);
+    if (!std::all_of(working.begin(), iter, is_even))
+        return 1;
+    if (!std::none_of(iter,   working.end(), is_even))
+        return 2;
+    if (!fast_is_permutation(data, data + size, working.cbegin()))
+        return 99;
+    return 0;
+}

diff  --git a/libcxx/test/libcxx/fuzzing/partition_copy.pass.cpp b/libcxx/test/libcxx/fuzzing/partition_copy.pass.cpp
index 383b4cfc5c5d..ac37c2ef2427 100644
--- a/libcxx/test/libcxx/fuzzing/partition_copy.pass.cpp
+++ b/libcxx/test/libcxx/fuzzing/partition_copy.pass.cpp
@@ -1,5 +1,4 @@
-// -*- C++ -*-
-//===------------------------ partition_copy.cpp --------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,7 +6,60 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03
+// UNSUPPORTED: c++03, c++11
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <vector>
+
+#include "fuzz.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+    auto is_even = [](auto t) {
+        return t % 2 == 0;
+    };
+
+    std::vector<std::uint8_t> v1, v2;
+    auto iter = std::partition_copy(data, data + size,
+        std::back_inserter<std::vector<std::uint8_t>>(v1),
+        std::back_inserter<std::vector<std::uint8_t>>(v2),
+        is_even);
+    ((void)iter);
+    // The two vectors should add up to the original size
+    if (v1.size() + v2.size() != size)
+        return 1;
+
+    // All of the even values should be in the first vector, and none in the second
+    if (!std::all_of(v1.begin(), v1.end(), is_even))
+        return 2;
+    if (!std::none_of(v2.begin(), v2.end(), is_even))
+        return 3;
+
+    // Every value in both vectors has to be in the original
+
+    // Make a copy of the input, and sort it
+    std::vector<std::uint8_t> v0{data, data + size};
+    std::sort(v0.begin(), v0.end());
+
+    // Sort each vector and ensure that all of the elements appear in the original input
+    std::sort(v1.begin(), v1.end());
+    if (!std::includes(v0.begin(), v0.end(), v1.begin(), v1.end()))
+        return 4;
+
+    std::sort(v2.begin(), v2.end());
+    if (!std::includes(v0.begin(), v0.end(), v2.begin(), v2.end()))
+        return 5;
+
+    // This, while simple, is really slow - 20 seconds on a 500K element input.
+    //  for (auto v: v1)
+    //      if (std::find(data, data + size, v) == data + size)
+    //          return 4;
+    //
+    //  for (auto v: v2)
+    //      if (std::find(data, data + size, v) == data + size)
+    //          return 5;
 
-#include "fuzzer_test.h"
-FUZZER_TEST(fuzzing::partition_copy);
+    return 0;
+}

diff  --git a/libcxx/test/libcxx/fuzzing/pop_heap.pass.cpp b/libcxx/test/libcxx/fuzzing/pop_heap.pass.cpp
new file mode 100644
index 000000000000..e54eedec3644
--- /dev/null
+++ b/libcxx/test/libcxx/fuzzing/pop_heap.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+#include "fuzz.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+    if (size < 2)
+        return 0;
+    std::vector<std::uint8_t> working(data, data + size);
+    std::make_heap(working.begin(), working.end());
+
+    // Pop things off, one at a time
+    auto iter = --working.end();
+    while (iter != working.begin()) {
+        std::pop_heap(working.begin(), iter);
+        if (!std::is_heap(working.begin(), --iter))
+            return 2;
+    }
+
+    return 0;
+}

diff  --git a/libcxx/test/libcxx/fuzzing/push_heap.pass.cpp b/libcxx/test/libcxx/fuzzing/push_heap.pass.cpp
new file mode 100644
index 000000000000..ce6717603975
--- /dev/null
+++ b/libcxx/test/libcxx/fuzzing/push_heap.pass.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+#include "fuzz.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+    if (size < 2)
+        return 0;
+
+    // Make a heap from the first half of the data
+    std::vector<std::uint8_t> working(data, data + size);
+    auto iter = working.begin() + (size / 2);
+    std::make_heap(working.begin(), iter);
+    if (!std::is_heap(working.begin(), iter))
+        return 1;
+
+    // Now push the rest onto the heap, one at a time
+    ++iter;
+    for (; iter != working.end(); ++iter) {
+        std::push_heap(working.begin(), iter);
+        if (!std::is_heap(working.begin(), iter))
+            return 2;
+    }
+
+    if (!fast_is_permutation(data, data + size, working.cbegin()))
+        return 99;
+    return 0;
+}

diff  --git a/libcxx/test/libcxx/fuzzing/random.pass.cpp b/libcxx/test/libcxx/fuzzing/random.pass.cpp
new file mode 100644
index 000000000000..e7545ffdf4da
--- /dev/null
+++ b/libcxx/test/libcxx/fuzzing/random.pass.cpp
@@ -0,0 +1,194 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11
+
+#include <cassert>
+#include <cmath>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <random>
+#include <type_traits>
+#include <vector>
+
+#include "fuzz.h"
+
+template <class IntT>
+std::vector<IntT> GetValues(const std::uint8_t *data, std::size_t size) {
+  std::vector<IntT> result;
+  while (size >= sizeof(IntT)) {
+    IntT tmp;
+    std::memcpy(&tmp, data, sizeof(IntT));
+    size -= sizeof(IntT);
+    data += sizeof(IntT);
+    result.push_back(tmp);
+  }
+  return result;
+}
+
+template <class Dist>
+struct ParamTypeHelper {
+  using ParamT = typename Dist::param_type;
+  using ResultT = typename Dist::result_type;
+  static_assert(std::is_same<ResultT, typename ParamT::distribution_type::result_type>::value, "");
+
+  static ParamT Create(const uint8_t* data, std::size_t size, bool &OK) {
+    constexpr bool select_vector_result = std::is_constructible<ParamT, ResultT*, ResultT*, ResultT*>::value;
+    constexpr bool select_vector_double = std::is_constructible<ParamT, double*, double*>::value;
+    constexpr int selector = select_vector_result ? 0 : (select_vector_double ? 1 : 2);
+    return DispatchAndCreate(std::integral_constant<int, selector>{}, data, size, OK);
+  }
+
+  // Vector result
+  static ParamT DispatchAndCreate(std::integral_constant<int, 0>, const std::uint8_t *data, std::size_t size, bool &OK) {
+    auto Input = GetValues<ResultT>(data, size);
+    OK = false;
+    if (Input.size() < 10)
+      return ParamT{};
+    OK = true;
+    auto Beg = Input.begin();
+    auto End = Input.end();
+    auto Mid = Beg + ((End - Beg) / 2);
+
+    assert(Mid - Beg <= (End  -  Mid));
+    ParamT p(Beg, Mid, Mid);
+    return p;
+  }
+
+  // Vector double
+  static ParamT DispatchAndCreate(std::integral_constant<int, 1>, const std::uint8_t *data, std::size_t size, bool &OK) {
+    auto Input = GetValues<double>(data, size);
+
+    OK = true;
+    auto Beg = Input.begin();
+    auto End = Input.end();
+
+    ParamT p(Beg, End);
+    return p;
+  }
+
+  // Default
+  static ParamT DispatchAndCreate(std::integral_constant<int, 2>, const std::uint8_t *data, std::size_t size, bool &OK) {
+    OK = false;
+    if (size < sizeof(ParamT))
+      return ParamT{};
+    OK = true;
+    ParamT input;
+    std::memcpy(&input, data, sizeof(ParamT));
+    return input;
+  }
+};
+
+template <class IntT>
+struct ParamTypeHelper<std::poisson_distribution<IntT>> {
+  using Dist = std::poisson_distribution<IntT>;
+  using ParamT = typename Dist::param_type;
+  using ResultT = typename Dist::result_type;
+
+  static ParamT Create(const std::uint8_t *data, std::size_t size, bool& OK) {
+    OK = false;
+    auto vals = GetValues<double>(data, size);
+    if (vals.empty() || std::isnan(vals[0]) || std::isnan(std::abs(vals[0])) || vals[0] < 0)
+      return ParamT{};
+    OK = true;
+    return ParamT{vals[0]};
+  }
+};
+
+template <class IntT>
+struct ParamTypeHelper<std::geometric_distribution<IntT>> {
+  using Dist = std::geometric_distribution<IntT>;
+  using ParamT = typename Dist::param_type;
+  using ResultT = typename Dist::result_type;
+
+  static ParamT Create(const std::uint8_t *data, std::size_t size, bool& OK) {
+    OK = false;
+    auto vals = GetValues<double>(data, size);
+    if (vals.empty() || std::isnan(vals[0]) || vals[0] < 0 )
+      return ParamT{};
+    OK = true;
+    return ParamT{vals[0]};
+  }
+};
+
+template <class IntT>
+struct ParamTypeHelper<std::lognormal_distribution<IntT>> {
+  using Dist = std::lognormal_distribution<IntT>;
+  using ParamT = typename Dist::param_type;
+  using ResultT = typename Dist::result_type;
+
+  static ParamT Create(const std::uint8_t *data, std::size_t size, bool& OK) {
+    OK = false;
+    auto vals = GetValues<ResultT>(data, size);
+    if (vals.size() < 2 )
+      return ParamT{};
+    OK = true;
+    return ParamT{vals[0], vals[1]};
+  }
+};
+
+template <>
+struct ParamTypeHelper<std::bernoulli_distribution> {
+  using Dist = std::bernoulli_distribution;
+  using ParamT = Dist::param_type;
+  using ResultT = Dist::result_type;
+
+  static ParamT Create(const std::uint8_t *data, std::size_t size, bool& OK) {
+    OK = false;
+    auto vals = GetValues<double>(data, size);
+    if (vals.empty())
+      return ParamT{};
+    OK = true;
+    return ParamT{vals[0]};
+  }
+};
+
+template <class Distribution>
+int helper(const std::uint8_t *data, std::size_t size) {
+  std::mt19937 engine;
+  using ParamT = typename Distribution::param_type;
+  bool OK;
+  ParamT p = ParamTypeHelper<Distribution>::Create(data, size, OK);
+  if (!OK)
+    return 0;
+  Distribution d(p);
+  volatile auto res = d(engine);
+  if (std::isnan(res)) {
+    // FIXME(llvm.org/PR44289):
+    // Investigate why these distributions are returning NaN and decide
+    // if that's what we want them to be doing.
+    //
+    // Make this assert false (or return non-zero).
+    return 0;
+  }
+  return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+  return helper<std::uniform_int_distribution<std::int16_t>>(data, size)       ||
+         helper<std::uniform_real_distribution<float>>(data, size)             ||
+         helper<std::bernoulli_distribution>(data, size)                       ||
+         helper<std::poisson_distribution<std::int16_t>>(data, size)           ||
+         helper<std::geometric_distribution<std::int16_t>>(data, size)         ||
+         helper<std::binomial_distribution<std::int16_t>>(data, size)          ||
+         helper<std::negative_binomial_distribution<std::int16_t>>(data, size) ||
+         helper<std::exponential_distribution<float>>(data, size)              ||
+         helper<std::gamma_distribution<float>>(data, size)                    ||
+         helper<std::weibull_distribution<float>>(data, size)                  ||
+         helper<std::extreme_value_distribution<float>>(data, size)            ||
+         helper<std::normal_distribution<float>>(data, size)                   ||
+         helper<std::lognormal_distribution<float>>(data, size)                ||
+         helper<std::chi_squared_distribution<float>>(data, size)              ||
+         helper<std::cauchy_distribution<float>>(data, size)                   ||
+         helper<std::fisher_f_distribution<float>>(data, size)                 ||
+         helper<std::student_t_distribution<float>>(data, size)                ||
+         helper<std::discrete_distribution<std::int16_t>>(data, size)          ||
+         helper<std::piecewise_constant_distribution<float>>(data, size)       ||
+         helper<std::piecewise_linear_distribution<float>>(data, size);
+}

diff  --git a/libcxx/test/libcxx/fuzzing/regex.pass.cpp b/libcxx/test/libcxx/fuzzing/regex.pass.cpp
new file mode 100644
index 000000000000..b027dd0a0fa4
--- /dev/null
+++ b/libcxx/test/libcxx/fuzzing/regex.pass.cpp
@@ -0,0 +1,45 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11
+// UNSUPPORTED: no-exceptions
+
+#include <cstddef>
+#include <cstdint>
+#include <regex>
+#include <string>
+
+#include "fuzz.h"
+
+template <std::regex_constants::syntax_option_type Syntax>
+static int regex_test(const std::uint8_t *data, std::size_t size) {
+    if (size == 0)
+        return 0;
+
+    std::string s((const char *)data, size);
+    std::regex re;
+    try {
+        re.assign(s, Syntax);
+    } catch (std::regex_error &) {
+        // the data represents an invalid regex, ignore this test case
+        return 0;
+    }
+
+    auto match = std::regex_match(s, re);
+    (void)match;
+    return 0; // always pretend we succeeded -- we're only looking for crashes
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+    return regex_test<std::regex_constants::awk>(data, size)        ||
+           regex_test<std::regex_constants::basic>(data, size)      ||
+           regex_test<std::regex_constants::ECMAScript>(data, size) ||
+           regex_test<std::regex_constants::egrep>(data, size)      ||
+           regex_test<std::regex_constants::extended>(data, size)   ||
+           regex_test<std::regex_constants::grep>(data, size);
+}

diff  --git a/libcxx/test/libcxx/fuzzing/regex_ECMAScript.pass.cpp b/libcxx/test/libcxx/fuzzing/regex_ECMAScript.pass.cpp
deleted file mode 100644
index 79454948b4b5..000000000000
--- a/libcxx/test/libcxx/fuzzing/regex_ECMAScript.pass.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// -*- C++ -*-
-//===--------------------- regex_ECMAScript.cpp ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03
-
-#include "fuzzer_test.h"
-FUZZER_TEST(fuzzing::regex_ECMAScript);

diff  --git a/libcxx/test/libcxx/fuzzing/regex_POSIX.pass.cpp b/libcxx/test/libcxx/fuzzing/regex_POSIX.pass.cpp
deleted file mode 100644
index af94fb7afa65..000000000000
--- a/libcxx/test/libcxx/fuzzing/regex_POSIX.pass.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// -*- C++ -*-
-//===----------------------- regex_POSIX.cpp ------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03
-
-#include "fuzzer_test.h"
-FUZZER_TEST(fuzzing::regex_POSIX);

diff  --git a/libcxx/test/libcxx/fuzzing/regex_awk.pass.cpp b/libcxx/test/libcxx/fuzzing/regex_awk.pass.cpp
deleted file mode 100644
index 8040d8b69182..000000000000
--- a/libcxx/test/libcxx/fuzzing/regex_awk.pass.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// -*- C++ -*-
-//===------------------------- regex_awk.cpp ------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03
-
-#include "fuzzer_test.h"
-FUZZER_TEST(fuzzing::regex_awk);

diff  --git a/libcxx/test/libcxx/fuzzing/regex_egrep.pass.cpp b/libcxx/test/libcxx/fuzzing/regex_egrep.pass.cpp
deleted file mode 100644
index 1c7076b55651..000000000000
--- a/libcxx/test/libcxx/fuzzing/regex_egrep.pass.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// -*- C++ -*-
-//===------------------------ regex_egrep.cpp -----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03
-
-#include "fuzzer_test.h"
-FUZZER_TEST(fuzzing::regex_egrep);

diff  --git a/libcxx/test/libcxx/fuzzing/regex_extended.pass.cpp b/libcxx/test/libcxx/fuzzing/regex_extended.pass.cpp
deleted file mode 100644
index d981c8bd4a33..000000000000
--- a/libcxx/test/libcxx/fuzzing/regex_extended.pass.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// -*- C++ -*-
-//===---------------------- regex_extended.cpp ----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03
-
-#include "fuzzer_test.h"
-FUZZER_TEST(fuzzing::regex_extended);

diff  --git a/libcxx/test/libcxx/fuzzing/regex_grep.pass.cpp b/libcxx/test/libcxx/fuzzing/regex_grep.pass.cpp
deleted file mode 100644
index 4c0ecebf2044..000000000000
--- a/libcxx/test/libcxx/fuzzing/regex_grep.pass.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// -*- C++ -*-
-//===------------------------ regex_grep.cpp ------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03
-
-#include "fuzzer_test.h"
-FUZZER_TEST(fuzzing::regex_grep);

diff  --git a/libcxx/test/libcxx/fuzzing/search.pass.cpp b/libcxx/test/libcxx/fuzzing/search.pass.cpp
new file mode 100644
index 000000000000..e20fad2ea7e9
--- /dev/null
+++ b/libcxx/test/libcxx/fuzzing/search.pass.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+
+#include "fuzz.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+    if (size < 2)
+        return 0;
+
+    const std::size_t pat_size = data[0] * (size - 1) / std::numeric_limits<uint8_t>::max();
+    assert(pat_size <= size - 1);
+    const std::uint8_t *pat_begin = data + 1;
+    const std::uint8_t *pat_end   = pat_begin + pat_size;
+    const std::uint8_t *data_end  = data + size;
+    assert(pat_end <= data_end);
+
+    auto it = std::search(pat_end, data_end, pat_begin, pat_end);
+    if (it != data_end) // not found
+        if (!std::equal(pat_begin, pat_end, it))
+            return 1;
+    return 0;
+}

diff  --git a/libcxx/test/libcxx/fuzzing/sort.pass.cpp b/libcxx/test/libcxx/fuzzing/sort.pass.cpp
index c9fcf652d95b..e11889713a39 100644
--- a/libcxx/test/libcxx/fuzzing/sort.pass.cpp
+++ b/libcxx/test/libcxx/fuzzing/sort.pass.cpp
@@ -1,5 +1,4 @@
-// -*- C++ -*-
-//===--------------------------- sort.cpp ---------------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,7 +6,22 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03
+// UNSUPPORTED: c++03, c++11
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+#include "fuzz.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+    std::vector<std::uint8_t> working(data, data + size);
+    std::sort(working.begin(), working.end());
 
-#include "fuzzer_test.h"
-FUZZER_TEST(fuzzing::sort);
+    if (!std::is_sorted(working.begin(), working.end()))
+        return 1;
+    if (!fast_is_permutation(data, data + size, working.cbegin()))
+        return 99;
+    return 0;
+}

diff  --git a/libcxx/test/libcxx/fuzzing/stable_partition.pass.cpp b/libcxx/test/libcxx/fuzzing/stable_partition.pass.cpp
index d8eb359271b1..2a1799dc3b85 100644
--- a/libcxx/test/libcxx/fuzzing/stable_partition.pass.cpp
+++ b/libcxx/test/libcxx/fuzzing/stable_partition.pass.cpp
@@ -1,5 +1,4 @@
-// -*- C++ -*-
-//===--------------------- stable_partition.cpp ---------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,7 +6,33 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03
+// UNSUPPORTED: c++03, c++11
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+#include "fuzz.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+    auto is_even = [](auto b) { return b.key % 2 == 0; };
+
+    std::vector<ByteWithPayload> input;
+    for (std::size_t i = 0; i < size; ++i)
+        input.push_back(ByteWithPayload(data[i], i));
+    std::vector<ByteWithPayload> working = input;
+    auto iter = std::stable_partition(working.begin(), working.end(), is_even);
 
-#include "fuzzer_test.h"
-FUZZER_TEST(fuzzing::stable_partition);
+    if (!std::all_of(working.begin(), iter, is_even))
+        return 1;
+    if (!std::none_of(iter,   working.end(), is_even))
+        return 2;
+    if (!std::is_sorted(working.begin(), iter, ByteWithPayload::payload_less()))
+        return 3;
+    if (!std::is_sorted(iter,   working.end(), ByteWithPayload::payload_less()))
+        return 4;
+    if (!fast_is_permutation(input.cbegin(), input.cend(), working.cbegin()))
+        return 99;
+    return 0;
+}

diff  --git a/libcxx/test/libcxx/fuzzing/stable_sort.pass.cpp b/libcxx/test/libcxx/fuzzing/stable_sort.pass.cpp
index 666e48bba53e..b493691035d7 100644
--- a/libcxx/test/libcxx/fuzzing/stable_sort.pass.cpp
+++ b/libcxx/test/libcxx/fuzzing/stable_sort.pass.cpp
@@ -1,5 +1,4 @@
-// -*- C++ -*-
-//===------------------------ stable_sort.cpp ----------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,7 +6,34 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03
+// UNSUPPORTED: c++03, c++11
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+#include "fuzz.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+    std::vector<ByteWithPayload> input;
+    for (std::size_t i = 0; i < size; ++i)
+        input.push_back(ByteWithPayload(data[i], i));
+
+    std::vector<ByteWithPayload> working = input;
+    std::stable_sort(working.begin(), working.end(), ByteWithPayload::key_less());
+
+    if (!std::is_sorted(working.begin(), working.end(), ByteWithPayload::key_less()))
+        return 1;
 
-#include "fuzzer_test.h"
-FUZZER_TEST(fuzzing::stable_sort);
+    auto iter = working.begin();
+    while (iter != working.end()) {
+        auto range = std::equal_range(iter, working.end(), *iter, ByteWithPayload::key_less());
+        if (!std::is_sorted(range.first, range.second, ByteWithPayload::total_less()))
+            return 2;
+        iter = range.second;
+    }
+    if (!fast_is_permutation(input.cbegin(), input.cend(), working.cbegin()))
+        return 99;
+    return 0;
+}

diff  --git a/libcxx/test/libcxx/fuzzing/unique.pass.cpp b/libcxx/test/libcxx/fuzzing/unique.pass.cpp
index 6ffbd5ce1075..e95c61711189 100644
--- a/libcxx/test/libcxx/fuzzing/unique.pass.cpp
+++ b/libcxx/test/libcxx/fuzzing/unique.pass.cpp
@@ -1,5 +1,4 @@
-// -*- C++ -*-
-//===--------------------------- unique.cpp -------------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,7 +6,49 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03
+// UNSUPPORTED: c++03, c++11
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+#include "fuzz.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+    std::vector<std::uint8_t> working(data, data + size);
+    std::sort(working.begin(), working.end());
+    std::vector<std::uint8_t> results = working;
+    std::vector<std::uint8_t>::iterator new_end = std::unique(results.begin(), results.end());
+    std::vector<std::uint8_t>::iterator it; // scratch iterator
+
+    // Check the size of the unique'd sequence.
+    // it should only be zero if the input sequence was empty.
+    if (results.begin() == new_end)
+        return working.size() == 0 ? 0 : 1;
+
+    // 'results' is sorted
+    if (!std::is_sorted(results.begin(), new_end))
+        return 2;
+
+    // All the elements in 'results' must be 
diff erent
+    it = results.begin();
+    std::uint8_t prev_value = *it++;
+    for (; it != new_end; ++it) {
+        if (*it == prev_value)
+            return 3;
+        prev_value = *it;
+    }
+
+    // Every element in 'results' must be in 'working'
+    for (it = results.begin(); it != new_end; ++it)
+        if (std::find(working.begin(), working.end(), *it) == working.end())
+            return 4;
+
+    // Every element in 'working' must be in 'results'
+    for (auto v : working)
+        if (std::find(results.begin(), new_end, v) == new_end)
+            return 5;
 
-#include "fuzzer_test.h"
-FUZZER_TEST(fuzzing::unique);
+    return 0;
+}

diff  --git a/libcxx/test/libcxx/fuzzing/unique_copy.pass.cpp b/libcxx/test/libcxx/fuzzing/unique_copy.pass.cpp
index 47a4f951cbe9..dfaaa19932f8 100644
--- a/libcxx/test/libcxx/fuzzing/unique_copy.pass.cpp
+++ b/libcxx/test/libcxx/fuzzing/unique_copy.pass.cpp
@@ -1,5 +1,4 @@
-// -*- C++ -*-
-//===------------------------ unique_copy.cpp -----------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,7 +6,51 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03
+// UNSUPPORTED: c++03, c++11
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <vector>
+
+#include "fuzz.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) {
+    std::vector<std::uint8_t> working(data, data + size);
+    std::sort(working.begin(), working.end());
+    std::vector<std::uint8_t> results;
+    (void)std::unique_copy(working.begin(), working.end(),
+                           std::back_inserter<std::vector<std::uint8_t>>(results));
+    std::vector<std::uint8_t>::iterator it; // scratch iterator
+
+    // Check the size of the unique'd sequence.
+    // it should only be zero if the input sequence was empty.
+    if (results.size() == 0)
+        return working.size() == 0 ? 0 : 1;
+
+    // 'results' is sorted
+    if (!std::is_sorted(results.begin(), results.end()))
+        return 2;
+
+    // All the elements in 'results' must be 
diff erent
+    it = results.begin();
+    std::uint8_t prev_value = *it++;
+    for (; it != results.end(); ++it) {
+        if (*it == prev_value)
+            return 3;
+        prev_value = *it;
+    }
+
+    // Every element in 'results' must be in 'working'
+    for (auto v : results)
+        if (std::find(working.begin(), working.end(), v) == working.end())
+            return 4;
+
+    // Every element in 'working' must be in 'results'
+    for (auto v : working)
+        if (std::find(results.begin(), results.end(), v) == results.end())
+            return 5;
 
-#include "fuzzer_test.h"
-FUZZER_TEST(fuzzing::unique_copy);
+    return 0;
+}

diff  --git a/libcxx/utils/ci/oss-fuzz.sh b/libcxx/utils/ci/oss-fuzz.sh
index eac1a27c9465..8a9421a3ea2d 100755
--- a/libcxx/utils/ci/oss-fuzz.sh
+++ b/libcxx/utils/ci/oss-fuzz.sh
@@ -4,20 +4,16 @@
 # This script runs the continuous fuzzing tests on OSS-Fuzz.
 #
 
-if [[ $SANITIZER = *undefined* ]]; then
-  CXXFLAGS="$CXXFLAGS -fsanitize=unsigned-integer-overflow -fsanitize-trap=unsigned-integer-overflow"
+if [[ ${SANITIZER} = *undefined* ]]; then
+  CXXFLAGS="${CXXFLAGS} -fsanitize=unsigned-integer-overflow -fsanitize-trap=unsigned-integer-overflow"
 fi
 
-for f in $(grep -v "#" libcxx/fuzzing/RoutineNames.txt); do
-  cat > ${f}_fuzzer.cc <<EOF
-#include "fuzzing/fuzzing.h"
-#include <cassert>
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  int result = fuzzing::$f(data, size);
-  assert(result == 0); return 0;
-}
-EOF
-  $CXX $CXXFLAGS -std=c++11 ${f}_fuzzer.cc ./libcxx/fuzzing/fuzzing.cpp \
-      -nostdinc++ -cxx-isystem ./libcxx/include -iquote ./libcxx \
-      -o $OUT/$f $LIB_FUZZING_ENGINE
+for test in libcxx/test/libcxx/fuzzing/*.pass.cpp; do
+    ${CXX} ${CXXFLAGS} \
+        -std=c++14 \
+        -DLIBCPP_OSS_FUZZ \
+        -nostdinc++ -cxx-isystem libcxx/include \
+        -o "${OUT}/$(basename ${test})" \
+        ${test} \
+        ${LIB_FUZZING_ENGINE}
 done


        


More information about the libcxx-commits mailing list