github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/executor/_include/flatbuffers/table.h (about)

     1  /*
     2   * Copyright 2021 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_TABLE_H_
    18  #define FLATBUFFERS_TABLE_H_
    19  
    20  #include "flatbuffers/base.h"
    21  #include "flatbuffers/verifier.h"
    22  
    23  namespace flatbuffers {
    24  
    25  // "tables" use an offset table (possibly shared) that allows fields to be
    26  // omitted and added at will, but uses an extra indirection to read.
    27  class Table {
    28   public:
    29    const uint8_t *GetVTable() const {
    30      return data_ - ReadScalar<soffset_t>(data_);
    31    }
    32  
    33    // This gets the field offset for any of the functions below it, or 0
    34    // if the field was not present.
    35    voffset_t GetOptionalFieldOffset(voffset_t field) const {
    36      // The vtable offset is always at the start.
    37      auto vtable = GetVTable();
    38      // The first element is the size of the vtable (fields + type id + itself).
    39      auto vtsize = ReadScalar<voffset_t>(vtable);
    40      // If the field we're accessing is outside the vtable, we're reading older
    41      // data, so it's the same as if the offset was 0 (not present).
    42      return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
    43    }
    44  
    45    template<typename T> T GetField(voffset_t field, T defaultval) const {
    46      auto field_offset = GetOptionalFieldOffset(field);
    47      return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
    48    }
    49  
    50    template<typename P, typename OffsetSize = uoffset_t>
    51    P GetPointer(voffset_t field) {
    52      auto field_offset = GetOptionalFieldOffset(field);
    53      auto p = data_ + field_offset;
    54      return field_offset ? reinterpret_cast<P>(p + ReadScalar<OffsetSize>(p))
    55                          : nullptr;
    56    }
    57    template<typename P, typename OffsetSize = uoffset_t>
    58    P GetPointer(voffset_t field) const {
    59      return const_cast<Table *>(this)->GetPointer<P, OffsetSize>(field);
    60    }
    61  
    62    template<typename P> P GetPointer64(voffset_t field) {
    63      return GetPointer<P, uoffset64_t>(field);
    64    }
    65  
    66    template<typename P> P GetPointer64(voffset_t field) const {
    67      return GetPointer<P, uoffset64_t>(field);
    68    }
    69  
    70    template<typename P> P GetStruct(voffset_t field) const {
    71      auto field_offset = GetOptionalFieldOffset(field);
    72      auto p = const_cast<uint8_t *>(data_ + field_offset);
    73      return field_offset ? reinterpret_cast<P>(p) : nullptr;
    74    }
    75  
    76    template<typename Raw, typename Face>
    77    flatbuffers::Optional<Face> GetOptional(voffset_t field) const {
    78      auto field_offset = GetOptionalFieldOffset(field);
    79      auto p = data_ + field_offset;
    80      return field_offset ? Optional<Face>(static_cast<Face>(ReadScalar<Raw>(p)))
    81                          : Optional<Face>();
    82    }
    83  
    84    template<typename T> bool SetField(voffset_t field, T val, T def) {
    85      auto field_offset = GetOptionalFieldOffset(field);
    86      if (!field_offset) return IsTheSameAs(val, def);
    87      WriteScalar(data_ + field_offset, val);
    88      return true;
    89    }
    90    template<typename T> bool SetField(voffset_t field, T val) {
    91      auto field_offset = GetOptionalFieldOffset(field);
    92      if (!field_offset) return false;
    93      WriteScalar(data_ + field_offset, val);
    94      return true;
    95    }
    96  
    97    bool SetPointer(voffset_t field, const uint8_t *val) {
    98      auto field_offset = GetOptionalFieldOffset(field);
    99      if (!field_offset) return false;
   100      WriteScalar(data_ + field_offset,
   101                  static_cast<uoffset_t>(val - (data_ + field_offset)));
   102      return true;
   103    }
   104  
   105    uint8_t *GetAddressOf(voffset_t field) {
   106      auto field_offset = GetOptionalFieldOffset(field);
   107      return field_offset ? data_ + field_offset : nullptr;
   108    }
   109    const uint8_t *GetAddressOf(voffset_t field) const {
   110      return const_cast<Table *>(this)->GetAddressOf(field);
   111    }
   112  
   113    bool CheckField(voffset_t field) const {
   114      return GetOptionalFieldOffset(field) != 0;
   115    }
   116  
   117    // Verify the vtable of this table.
   118    // Call this once per table, followed by VerifyField once per field.
   119    bool VerifyTableStart(Verifier &verifier) const {
   120      return verifier.VerifyTableStart(data_);
   121    }
   122  
   123    // Verify a particular field.
   124    template<typename T>
   125    bool VerifyField(const Verifier &verifier, voffset_t field,
   126                     size_t align) const {
   127      // Calling GetOptionalFieldOffset should be safe now thanks to
   128      // VerifyTable().
   129      auto field_offset = GetOptionalFieldOffset(field);
   130      // Check the actual field.
   131      return !field_offset || verifier.VerifyField<T>(data_, field_offset, align);
   132    }
   133  
   134    // VerifyField for required fields.
   135    template<typename T>
   136    bool VerifyFieldRequired(const Verifier &verifier, voffset_t field,
   137                             size_t align) const {
   138      auto field_offset = GetOptionalFieldOffset(field);
   139      return verifier.Check(field_offset != 0) &&
   140             verifier.VerifyField<T>(data_, field_offset, align);
   141    }
   142  
   143    // Versions for offsets.
   144    template<typename OffsetT = uoffset_t>
   145    bool VerifyOffset(const Verifier &verifier, voffset_t field) const {
   146      auto field_offset = GetOptionalFieldOffset(field);
   147      return !field_offset || verifier.VerifyOffset<OffsetT>(data_, field_offset);
   148    }
   149  
   150    template<typename OffsetT = uoffset_t>
   151    bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const {
   152      auto field_offset = GetOptionalFieldOffset(field);
   153      return verifier.Check(field_offset != 0) &&
   154             verifier.VerifyOffset<OffsetT>(data_, field_offset);
   155    }
   156  
   157    bool VerifyOffset64(const Verifier &verifier, voffset_t field) const {
   158      return VerifyOffset<uoffset64_t>(verifier, field);
   159    }
   160  
   161    bool VerifyOffset64Required(const Verifier &verifier, voffset_t field) const {
   162      return VerifyOffsetRequired<uoffset64_t>(verifier, field);
   163    }
   164  
   165   private:
   166    // private constructor & copy constructor: you obtain instances of this
   167    // class by pointing to existing data only
   168    Table();
   169    Table(const Table &other);
   170    Table &operator=(const Table &);
   171  
   172    uint8_t data_[1];
   173  };
   174  
   175  // This specialization allows avoiding warnings like:
   176  // MSVC C4800: type: forcing value to bool 'true' or 'false'.
   177  template<>
   178  inline flatbuffers::Optional<bool> Table::GetOptional<uint8_t, bool>(
   179      voffset_t field) const {
   180    auto field_offset = GetOptionalFieldOffset(field);
   181    auto p = data_ + field_offset;
   182    return field_offset ? Optional<bool>(ReadScalar<uint8_t>(p) != 0)
   183                        : Optional<bool>();
   184  }
   185  
   186  }  // namespace flatbuffers
   187  
   188  #endif  // FLATBUFFERS_TABLE_H_