diff --git a/fuzztest/internal/domains/container_of_impl.h b/fuzztest/internal/domains/container_of_impl.h index 6e30c6e6..3ef62f8b 100644 --- a/fuzztest/internal/domains/container_of_impl.h +++ b/fuzztest/internal/domains/container_of_impl.h @@ -74,12 +74,11 @@ using ContainerOfImplBaseCorpusType = std::conditional_t< std::list>, ValueType>; // Common base for container domains. Provides common APIs. -template -class ContainerOfImplBase : public domain_implementor::DomainBase< - Derived, ExtractTemplateParameter<0, Derived>, - ContainerOfImplBaseCorpusType> { - using InnerDomainT = ExtractTemplateParameter<1, Derived>; - +template , + typename InnerDomainT = ExtractTemplateParameter<1, Derived>> +class ContainerOfImplBase + : public domain_implementor::DomainBase< + Derived, T, ContainerOfImplBaseCorpusType> { public: using ContainerOfImplBase::DomainBase::has_custom_corpus_type; using typename ContainerOfImplBase::DomainBase::corpus_type; @@ -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; @@ -341,11 +339,13 @@ class ContainerOfImplBase : public domain_implementor::DomainBase< InnerDomainT Inner() const { return inner_; } - template + // Needed for `CopyConstraintsFrom`. + template friend class ContainerOfImplBase; - template - void CopyConstraintsFrom(const ContainerOfImplBase& other) { + template + void CopyConstraintsFrom(const ContainerOfImplBase& other) { min_size_ = other.min_size_; max_size_ = other.max_size_; } @@ -524,16 +524,17 @@ Please verify that the inner domain can provide enough values. } }; -template -class SequenceContainerOfImpl - : public ContainerOfImplBase> { - using Base = typename SequenceContainerOfImpl::ContainerOfImplBase; +template , + typename InnerDomain = ExtractTemplateParameter<1, Derived>> +class SequenceContainerOfImplBase + : public ContainerOfImplBase { + 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) { @@ -582,6 +583,15 @@ class SequenceContainerOfImpl } }; +template +class SequenceContainerOfImpl : public SequenceContainerOfImplBase< + SequenceContainerOfImpl> { + using Base = typename SequenceContainerOfImpl::SequenceContainerOfImplBase; + + public: + using Base::Base; +}; + template using ContainerOfImpl = std::conditional_t, diff --git a/fuzztest/llvm_fuzzer_wrapper.cc b/fuzztest/llvm_fuzzer_wrapper.cc index f0c59b75..b28d1f18 100644 --- a/fuzztest/llvm_fuzzer_wrapper.cc +++ b/fuzztest/llvm_fuzzer_wrapper.cc @@ -1,3 +1,4 @@ +#include #include #include #include @@ -84,52 +85,6 @@ std::vector> ReadByteArrayDictionaryFromFile() { return out; } -template -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; @@ -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, fuzztest::internal::ArbitraryImpl>(); + static auto domain = fuzztest::Arbitrary>() + .WithDictionary(ReadByteArrayDictionaryFromFile) + .WithSeeds(ReadByteArraysFromDirectory); domain.WithMaxSize(max_size); absl::BitGen bitgen; - InplaceVector val(data, size); + std::vector 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, fuzztest::internal::ArbitraryImpl> { + : public fuzztest::internal::SequenceContainerOfImplBase< + ArbitraryByteVector, std::vector, + fuzztest::internal::ArbitraryImpl> { using Base = typename ArbitraryByteVector::ContainerOfImplBase; public: