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
26 changes: 26 additions & 0 deletions domain_tests/arbitrary_domains_flatbuffers_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@
#include "./domain_tests/domain_testing.h"
#include "./fuzztest/flatbuffers.h"
#include "./fuzztest/internal/meta.h"
#include "./fuzztest/internal/test_flatbuffers_64bits_generated.h"
#include "./fuzztest/internal/test_flatbuffers_generated.h"

namespace fuzztest {
namespace {

using ::fuzztest::internal::BoolTable;
using ::fuzztest::internal::DefaultTable;
using ::fuzztest::internal::DefaultTable64;
using ::fuzztest::internal::OptionalTable;
using ::fuzztest::internal::RecursiveTable;
using ::fuzztest::internal::RequiredTable;
Expand Down Expand Up @@ -592,5 +594,29 @@ TEST(FlatbuffersTableDomainImplTest, RecursiveTable) {
ASSERT_THAT(new_table, IsNull());
}

TEST(FlatbuffersTableDomainImplTest, DefaultTable64ValueRoundTrip) {
flatbuffers::FlatBufferBuilder64 fbb;
auto str_offset = fbb.CreateString<flatbuffers::Offset64>("foo bar baz");
auto table_offset = internal::CreateDefaultTable64(fbb, str_offset);
fbb.Finish(table_offset);
auto table = flatbuffers::GetRoot<DefaultTable64>(fbb.GetBufferPointer());

auto domain = Arbitrary<const DefaultTable64*>();
auto corpus = domain.FromValue(table);
ASSERT_TRUE(corpus.has_value());
ASSERT_OK(domain.ValidateCorpusValue(*corpus));

auto ir = domain.SerializeCorpus(corpus.value());

auto new_corpus = domain.ParseCorpus(ir);
ASSERT_TRUE(new_corpus.has_value());
ASSERT_OK(domain.ValidateCorpusValue(*new_corpus));

auto new_table = domain.GetValue(*new_corpus);
ASSERT_THAT(new_table, NotNull());
ASSERT_THAT(new_table->str(), NotNull());
EXPECT_EQ(new_table->str()->str(), "foo bar baz");
}

} // namespace
} // namespace fuzztest
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
4 changes: 2 additions & 2 deletions fuzztest/internal/domains/flatbuffers_domain_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -276,11 +276,11 @@ bool FlatbuffersTableUntypedDomainImpl::IsSupportedField(
}

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
53 changes: 37 additions & 16 deletions fuzztest/internal/domains/flatbuffers_domain_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "absl/strings/str_format.h"
#include "absl/synchronization/mutex.h"
#include "flatbuffers/base.h"
#include "flatbuffers/buffer.h"
#include "flatbuffers/flatbuffer_builder.h"
#include "flatbuffers/reflection_generated.h"
#include "flatbuffers/string.h"
Expand Down Expand Up @@ -365,7 +366,7 @@ class FlatbuffersTableUntypedDomainImpl
bool IsSupportedField(const reflection::Field* absl_nonnull field) const;

uint32_t BuildTable(const corpus_type& value,
flatbuffers::FlatBufferBuilder& builder) const;
flatbuffers::FlatBufferBuilder64& builder) const;

// Returns the domain for the given field.
// The domain is cached, and the same instance is returned for the same field.
Expand Down Expand Up @@ -441,9 +442,15 @@ class FlatbuffersTableUntypedDomainImpl
}
} else if constexpr (std::is_same_v<T, std::string>) {
if (user_value->CheckField(field->offset())) {
inner_value = std::optional(
user_value->GetPointer<flatbuffers::String*>(field->offset())
->str());
if (field->offset64()) {
inner_value = std::optional(
user_value->GetPointer64<flatbuffers::String*>(field->offset())
->str());
} else {
inner_value = std::optional(
user_value->GetPointer<flatbuffers::String*>(field->offset())
->str());
}
}
} else if constexpr (std::is_same_v<T, FlatbuffersTableTag>) {
auto sub_object = self.schema_->objects()->Get(field->type()->index());
Expand All @@ -464,9 +471,9 @@ class FlatbuffersTableUntypedDomainImpl
// Create out-of-line table fields, see `BuildTable` for details.
struct TableFieldBuilderVisitor {
const FlatbuffersTableUntypedDomainImpl& self;
flatbuffers::FlatBufferBuilder& builder;
absl::flat_hash_map<typename corpus_type::key_type, flatbuffers::uoffset_t>&
offsets;
flatbuffers::FlatBufferBuilder64& builder;
absl::flat_hash_map<typename corpus_type::key_type,
flatbuffers::uoffset64_t>& offsets;
const typename corpus_type::mapped_type& corpus_value;

template <typename T>
Expand All @@ -475,8 +482,16 @@ class FlatbuffersTableUntypedDomainImpl
auto& domain = self.GetCachedDomain<T>(field);
auto user_value = domain.GetValue(corpus_value);
if (user_value.has_value()) {
auto offset =
builder.CreateString(user_value->data(), user_value->size()).o;
flatbuffers::uoffset64_t offset;
if (field->offset64()) {
offset = builder
.CreateString<flatbuffers::Offset64>(
user_value->data(), user_value->size())
.o;
} else {
offset =
builder.CreateString(user_value->data(), user_value->size()).o;
}
offsets.insert({field->id(), offset});
}
} else if constexpr (std::is_same_v<T, FlatbuffersTableTag>) {
Expand All @@ -502,9 +517,9 @@ class FlatbuffersTableUntypedDomainImpl
// offsets for "out-of-line fields". See `BuildTable` for details.
struct TableBuilderVisitor {
const FlatbuffersTableUntypedDomainImpl& self;
flatbuffers::FlatBufferBuilder& builder;
const absl::flat_hash_map<typename corpus_type::key_type,
flatbuffers::uoffset_t>& offsets;
flatbuffers::FlatBufferBuilder64& builder;
absl::flat_hash_map<typename corpus_type::key_type,
flatbuffers::uoffset64_t>& offsets;
const typename corpus_type::value_type::second_type& corpus_value;

template <typename T>
Expand All @@ -521,9 +536,15 @@ class FlatbuffersTableUntypedDomainImpl
} else if constexpr (std::is_same_v<T, std::string>) {
// "Out-of-line field". Store just offset.
if (auto it = offsets.find(field->id()); it != offsets.end()) {
builder.AddOffset(
field->offset(),
flatbuffers::Offset<flatbuffers::String>(it->second));
if (field->offset64()) {
builder.AddOffset(
field->offset(),
flatbuffers::Offset64<flatbuffers::String>(it->second));
} else {
builder.AddOffset(
field->offset(),
flatbuffers::Offset<flatbuffers::String>(it->second));
}
}
} else if constexpr (std::is_same_v<T, FlatbuffersTableTag>) {
// "Out-of-line field". Store just offset.
Expand Down Expand Up @@ -753,7 +774,7 @@ class FlatbuffersTableDomainImpl

// Converts corpus value into the exact flatbuffer.
value_type GetValue(const corpus_type& value) const {
flatbuffers::FlatBufferBuilder builder;
flatbuffers::FlatBufferBuilder64 builder;
const uint32_t offset = inner_->BuildTable(value.untyped_corpus, builder);
builder.Finish(flatbuffers::Offset<flatbuffers::Table>(offset));
value.buffer =
Expand Down
21 changes: 21 additions & 0 deletions fuzztest/internal/test_flatbuffers_64bits.fbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace fuzztest.internal;

table DefaultTable64 {
str:string (offset64);
}

root_type DefaultTable64;
Loading