Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
499 changes: 429 additions & 70 deletions domain_tests/arbitrary_domains_flatbuffers_test.cc

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion fuzztest/internal/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -616,8 +616,13 @@ cc_test(

flatbuffer_library_public(
name = "test_flatbuffers_fbs",
srcs = ["test_flatbuffers.fbs"],
srcs = [
"test_flatbuffers.fbs",
"test_flatbuffers_64bits.fbs",
],
outs = [
"test_flatbuffers_64bits_bfbs_generated.h",
"test_flatbuffers_64bits_generated.h",
"test_flatbuffers_bfbs_generated.h",
"test_flatbuffers_generated.h",
],
Expand Down
1 change: 1 addition & 0 deletions fuzztest/internal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@ if (FUZZTEST_BUILD_FLATBUFFERS)
test_flatbuffers_headers
SCHEMAS
"test_flatbuffers.fbs"
"test_flatbuffers_64bits.fbs"
FLAGS
--bfbs-gen-embed --gen-name-strings
TESTONLY
Expand Down
3 changes: 2 additions & 1 deletion fuzztest/internal/domains/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,9 @@ cc_library(
hdrs = ["flatbuffers_domain_impl.h"],
deps = [
":core_domains_impl",
"@abseil-cpp//absl/algorithm:container",
"@abseil-cpp//absl/base:core_headers",
"@abseil-cpp//absl/base:nullability",
"@abseil-cpp//absl/container:btree",
"@abseil-cpp//absl/container:flat_hash_map",
"@abseil-cpp//absl/container:flat_hash_set",
"@abseil-cpp//absl/random:bit_gen_ref",
Expand All @@ -204,6 +204,7 @@ cc_library(
"@com_google_fuzztest//fuzztest/internal:meta",
"@com_google_fuzztest//fuzztest/internal:serialization",
"@com_google_fuzztest//fuzztest/internal:status",
"@com_google_fuzztest//fuzztest/internal:type_support",
"@flatbuffers//:runtime_cc",
],
)
Expand Down
67 changes: 34 additions & 33 deletions fuzztest/internal/domains/flatbuffers_domain_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,18 @@ namespace fuzztest::internal {
FlatbuffersTableUntypedDomainImpl::FlatbuffersTableUntypedDomainImpl(
const reflection::Schema* absl_nonnull schema,
const reflection::Object* absl_nonnull table_object)
: schema_(schema), table_object_(table_object) {}
: schema_(schema), table_object_(table_object) {
for (const auto& field : *table_object_->fields()) {
fields_by_id_[field->id()] = field;
}
}

FlatbuffersTableUntypedDomainImpl::FlatbuffersTableUntypedDomainImpl(
const FlatbuffersTableUntypedDomainImpl& other)
: DomainBase(other),
schema_(other.schema_),
table_object_(other.table_object_) {
table_object_(other.table_object_),
fields_by_id_(other.fields_by_id_) {
absl::MutexLock l_other(other.mutex_);
absl::MutexLock l_this(mutex_);
domains_ = other.domains_;
Expand All @@ -55,6 +60,7 @@ FlatbuffersTableUntypedDomainImpl& FlatbuffersTableUntypedDomainImpl::operator=(
DomainBase::operator=(other);
schema_ = other.schema_;
table_object_ = other.table_object_;
fields_by_id_ = other.fields_by_id_;
absl::MutexLock l_other(other.mutex_);
absl::MutexLock l_this(mutex_);
domains_ = other.domains_;
Expand All @@ -63,7 +69,9 @@ FlatbuffersTableUntypedDomainImpl& FlatbuffersTableUntypedDomainImpl::operator=(

FlatbuffersTableUntypedDomainImpl::FlatbuffersTableUntypedDomainImpl(
FlatbuffersTableUntypedDomainImpl&& other)
: schema_(other.schema_), table_object_(other.table_object_) {
: schema_(other.schema_),
table_object_(other.table_object_),
fields_by_id_(std::move(other.fields_by_id_)) {
absl::MutexLock l_other(other.mutex_);
absl::MutexLock l_this(mutex_);
domains_ = std::move(other.domains_);
Expand All @@ -74,6 +82,7 @@ FlatbuffersTableUntypedDomainImpl& FlatbuffersTableUntypedDomainImpl::operator=(
FlatbuffersTableUntypedDomainImpl&& other) {
schema_ = other.schema_;
table_object_ = other.table_object_;
fields_by_id_ = std::move(other.fields_by_id_);
absl::MutexLock l_other(other.mutex_);
absl::MutexLock l_this(mutex_);
domains_ = std::move(other.domains_);
Expand All @@ -87,7 +96,7 @@ FlatbuffersTableUntypedDomainImpl::Init(absl::BitGenRef prng) {
return *seed;
}
corpus_type val;
for (const auto* field : *table_object_->fields()) {
for (const auto& [_, field] : fields_by_id_) {
VisitFlatbufferField(schema_, field, InitializeVisitor{*this, prng, val});
}
return val;
Expand All @@ -98,7 +107,7 @@ void FlatbuffersTableUntypedDomainImpl::Mutate(
corpus_type& val, absl::BitGenRef prng,
const domain_implementor::MutationMetadata& metadata, bool only_shrink) {
uint64_t field_count = 0;
for (const auto* field : *table_object_->fields()) {
for (const auto& [_, field] : fields_by_id_) {
VisitFlatbufferField(schema_, field,
CountNumberOfMutableFieldsVisitor{*this, field_count,
val, only_shrink});
Expand All @@ -112,7 +121,7 @@ void FlatbuffersTableUntypedDomainImpl::Mutate(
uint64_t FlatbuffersTableUntypedDomainImpl::CountNumberOfFields(
corpus_type& val) {
uint64_t field_count = 0;
for (const auto* field : *table_object_->fields()) {
for (const auto& [_, field] : fields_by_id_) {
VisitFlatbufferField(
schema_, field,
CountNumberOfMutableFieldsVisitor{*this, field_count, val});
Expand All @@ -130,29 +139,11 @@ uint64_t FlatbuffersTableUntypedDomainImpl::MutateSelectedField(
return fields_count;
}

for (const auto* field : *table_object_->fields()) {
if (!IsSupportedField(field)) {
if (only_shrink && !val.contains(field->id())) continue;
}

++field_counter;
if (field_counter == selected_field_index) {
VisitFlatbufferField(
schema_, field,
MutateVisitor{*this, prng, metadata, only_shrink, val});
return field_counter;
}

if (field->type()->base_type() == reflection::BaseType::Obj) {
auto sub_object = schema_->objects()->Get(field->type()->index());
if (!sub_object->is_struct()) {
field_counter +=
GetCachedDomain<FlatbuffersTableTag>(field).MutateSelectedField(
val[field->id()], prng, metadata, only_shrink,
selected_field_index - field_counter);
}
// TODO: Add support for structs.
}
for (const auto& [_, field] : fields_by_id_) {
VisitFlatbufferField(
schema_, field,
MutateSelectedFieldVisitor{*this, field_counter, val, prng, metadata,
only_shrink, selected_field_index});

if (field_counter >= selected_field_index) {
return field_counter;
Expand All @@ -163,7 +154,7 @@ uint64_t FlatbuffersTableUntypedDomainImpl::MutateSelectedField(

absl::Status FlatbuffersTableUntypedDomainImpl::ValidateCorpusValue(
const corpus_type& corpus_value) const {
for (const auto* field : *table_object_->fields()) {
for (const auto& [_, field] : fields_by_id_) {
absl::Status result;
GenericDomainCorpusType field_corpus;
if (auto it = corpus_value.find(field->id()); it != corpus_value.end()) {
Expand All @@ -183,7 +174,7 @@ FlatbuffersTableUntypedDomainImpl::FromValue(const value_type& value) const {
return std::nullopt;
}
corpus_type ret;
for (const auto* field : *table_object_->fields()) {
for (const auto& [_, field] : fields_by_id_) {
VisitFlatbufferField(schema_, field, FromValueVisitor{*this, value, ret});
}
return ret;
Expand Down Expand Up @@ -272,15 +263,25 @@ bool FlatbuffersTableUntypedDomainImpl::IsSupportedField(
auto sub_object = schema_->objects()->Get(field->type()->index());
return !sub_object->is_struct();
};
if (base_type == reflection::BaseType::Vector ||
base_type == reflection::BaseType::Vector64) {
auto elem_type = field->type()->element();
if (flatbuffers::IsScalar(elem_type)) return true;
if (elem_type == reflection::BaseType::String) return true;
if (elem_type == reflection::BaseType::Obj) {
auto sub_object = schema_->objects()->Get(field->type()->index());
return !sub_object->is_struct();
}
}
return false;
}

uint32_t FlatbuffersTableUntypedDomainImpl::BuildTable(
const corpus_type& value, flatbuffers::FlatBufferBuilder& builder) const {
const corpus_type& value, flatbuffers::FlatBufferBuilder64& builder) const {
// Add all the fields to the builder.

// Offsets is the map of field id to its offset in the table.
absl::flat_hash_map<typename corpus_type::key_type, flatbuffers::uoffset_t>
absl::flat_hash_map<typename corpus_type::key_type, flatbuffers::uoffset64_t>
offsets;

// Some fields are stored inline in the flatbuffer table itself (a.k.a
Expand Down
Loading
Loading