[C++] Rare bad buffer content alignment if sizeof(T) != alignof(T) (#7520)

* [C++] Add a failing unit test for #7516 (Rare bad buffer content alignment if sizeof(T) != alignof(T))

* [C++] Fix final buffer alignment when using an array of structs
* A struct can have an arbitrary size and therefore sizeof(struct) == alignof(struct)
  does not hold anymore as for value primitives.
* This patch fixes this by introducing alignment parameters to various
  CreateVector*/StartVector calls.
* Closes #7516
This commit is contained in:
Denis Blank 2022-09-21 20:05:05 +02:00 committed by GitHub
parent bfceebb7fb
commit 72aa85a759
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 611 additions and 16 deletions

View File

@ -230,6 +230,8 @@ set(FlatBuffers_Tests_SRCS
tests/util_test.cpp
tests/native_type_test_impl.h
tests/native_type_test_impl.cpp
tests/alignment_test.h
tests/alignment_test.cpp
include/flatbuffers/code_generators.h
src/code_generators.cpp
# file generate by running compiler on tests/monster_test.fbs
@ -251,6 +253,8 @@ set(FlatBuffers_Tests_SRCS
${CMAKE_CURRENT_BINARY_DIR}/tests/optional_scalars_generated.h
# file generate by running compiler on tests/native_inline_table_test.fbs
${CMAKE_CURRENT_BINARY_DIR}/tests/native_inline_table_test_generated.h
# file generate by running compiler on tests/alignment_test.fbs
${CMAKE_CURRENT_BINARY_DIR}/tests/alignment_test_generated.h
)
set(FlatBuffers_Tests_CPP17_SRCS
@ -623,6 +627,7 @@ if(FLATBUFFERS_BUILD_TESTS)
compile_flatbuffers_schema_to_binary(tests/arrays_test.fbs)
compile_flatbuffers_schema_to_embedded_binary(tests/monster_test.fbs "--no-includes;--gen-compare")
compile_flatbuffers_schema_to_cpp(tests/native_inline_table_test.fbs "--gen-compare")
compile_flatbuffers_schema_to_cpp(tests/alignment_test.fbs "--gen-compare")
if(NOT (MSVC AND (MSVC_VERSION LESS 1900)))
compile_flatbuffers_schema_to_cpp(tests/monster_extra.fbs) # Test floating-point NAN/INF.
endif()

View File

@ -449,7 +449,7 @@ class FlatBufferBuilder {
}
template<typename T> void PreAlign(size_t len) {
AssertScalarT<T>();
PreAlign(len, sizeof(T));
PreAlign(len, AlignOf<T>());
}
/// @endcond
@ -589,11 +589,15 @@ class FlatBufferBuilder {
return PushElement(static_cast<uoffset_t>(len));
}
void StartVector(size_t len, size_t elemsize) {
void StartVector(size_t len, size_t elemsize, size_t alignment) {
NotNested();
nested = true;
PreAlign<uoffset_t>(len * elemsize);
PreAlign(len * elemsize, elemsize); // Just in case elemsize > uoffset_t.
PreAlign(len * elemsize, alignment); // Just in case elemsize > uoffset_t.
}
template<typename T> void StartVector(size_t len) {
return StartVector(len, sizeof(T), AlignOf<T>());
}
// Call this right before StartVector/CreateVector if you want to force the
@ -627,7 +631,7 @@ class FlatBufferBuilder {
// If this assert hits, you're specifying a template argument that is
// causing the wrong overload to be selected, remove it.
AssertScalarT<T>();
StartVector(len, sizeof(T));
StartVector<T>(len);
if (len == 0) { return Offset<Vector<T>>(EndVector(len)); }
// clang-format off
#if FLATBUFFERS_LITTLEENDIAN
@ -668,7 +672,7 @@ class FlatBufferBuilder {
template<typename T>
Offset<Vector<Offset<T>>> CreateVector(const Offset<T> *v, size_t len) {
StartVector(len, sizeof(Offset<T>));
StartVector<Offset<T>>(len);
for (auto i = len; i > 0;) { PushElement(v[--i]); }
return Offset<Vector<Offset<T>>>(EndVector(len));
}
@ -688,7 +692,7 @@ class FlatBufferBuilder {
// an array. Instead, read elements manually.
// Background: https://isocpp.org/blog/2012/11/on-vectorbool
Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v) {
StartVector(v.size(), sizeof(uint8_t));
StartVector<uint8_t>(v.size());
for (auto i = v.size(); i > 0;) {
PushElement(static_cast<uint8_t>(v[--i]));
}
@ -762,7 +766,7 @@ class FlatBufferBuilder {
for (auto it = begin; it != end; ++it) {
buf_.scratch_push_small(CreateString(*it));
}
StartVector(size, sizeof(Offset<String>));
StartVector<Offset<String>>(size);
for (auto i = 1; i <= size; i++) {
// Note we re-evaluate the buf location each iteration to account for any
// underlying buffer resizing that may occur.
@ -782,7 +786,7 @@ class FlatBufferBuilder {
/// where the vector is stored.
template<typename T>
Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
StartVector(len * sizeof(T) / AlignOf<T>(), sizeof(T), AlignOf<T>());
if (len > 0) {
PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
}
@ -1025,9 +1029,9 @@ class FlatBufferBuilder {
/// written to at a later time to serialize the data into a `vector`
/// in the buffer.
uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
uint8_t **buf) {
size_t alignment, uint8_t **buf) {
NotNested();
StartVector(len, elemsize);
StartVector(len, elemsize, alignment);
buf_.make_space(len * elemsize);
auto vec_start = GetSize();
auto vec_end = EndVector(len);
@ -1035,6 +1039,12 @@ class FlatBufferBuilder {
return vec_end;
}
FLATBUFFERS_ATTRIBUTE([[deprecated("call the version above instead")]])
uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
uint8_t **buf) {
return CreateUninitializedVector(len, elemsize, elemsize, buf);
}
/// @brief Specialized version of `CreateVector` for non-copying use cases.
/// Write the data any time later to the returned buffer pointer `buf`.
/// @tparam T The data type of the data that will be stored in the buffer
@ -1046,14 +1056,14 @@ class FlatBufferBuilder {
template<typename T>
Offset<Vector<T>> CreateUninitializedVector(size_t len, T **buf) {
AssertScalarT<T>();
return CreateUninitializedVector(len, sizeof(T),
return CreateUninitializedVector(len, sizeof(T), AlignOf<T>(),
reinterpret_cast<uint8_t **>(buf));
}
template<typename T>
Offset<Vector<const T *>> CreateUninitializedVectorOfStructs(size_t len,
T **buf) {
return CreateUninitializedVector(len, sizeof(T),
return CreateUninitializedVector(len, sizeof(T), AlignOf<T>(),
reinterpret_cast<uint8_t **>(buf));
}
@ -1064,7 +1074,7 @@ class FlatBufferBuilder {
Offset<Vector<T>> CreateVectorScalarCast(const U *v, size_t len) {
AssertScalarT<T>();
AssertScalarT<U>();
StartVector(len, sizeof(T));
StartVector<T>(len);
for (auto i = len; i > 0;) { PushElement(static_cast<T>(v[--i])); }
return Offset<Vector<T>>(EndVector(len));
}
@ -1173,7 +1183,7 @@ class FlatBufferBuilder {
// Allocates space for a vector of structures.
// Must be completed with EndVectorOfStructs().
template<typename T> T *StartVectorOfStructs(size_t vector_size) {
StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
StartVector(vector_size * sizeof(T) / AlignOf<T>(), sizeof(T), AlignOf<T>());
return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
}

View File

@ -1614,6 +1614,7 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
});
ECHECK(err);
const size_t alignment = InlineAlignment(type);
const size_t len = count * InlineSize(type) / InlineAlignment(type);
const size_t elemsize = InlineAlignment(type);
const auto force_align = field->attributes.Lookup("force_align");
@ -1623,7 +1624,8 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
if (align > 1) { builder_.ForceVectorAlignment(len, elemsize, align); }
}
builder_.StartVector(len, elemsize);
// TODO Fix using element alignment as size (`elemsize`)!
builder_.StartVector(len, elemsize, alignment);
for (uoffset_t i = 0; i < count; i++) {
// start at the back, since we're building the data backwards.
auto &val = field_stack_.back().first;

View File

@ -689,9 +689,10 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
FLATBUFFERS_FALLTHROUGH(); // fall thru
default: { // Scalars and structs.
auto element_size = GetTypeSize(element_base_type);
auto element_alignment = element_size; // For primitive elements
if (elemobjectdef && elemobjectdef->is_struct())
element_size = elemobjectdef->bytesize();
fbb.StartVector(vec->size(), element_size);
fbb.StartVector(vec->size(), element_size, element_alignment);
fbb.PushBytes(vec->Data(), element_size * vec->size());
offset = fbb.EndVector(vec->size());
break;

View File

@ -8,6 +8,9 @@ cc_test(
name = "flatbuffers_test",
testonly = 1,
srcs = [
"alignment_test.cpp",
"alignment_test.h",
"alignment_test_generated.h",
"evolution_test.cpp",
"evolution_test.h",
"evolution_test/evolution_v1_generated.h",
@ -50,6 +53,7 @@ cc_test(
"-DBAZEL_TEST_DATA_PATH",
],
data = [
":alignment_test.fbs",
":arrays_test.bfbs",
":arrays_test.fbs",
":arrays_test.golden",
@ -90,6 +94,7 @@ cc_test(
"include/",
],
deps = [
":alignment_test_cc_fbs",
":arrays_test_cc_fbs",
":monster_extra_cc_fbs",
":monster_test_cc_fbs",
@ -214,3 +219,8 @@ flatbuffer_cc_library(
"--cpp-ptr-type flatbuffers::unique_ptr",
],
)
flatbuffer_cc_library(
name = "alignment_test_cc_fbs",
srcs = ["alignment_test.fbs"],
)

31
tests/alignment_test.cpp Normal file
View File

@ -0,0 +1,31 @@
#include "alignment_test.h"
#include "flatbuffers/flatbuffer_builder.h"
#include "alignment_test_generated.h"
#include "test_assert.h"
namespace flatbuffers {
namespace tests {
void AlignmentTest() {
FlatBufferBuilder builder;
BadAlignmentLarge large;
Offset<OuterLarge> outer_large = CreateOuterLarge(builder, &large);
BadAlignmentSmall *small;
Offset<Vector<const BadAlignmentSmall *>> small_offset =
builder.CreateUninitializedVectorOfStructs(9, &small);
(void)small; // We do not have to write data to trigger the test failure
Offset<BadAlignmentRoot> root =
CreateBadAlignmentRoot(builder, outer_large, small_offset);
builder.Finish(root);
Verifier verifier(builder.GetBufferPointer(), builder.GetSize());
TEST_ASSERT(VerifyBadAlignmentRootBuffer(verifier));
}
} // namespace tests
} // namespace flatbuffers

24
tests/alignment_test.fbs Normal file
View File

@ -0,0 +1,24 @@
// sizeof(BadAlignmentSmall) == 12
// alignof(BadAlignmentSmall) == 4
struct BadAlignmentSmall {
var_0: uint;
var_1: uint;
var_2: uint;
}
// sizeof(BadAlignmentLarge) == 8
// alignof(BadAlignmentLarge) == 8
struct BadAlignmentLarge {
var_0: ulong;
}
table OuterLarge {
large: BadAlignmentLarge;
}
table BadAlignmentRoot {
large: OuterLarge;
small: [BadAlignmentSmall];
}
root_type BadAlignmentRoot;

12
tests/alignment_test.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef TESTS_ALIGNMENT_TEST_H
#define TESTS_ALIGNMENT_TEST_H
namespace flatbuffers {
namespace tests {
void AlignmentTest();
} // namespace tests
} // namespace flatbuffers
#endif

View File

@ -0,0 +1,497 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_ALIGNMENTTEST_H_
#define FLATBUFFERS_GENERATED_ALIGNMENTTEST_H_
#include "flatbuffers/flatbuffers.h"
// Ensure the included flatbuffers.h is the same version as when this file was
// generated, otherwise it may not be compatible.
static_assert(FLATBUFFERS_VERSION_MAJOR == 2 &&
FLATBUFFERS_VERSION_MINOR == 0 &&
FLATBUFFERS_VERSION_REVISION == 8,
"Non-compatible flatbuffers version included");
struct BadAlignmentSmall;
struct BadAlignmentLarge;
struct OuterLarge;
struct OuterLargeBuilder;
struct OuterLargeT;
struct BadAlignmentRoot;
struct BadAlignmentRootBuilder;
struct BadAlignmentRootT;
bool operator==(const BadAlignmentSmall &lhs, const BadAlignmentSmall &rhs);
bool operator!=(const BadAlignmentSmall &lhs, const BadAlignmentSmall &rhs);
bool operator==(const BadAlignmentLarge &lhs, const BadAlignmentLarge &rhs);
bool operator!=(const BadAlignmentLarge &lhs, const BadAlignmentLarge &rhs);
bool operator==(const OuterLargeT &lhs, const OuterLargeT &rhs);
bool operator!=(const OuterLargeT &lhs, const OuterLargeT &rhs);
bool operator==(const BadAlignmentRootT &lhs, const BadAlignmentRootT &rhs);
bool operator!=(const BadAlignmentRootT &lhs, const BadAlignmentRootT &rhs);
inline const flatbuffers::TypeTable *BadAlignmentSmallTypeTable();
inline const flatbuffers::TypeTable *BadAlignmentLargeTypeTable();
inline const flatbuffers::TypeTable *OuterLargeTypeTable();
inline const flatbuffers::TypeTable *BadAlignmentRootTypeTable();
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) BadAlignmentSmall FLATBUFFERS_FINAL_CLASS {
private:
uint32_t var_0_;
uint32_t var_1_;
uint32_t var_2_;
public:
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
return BadAlignmentSmallTypeTable();
}
BadAlignmentSmall()
: var_0_(0),
var_1_(0),
var_2_(0) {
}
BadAlignmentSmall(uint32_t _var_0, uint32_t _var_1, uint32_t _var_2)
: var_0_(flatbuffers::EndianScalar(_var_0)),
var_1_(flatbuffers::EndianScalar(_var_1)),
var_2_(flatbuffers::EndianScalar(_var_2)) {
}
uint32_t var_0() const {
return flatbuffers::EndianScalar(var_0_);
}
void mutate_var_0(uint32_t _var_0) {
flatbuffers::WriteScalar(&var_0_, _var_0);
}
uint32_t var_1() const {
return flatbuffers::EndianScalar(var_1_);
}
void mutate_var_1(uint32_t _var_1) {
flatbuffers::WriteScalar(&var_1_, _var_1);
}
uint32_t var_2() const {
return flatbuffers::EndianScalar(var_2_);
}
void mutate_var_2(uint32_t _var_2) {
flatbuffers::WriteScalar(&var_2_, _var_2);
}
};
FLATBUFFERS_STRUCT_END(BadAlignmentSmall, 12);
inline bool operator==(const BadAlignmentSmall &lhs, const BadAlignmentSmall &rhs) {
return
(lhs.var_0() == rhs.var_0()) &&
(lhs.var_1() == rhs.var_1()) &&
(lhs.var_2() == rhs.var_2());
}
inline bool operator!=(const BadAlignmentSmall &lhs, const BadAlignmentSmall &rhs) {
return !(lhs == rhs);
}
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) BadAlignmentLarge FLATBUFFERS_FINAL_CLASS {
private:
uint64_t var_0_;
public:
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
return BadAlignmentLargeTypeTable();
}
BadAlignmentLarge()
: var_0_(0) {
}
BadAlignmentLarge(uint64_t _var_0)
: var_0_(flatbuffers::EndianScalar(_var_0)) {
}
uint64_t var_0() const {
return flatbuffers::EndianScalar(var_0_);
}
void mutate_var_0(uint64_t _var_0) {
flatbuffers::WriteScalar(&var_0_, _var_0);
}
};
FLATBUFFERS_STRUCT_END(BadAlignmentLarge, 8);
inline bool operator==(const BadAlignmentLarge &lhs, const BadAlignmentLarge &rhs) {
return
(lhs.var_0() == rhs.var_0());
}
inline bool operator!=(const BadAlignmentLarge &lhs, const BadAlignmentLarge &rhs) {
return !(lhs == rhs);
}
struct OuterLargeT : public flatbuffers::NativeTable {
typedef OuterLarge TableType;
flatbuffers::unique_ptr<BadAlignmentLarge> large{};
OuterLargeT() = default;
OuterLargeT(const OuterLargeT &o);
OuterLargeT(OuterLargeT&&) FLATBUFFERS_NOEXCEPT = default;
OuterLargeT &operator=(OuterLargeT o) FLATBUFFERS_NOEXCEPT;
};
struct OuterLarge FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef OuterLargeT NativeTableType;
typedef OuterLargeBuilder Builder;
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
return OuterLargeTypeTable();
}
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_LARGE = 4
};
const BadAlignmentLarge *large() const {
return GetStruct<const BadAlignmentLarge *>(VT_LARGE);
}
BadAlignmentLarge *mutable_large() {
return GetStruct<BadAlignmentLarge *>(VT_LARGE);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<BadAlignmentLarge>(verifier, VT_LARGE, 8) &&
verifier.EndTable();
}
OuterLargeT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
void UnPackTo(OuterLargeT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
static flatbuffers::Offset<OuterLarge> Pack(flatbuffers::FlatBufferBuilder &_fbb, const OuterLargeT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
};
struct OuterLargeBuilder {
typedef OuterLarge Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_large(const BadAlignmentLarge *large) {
fbb_.AddStruct(OuterLarge::VT_LARGE, large);
}
explicit OuterLargeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
flatbuffers::Offset<OuterLarge> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<OuterLarge>(end);
return o;
}
};
inline flatbuffers::Offset<OuterLarge> CreateOuterLarge(
flatbuffers::FlatBufferBuilder &_fbb,
const BadAlignmentLarge *large = nullptr) {
OuterLargeBuilder builder_(_fbb);
builder_.add_large(large);
return builder_.Finish();
}
flatbuffers::Offset<OuterLarge> CreateOuterLarge(flatbuffers::FlatBufferBuilder &_fbb, const OuterLargeT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
struct BadAlignmentRootT : public flatbuffers::NativeTable {
typedef BadAlignmentRoot TableType;
flatbuffers::unique_ptr<OuterLargeT> large{};
std::vector<BadAlignmentSmall> small{};
BadAlignmentRootT() = default;
BadAlignmentRootT(const BadAlignmentRootT &o);
BadAlignmentRootT(BadAlignmentRootT&&) FLATBUFFERS_NOEXCEPT = default;
BadAlignmentRootT &operator=(BadAlignmentRootT o) FLATBUFFERS_NOEXCEPT;
};
struct BadAlignmentRoot FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef BadAlignmentRootT NativeTableType;
typedef BadAlignmentRootBuilder Builder;
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
return BadAlignmentRootTypeTable();
}
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_LARGE = 4,
VT_SMALL = 6
};
const OuterLarge *large() const {
return GetPointer<const OuterLarge *>(VT_LARGE);
}
OuterLarge *mutable_large() {
return GetPointer<OuterLarge *>(VT_LARGE);
}
const flatbuffers::Vector<const BadAlignmentSmall *> *small() const {
return GetPointer<const flatbuffers::Vector<const BadAlignmentSmall *> *>(VT_SMALL);
}
flatbuffers::Vector<const BadAlignmentSmall *> *mutable_small() {
return GetPointer<flatbuffers::Vector<const BadAlignmentSmall *> *>(VT_SMALL);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffset(verifier, VT_LARGE) &&
verifier.VerifyTable(large()) &&
VerifyOffset(verifier, VT_SMALL) &&
verifier.VerifyVector(small()) &&
verifier.EndTable();
}
BadAlignmentRootT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
void UnPackTo(BadAlignmentRootT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
static flatbuffers::Offset<BadAlignmentRoot> Pack(flatbuffers::FlatBufferBuilder &_fbb, const BadAlignmentRootT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
};
struct BadAlignmentRootBuilder {
typedef BadAlignmentRoot Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_large(flatbuffers::Offset<OuterLarge> large) {
fbb_.AddOffset(BadAlignmentRoot::VT_LARGE, large);
}
void add_small(flatbuffers::Offset<flatbuffers::Vector<const BadAlignmentSmall *>> small) {
fbb_.AddOffset(BadAlignmentRoot::VT_SMALL, small);
}
explicit BadAlignmentRootBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
flatbuffers::Offset<BadAlignmentRoot> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<BadAlignmentRoot>(end);
return o;
}
};
inline flatbuffers::Offset<BadAlignmentRoot> CreateBadAlignmentRoot(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<OuterLarge> large = 0,
flatbuffers::Offset<flatbuffers::Vector<const BadAlignmentSmall *>> small = 0) {
BadAlignmentRootBuilder builder_(_fbb);
builder_.add_small(small);
builder_.add_large(large);
return builder_.Finish();
}
inline flatbuffers::Offset<BadAlignmentRoot> CreateBadAlignmentRootDirect(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<OuterLarge> large = 0,
const std::vector<BadAlignmentSmall> *small = nullptr) {
auto small__ = small ? _fbb.CreateVectorOfStructs<BadAlignmentSmall>(*small) : 0;
return CreateBadAlignmentRoot(
_fbb,
large,
small__);
}
flatbuffers::Offset<BadAlignmentRoot> CreateBadAlignmentRoot(flatbuffers::FlatBufferBuilder &_fbb, const BadAlignmentRootT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
inline bool operator==(const OuterLargeT &lhs, const OuterLargeT &rhs) {
return
((lhs.large == rhs.large) || (lhs.large && rhs.large && *lhs.large == *rhs.large));
}
inline bool operator!=(const OuterLargeT &lhs, const OuterLargeT &rhs) {
return !(lhs == rhs);
}
inline OuterLargeT::OuterLargeT(const OuterLargeT &o)
: large((o.large) ? new BadAlignmentLarge(*o.large) : nullptr) {
}
inline OuterLargeT &OuterLargeT::operator=(OuterLargeT o) FLATBUFFERS_NOEXCEPT {
std::swap(large, o.large);
return *this;
}
inline OuterLargeT *OuterLarge::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
auto _o = std::unique_ptr<OuterLargeT>(new OuterLargeT());
UnPackTo(_o.get(), _resolver);
return _o.release();
}
inline void OuterLarge::UnPackTo(OuterLargeT *_o, const flatbuffers::resolver_function_t *_resolver) const {
(void)_o;
(void)_resolver;
{ auto _e = large(); if (_e) _o->large = flatbuffers::unique_ptr<BadAlignmentLarge>(new BadAlignmentLarge(*_e)); }
}
inline flatbuffers::Offset<OuterLarge> OuterLarge::Pack(flatbuffers::FlatBufferBuilder &_fbb, const OuterLargeT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
return CreateOuterLarge(_fbb, _o, _rehasher);
}
inline flatbuffers::Offset<OuterLarge> CreateOuterLarge(flatbuffers::FlatBufferBuilder &_fbb, const OuterLargeT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
(void)_rehasher;
(void)_o;
struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const OuterLargeT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
auto _large = _o->large ? _o->large.get() : nullptr;
return CreateOuterLarge(
_fbb,
_large);
}
inline bool operator==(const BadAlignmentRootT &lhs, const BadAlignmentRootT &rhs) {
return
((lhs.large == rhs.large) || (lhs.large && rhs.large && *lhs.large == *rhs.large)) &&
(lhs.small == rhs.small);
}
inline bool operator!=(const BadAlignmentRootT &lhs, const BadAlignmentRootT &rhs) {
return !(lhs == rhs);
}
inline BadAlignmentRootT::BadAlignmentRootT(const BadAlignmentRootT &o)
: large((o.large) ? new OuterLargeT(*o.large) : nullptr),
small(o.small) {
}
inline BadAlignmentRootT &BadAlignmentRootT::operator=(BadAlignmentRootT o) FLATBUFFERS_NOEXCEPT {
std::swap(large, o.large);
std::swap(small, o.small);
return *this;
}
inline BadAlignmentRootT *BadAlignmentRoot::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
auto _o = std::unique_ptr<BadAlignmentRootT>(new BadAlignmentRootT());
UnPackTo(_o.get(), _resolver);
return _o.release();
}
inline void BadAlignmentRoot::UnPackTo(BadAlignmentRootT *_o, const flatbuffers::resolver_function_t *_resolver) const {
(void)_o;
(void)_resolver;
{ auto _e = large(); if (_e) { if(_o->large) { _e->UnPackTo(_o->large.get(), _resolver); } else { _o->large = flatbuffers::unique_ptr<OuterLargeT>(_e->UnPack(_resolver)); } } else if (_o->large) { _o->large.reset(); } }
{ auto _e = small(); if (_e) { _o->small.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->small[_i] = *_e->Get(_i); } } else { _o->small.resize(0); } }
}
inline flatbuffers::Offset<BadAlignmentRoot> BadAlignmentRoot::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BadAlignmentRootT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
return CreateBadAlignmentRoot(_fbb, _o, _rehasher);
}
inline flatbuffers::Offset<BadAlignmentRoot> CreateBadAlignmentRoot(flatbuffers::FlatBufferBuilder &_fbb, const BadAlignmentRootT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
(void)_rehasher;
(void)_o;
struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const BadAlignmentRootT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
auto _large = _o->large ? CreateOuterLarge(_fbb, _o->large.get(), _rehasher) : 0;
auto _small = _o->small.size() ? _fbb.CreateVectorOfStructs(_o->small) : 0;
return CreateBadAlignmentRoot(
_fbb,
_large,
_small);
}
inline const flatbuffers::TypeTable *BadAlignmentSmallTypeTable() {
static const flatbuffers::TypeCode type_codes[] = {
{ flatbuffers::ET_UINT, 0, -1 },
{ flatbuffers::ET_UINT, 0, -1 },
{ flatbuffers::ET_UINT, 0, -1 }
};
static const int64_t values[] = { 0, 4, 8, 12 };
static const char * const names[] = {
"var_0",
"var_1",
"var_2"
};
static const flatbuffers::TypeTable tt = {
flatbuffers::ST_STRUCT, 3, type_codes, nullptr, nullptr, values, names
};
return &tt;
}
inline const flatbuffers::TypeTable *BadAlignmentLargeTypeTable() {
static const flatbuffers::TypeCode type_codes[] = {
{ flatbuffers::ET_ULONG, 0, -1 }
};
static const int64_t values[] = { 0, 8 };
static const char * const names[] = {
"var_0"
};
static const flatbuffers::TypeTable tt = {
flatbuffers::ST_STRUCT, 1, type_codes, nullptr, nullptr, values, names
};
return &tt;
}
inline const flatbuffers::TypeTable *OuterLargeTypeTable() {
static const flatbuffers::TypeCode type_codes[] = {
{ flatbuffers::ET_SEQUENCE, 0, 0 }
};
static const flatbuffers::TypeFunction type_refs[] = {
BadAlignmentLargeTypeTable
};
static const char * const names[] = {
"large"
};
static const flatbuffers::TypeTable tt = {
flatbuffers::ST_TABLE, 1, type_codes, type_refs, nullptr, nullptr, names
};
return &tt;
}
inline const flatbuffers::TypeTable *BadAlignmentRootTypeTable() {
static const flatbuffers::TypeCode type_codes[] = {
{ flatbuffers::ET_SEQUENCE, 0, 0 },
{ flatbuffers::ET_SEQUENCE, 1, 1 }
};
static const flatbuffers::TypeFunction type_refs[] = {
OuterLargeTypeTable,
BadAlignmentSmallTypeTable
};
static const char * const names[] = {
"large",
"small"
};
static const flatbuffers::TypeTable tt = {
flatbuffers::ST_TABLE, 2, type_codes, type_refs, nullptr, nullptr, names
};
return &tt;
}
inline const BadAlignmentRoot *GetBadAlignmentRoot(const void *buf) {
return flatbuffers::GetRoot<BadAlignmentRoot>(buf);
}
inline const BadAlignmentRoot *GetSizePrefixedBadAlignmentRoot(const void *buf) {
return flatbuffers::GetSizePrefixedRoot<BadAlignmentRoot>(buf);
}
inline BadAlignmentRoot *GetMutableBadAlignmentRoot(void *buf) {
return flatbuffers::GetMutableRoot<BadAlignmentRoot>(buf);
}
inline BadAlignmentRoot *GetMutableSizePrefixedBadAlignmentRoot(void *buf) {
return flatbuffers::GetMutableSizePrefixedRoot<BadAlignmentRoot>(buf);
}
inline bool VerifyBadAlignmentRootBuffer(
flatbuffers::Verifier &verifier) {
return verifier.VerifyBuffer<BadAlignmentRoot>(nullptr);
}
inline bool VerifySizePrefixedBadAlignmentRootBuffer(
flatbuffers::Verifier &verifier) {
return verifier.VerifySizePrefixedBuffer<BadAlignmentRoot>(nullptr);
}
inline void FinishBadAlignmentRootBuffer(
flatbuffers::FlatBufferBuilder &fbb,
flatbuffers::Offset<BadAlignmentRoot> root) {
fbb.Finish(root);
}
inline void FinishSizePrefixedBadAlignmentRootBuffer(
flatbuffers::FlatBufferBuilder &fbb,
flatbuffers::Offset<BadAlignmentRoot> root) {
fbb.FinishSizePrefixed(root);
}
inline flatbuffers::unique_ptr<BadAlignmentRootT> UnPackBadAlignmentRoot(
const void *buf,
const flatbuffers::resolver_function_t *res = nullptr) {
return flatbuffers::unique_ptr<BadAlignmentRootT>(GetBadAlignmentRoot(buf)->UnPack(res));
}
inline flatbuffers::unique_ptr<BadAlignmentRootT> UnPackSizePrefixedBadAlignmentRoot(
const void *buf,
const flatbuffers::resolver_function_t *res = nullptr) {
return flatbuffers::unique_ptr<BadAlignmentRootT>(GetSizePrefixedBadAlignmentRoot(buf)->UnPack(res));
}
#endif // FLATBUFFERS_GENERATED_ALIGNMENTTEST_H_

View File

@ -20,6 +20,7 @@
#include <string>
#include "evolution_test.h"
#include "alignment_test.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/minireflect.h"
@ -1416,6 +1417,8 @@ int FlatBufferTests(const std::string &tests_data_path) {
SizePrefixedTest();
AlignmentTest();
#ifndef FLATBUFFERS_NO_FILE_TESTS
ParseAndGenerateTextTest(tests_data_path, false);
ParseAndGenerateTextTest(tests_data_path, true);