Skip to content

Commit

Permalink
Use the desired Mutate() in the LLVM fuzzer wrapper domain.
Browse files Browse the repository at this point in the history
Otherwise `ContainerOfImplBase::Mutate()` will be used instead of `ArbitraryByteVector::Mutate()`, which handles the custom mutator logic.

PiperOrigin-RevId: 702066945
  • Loading branch information
xinhaoyuan authored and copybara-github committed Dec 9, 2024
1 parent 117570f commit 1d08a71
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 67 deletions.
42 changes: 26 additions & 16 deletions fuzztest/internal/domains/container_of_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,11 @@ using ContainerOfImplBaseCorpusType = std::conditional_t<
std::list<corpus_type_t<InnerDomain>>, ValueType>;

// Common base for container domains. Provides common APIs.
template <typename Derived>
class ContainerOfImplBase : public domain_implementor::DomainBase<
Derived, ExtractTemplateParameter<0, Derived>,
ContainerOfImplBaseCorpusType<Derived>> {
using InnerDomainT = ExtractTemplateParameter<1, Derived>;

template <typename Derived, typename T = ExtractTemplateParameter<0, Derived>,
typename InnerDomainT = ExtractTemplateParameter<1, Derived>>
class ContainerOfImplBase
: public domain_implementor::DomainBase<
Derived, T, ContainerOfImplBaseCorpusType<Derived, T, InnerDomainT>> {
public:
using ContainerOfImplBase::DomainBase::has_custom_corpus_type;
using typename ContainerOfImplBase::DomainBase::corpus_type;
Expand Down Expand Up @@ -124,7 +123,6 @@ class ContainerOfImplBase : public domain_implementor::DomainBase<
const bool can_use_memory_dict = !only_shrink &&
container_has_memory_dict && can_change &&
metadata.cmp_tables != nullptr;

const int action_count =
can_shrink + can_grow + can_change + can_use_memory_dict;
if (action_count == 0) return;
Expand Down Expand Up @@ -341,11 +339,13 @@ class ContainerOfImplBase : public domain_implementor::DomainBase<

InnerDomainT Inner() const { return inner_; }

template <typename>
// Needed for `CopyConstraintsFrom`.
template <typename, typename, typename>
friend class ContainerOfImplBase;

template <typename OtherDerived>
void CopyConstraintsFrom(const ContainerOfImplBase<OtherDerived>& other) {
template <typename OtherDerived, typename OtherT, typename OtherInnerDomain>
void CopyConstraintsFrom(const ContainerOfImplBase<OtherDerived, OtherT,
OtherInnerDomain>& other) {
min_size_ = other.min_size_;
max_size_ = other.max_size_;
}
Expand Down Expand Up @@ -524,16 +524,17 @@ Please verify that the inner domain can provide enough values.
}
};

template <typename T, typename InnerDomain>
class SequenceContainerOfImpl
: public ContainerOfImplBase<SequenceContainerOfImpl<T, InnerDomain>> {
using Base = typename SequenceContainerOfImpl::ContainerOfImplBase;
template <typename Derived, typename T = ExtractTemplateParameter<0, Derived>,
typename InnerDomain = ExtractTemplateParameter<1, Derived>>
class SequenceContainerOfImplBase
: public ContainerOfImplBase<Derived, T, InnerDomain> {
using Base = typename SequenceContainerOfImplBase::ContainerOfImplBase;

public:
using typename Base::corpus_type;

SequenceContainerOfImpl() = default;
explicit SequenceContainerOfImpl(InnerDomain inner)
SequenceContainerOfImplBase() = default;
explicit SequenceContainerOfImplBase(InnerDomain inner)
: Base(std::move(inner)) {}

corpus_type Init(absl::BitGenRef prng) {
Expand Down Expand Up @@ -582,6 +583,15 @@ class SequenceContainerOfImpl
}
};

template <typename T, typename InnerDomain>
class SequenceContainerOfImpl : public SequenceContainerOfImplBase<
SequenceContainerOfImpl<T, InnerDomain>> {
using Base = typename SequenceContainerOfImpl::SequenceContainerOfImplBase;

public:
using Base::Base;
};

template <typename T, typename InnerDomain>
using ContainerOfImpl =
std::conditional_t<is_associative_container_v<T>,
Expand Down
61 changes: 10 additions & 51 deletions fuzztest/llvm_fuzzer_wrapper.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
Expand Down Expand Up @@ -84,52 +85,6 @@ std::vector<std::vector<uint8_t>> ReadByteArrayDictionaryFromFile() {
return out;
}

template <typename T>
class InplaceVector {
public:
using iterator = T*;
using value_type = T;

InplaceVector() : data_(nullptr), size_(0) {}
InplaceVector(T* data, std::size_t size) : data_(data), size_(size) {}

T& operator[](int i) { return data_[i]; }

T const& operator[](int i) const { return data_[i]; }

std::size_t size() const { return size_; }

T* begin() const { return data_; }

T* end() const { return data_ + size_; }

void insert(T* index, T val) {
for (T* itr = data_ + size_; itr > index; --itr) {
*itr = *(itr - 1);
}
*index = val;
++size_;
}

void erase(T* index) {
for (T* itr = index; itr < data_ + size_ - 1; ++itr) {
*itr = *(itr + 1);
}
--size_;
}

void erase(T* begin, T* end) {
for (T *itr = begin, *jtr = end; jtr < data_ + size_; ++itr, ++jtr) {
*itr = *jtr;
}
size_ -= (end - begin);
}

private:
T* data_;
std::size_t size_;
};

namespace {

using ::fuzztest::domain_implementor::MutationMetadata;
Expand Down Expand Up @@ -207,20 +162,24 @@ extern "C" size_t CentipedeLLVMFuzzerMutateCallback(uint8_t* data, size_t size,
extern "C" size_t LLVMFuzzerMutate(uint8_t* data, size_t size,
size_t max_size) {
#endif // FUZZTEST_USE_CENTIPEDE
static auto domain = fuzztest::internal::SequenceContainerOfImpl<
InplaceVector<uint8_t>, fuzztest::internal::ArbitraryImpl<uint8_t>>();
static auto domain = fuzztest::Arbitrary<std::vector<uint8_t>>()
.WithDictionary(ReadByteArrayDictionaryFromFile)
.WithSeeds(ReadByteArraysFromDirectory);
domain.WithMaxSize(max_size);
absl::BitGen bitgen;
InplaceVector<uint8_t> val(data, size);
std::vector<uint8_t> val{data, data + size};
const auto& metadata = mutation_metadata_manager->Acquire();
domain.Mutate(val, bitgen, metadata, false);
mutation_metadata_manager->Release();
// This can be eliminated if Mutate() can operate on the original `data`.
std::copy(val.begin(), val.end(), data);
return val.size();
}

class ArbitraryByteVector
: public fuzztest::internal::SequenceContainerOfImpl<
std::vector<uint8_t>, fuzztest::internal::ArbitraryImpl<uint8_t>> {
: public fuzztest::internal::SequenceContainerOfImplBase<
ArbitraryByteVector, std::vector<uint8_t>,
fuzztest::internal::ArbitraryImpl<uint8_t>> {
using Base = typename ArbitraryByteVector::ContainerOfImplBase;

public:
Expand Down

0 comments on commit 1d08a71

Please sign in to comment.