mirror of
https://github.com/google/flatbuffers.git
synced 2025-04-09 00:12:15 +08:00
[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:
parent
bfceebb7fb
commit
72aa85a759
@ -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()
|
||||
|
@ -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)));
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
31
tests/alignment_test.cpp
Normal 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
24
tests/alignment_test.fbs
Normal 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
12
tests/alignment_test.h
Normal 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
|
497
tests/alignment_test_generated.h
Normal file
497
tests/alignment_test_generated.h
Normal 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_
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user