github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/executor/_include/flatbuffers/flatbuffers.h (about) 1 /* 2 * Copyright 2014 Google Inc. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef FLATBUFFERS_H_ 18 #define FLATBUFFERS_H_ 19 20 #include <algorithm> 21 22 // TODO: These includes are for mitigating the pains of users editing their 23 // source because they relied on flatbuffers.h to include everything for them. 24 #include "flatbuffers/array.h" 25 #include "flatbuffers/base.h" 26 #include "flatbuffers/buffer.h" 27 #include "flatbuffers/buffer_ref.h" 28 #include "flatbuffers/detached_buffer.h" 29 #include "flatbuffers/flatbuffer_builder.h" 30 #include "flatbuffers/stl_emulation.h" 31 #include "flatbuffers/string.h" 32 #include "flatbuffers/struct.h" 33 #include "flatbuffers/table.h" 34 #include "flatbuffers/vector.h" 35 #include "flatbuffers/vector_downward.h" 36 #include "flatbuffers/verifier.h" 37 38 namespace flatbuffers { 39 40 /// @brief This can compute the start of a FlatBuffer from a root pointer, i.e. 41 /// it is the opposite transformation of GetRoot(). 42 /// This may be useful if you want to pass on a root and have the recipient 43 /// delete the buffer afterwards. 44 inline const uint8_t *GetBufferStartFromRootPointer(const void *root) { 45 auto table = reinterpret_cast<const Table *>(root); 46 auto vtable = table->GetVTable(); 47 // Either the vtable is before the root or after the root. 48 auto start = (std::min)(vtable, reinterpret_cast<const uint8_t *>(root)); 49 // Align to at least sizeof(uoffset_t). 50 start = reinterpret_cast<const uint8_t *>(reinterpret_cast<uintptr_t>(start) & 51 ~(sizeof(uoffset_t) - 1)); 52 // Additionally, there may be a file_identifier in the buffer, and the root 53 // offset. The buffer may have been aligned to any size between 54 // sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align"). 55 // Sadly, the exact alignment is only known when constructing the buffer, 56 // since it depends on the presence of values with said alignment properties. 57 // So instead, we simply look at the next uoffset_t values (root, 58 // file_identifier, and alignment padding) to see which points to the root. 59 // None of the other values can "impersonate" the root since they will either 60 // be 0 or four ASCII characters. 61 static_assert(flatbuffers::kFileIdentifierLength == sizeof(uoffset_t), 62 "file_identifier is assumed to be the same size as uoffset_t"); 63 for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1; 64 possible_roots; possible_roots--) { 65 start -= sizeof(uoffset_t); 66 if (ReadScalar<uoffset_t>(start) + start == 67 reinterpret_cast<const uint8_t *>(root)) 68 return start; 69 } 70 // We didn't find the root, either the "root" passed isn't really a root, 71 // or the buffer is corrupt. 72 // Assert, because calling this function with bad data may cause reads 73 // outside of buffer boundaries. 74 FLATBUFFERS_ASSERT(false); 75 return nullptr; 76 } 77 78 /// @brief This return the prefixed size of a FlatBuffer. 79 template<typename SizeT = uoffset_t> 80 inline SizeT GetPrefixedSize(const uint8_t *buf) { 81 return ReadScalar<SizeT>(buf); 82 } 83 84 // Gets the total length of the buffer given a sized prefixed FlatBuffer. 85 // 86 // This includes the size of the prefix as well as the buffer: 87 // 88 // [size prefix][flatbuffer] 89 // |---------length--------| 90 template<typename SizeT = uoffset_t> 91 inline SizeT GetSizePrefixedBufferLength(const uint8_t *const buf) { 92 return ReadScalar<SizeT>(buf) + sizeof(SizeT); 93 } 94 95 // Base class for native objects (FlatBuffer data de-serialized into native 96 // C++ data structures). 97 // Contains no functionality, purely documentative. 98 struct NativeTable {}; 99 100 /// @brief Function types to be used with resolving hashes into objects and 101 /// back again. The resolver gets a pointer to a field inside an object API 102 /// object that is of the type specified in the schema using the attribute 103 /// `cpp_type` (it is thus important whatever you write to this address 104 /// matches that type). The value of this field is initially null, so you 105 /// may choose to implement a delayed binding lookup using this function 106 /// if you wish. The resolver does the opposite lookup, for when the object 107 /// is being serialized again. 108 typedef uint64_t hash_value_t; 109 typedef std::function<void(void **pointer_adr, hash_value_t hash)> 110 resolver_function_t; 111 typedef std::function<hash_value_t(void *pointer)> rehasher_function_t; 112 113 // Helper function to test if a field is present, using any of the field 114 // enums in the generated code. 115 // `table` must be a generated table type. Since this is a template parameter, 116 // this is not typechecked to be a subclass of Table, so beware! 117 // Note: this function will return false for fields equal to the default 118 // value, since they're not stored in the buffer (unless force_defaults was 119 // used). 120 template<typename T> 121 bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field) { 122 // Cast, since Table is a private baseclass of any table types. 123 return reinterpret_cast<const Table *>(table)->CheckField( 124 static_cast<voffset_t>(field)); 125 } 126 127 // Utility function for reverse lookups on the EnumNames*() functions 128 // (in the generated C++ code) 129 // names must be NULL terminated. 130 inline int LookupEnum(const char **names, const char *name) { 131 for (const char **p = names; *p; p++) 132 if (!strcmp(*p, name)) return static_cast<int>(p - names); 133 return -1; 134 } 135 136 // These macros allow us to layout a struct with a guarantee that they'll end 137 // up looking the same on different compilers and platforms. 138 // It does this by disallowing the compiler to do any padding, and then 139 // does padding itself by inserting extra padding fields that make every 140 // element aligned to its own size. 141 // Additionally, it manually sets the alignment of the struct as a whole, 142 // which is typically its largest element, or a custom size set in the schema 143 // by the force_align attribute. 144 // These are used in the generated code only. 145 146 // clang-format off 147 #if defined(_MSC_VER) 148 #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \ 149 __pragma(pack(1)) \ 150 struct __declspec(align(alignment)) 151 #define FLATBUFFERS_STRUCT_END(name, size) \ 152 __pragma(pack()) \ 153 static_assert(sizeof(name) == size, "compiler breaks packing rules") 154 #elif defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__) 155 #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \ 156 _Pragma("pack(1)") \ 157 struct __attribute__((aligned(alignment))) 158 #define FLATBUFFERS_STRUCT_END(name, size) \ 159 _Pragma("pack()") \ 160 static_assert(sizeof(name) == size, "compiler breaks packing rules") 161 #else 162 #error Unknown compiler, please define structure alignment macros 163 #endif 164 // clang-format on 165 166 // Minimal reflection via code generation. 167 // Besides full-fat reflection (see reflection.h) and parsing/printing by 168 // loading schemas (see idl.h), we can also have code generation for minimal 169 // reflection data which allows pretty-printing and other uses without needing 170 // a schema or a parser. 171 // Generate code with --reflect-types (types only) or --reflect-names (names 172 // also) to enable. 173 // See minireflect.h for utilities using this functionality. 174 175 // These types are organized slightly differently as the ones in idl.h. 176 enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM }; 177 178 // Scalars have the same order as in idl.h 179 // clang-format off 180 #define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \ 181 ET(ET_UTYPE) \ 182 ET(ET_BOOL) \ 183 ET(ET_CHAR) \ 184 ET(ET_UCHAR) \ 185 ET(ET_SHORT) \ 186 ET(ET_USHORT) \ 187 ET(ET_INT) \ 188 ET(ET_UINT) \ 189 ET(ET_LONG) \ 190 ET(ET_ULONG) \ 191 ET(ET_FLOAT) \ 192 ET(ET_DOUBLE) \ 193 ET(ET_STRING) \ 194 ET(ET_SEQUENCE) // See SequenceType. 195 196 enum ElementaryType { 197 #define FLATBUFFERS_ET(E) E, 198 FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET) 199 #undef FLATBUFFERS_ET 200 }; 201 202 inline const char * const *ElementaryTypeNames() { 203 static const char * const names[] = { 204 #define FLATBUFFERS_ET(E) #E, 205 FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET) 206 #undef FLATBUFFERS_ET 207 }; 208 return names; 209 } 210 // clang-format on 211 212 // Basic type info cost just 16bits per field! 213 // We're explicitly defining the signedness since the signedness of integer 214 // bitfields is otherwise implementation-defined and causes warnings on older 215 // GCC compilers. 216 struct TypeCode { 217 // ElementaryType 218 unsigned short base_type : 4; 219 // Either vector (in table) or array (in struct) 220 unsigned short is_repeating : 1; 221 // Index into type_refs below, or -1 for none. 222 signed short sequence_ref : 11; 223 }; 224 225 static_assert(sizeof(TypeCode) == 2, "TypeCode"); 226 227 struct TypeTable; 228 229 // Signature of the static method present in each type. 230 typedef const TypeTable *(*TypeFunction)(); 231 232 struct TypeTable { 233 SequenceType st; 234 size_t num_elems; // of type_codes, values, names (but not type_refs). 235 const TypeCode *type_codes; // num_elems count 236 const TypeFunction *type_refs; // less than num_elems entries (see TypeCode). 237 const int16_t *array_sizes; // less than num_elems entries (see TypeCode). 238 const int64_t *values; // Only set for non-consecutive enum/union or structs. 239 const char *const *names; // Only set if compiled with --reflect-names. 240 }; 241 242 // String which identifies the current version of FlatBuffers. 243 inline const char *flatbuffers_version_string() { 244 return "FlatBuffers " FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "." 245 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "." 246 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION); 247 } 248 249 // clang-format off 250 #define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\ 251 inline E operator | (E lhs, E rhs){\ 252 return E(T(lhs) | T(rhs));\ 253 }\ 254 inline E operator & (E lhs, E rhs){\ 255 return E(T(lhs) & T(rhs));\ 256 }\ 257 inline E operator ^ (E lhs, E rhs){\ 258 return E(T(lhs) ^ T(rhs));\ 259 }\ 260 inline E operator ~ (E lhs){\ 261 return E(~T(lhs));\ 262 }\ 263 inline E operator |= (E &lhs, E rhs){\ 264 lhs = lhs | rhs;\ 265 return lhs;\ 266 }\ 267 inline E operator &= (E &lhs, E rhs){\ 268 lhs = lhs & rhs;\ 269 return lhs;\ 270 }\ 271 inline E operator ^= (E &lhs, E rhs){\ 272 lhs = lhs ^ rhs;\ 273 return lhs;\ 274 }\ 275 inline bool operator !(E rhs) \ 276 {\ 277 return !bool(T(rhs)); \ 278 } 279 /// @endcond 280 } // namespace flatbuffers 281 282 // clang-format on 283 284 #endif // FLATBUFFERS_H_