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_