github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/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> P GetPointer(voffset_t field) {
    51      auto field_offset = GetOptionalFieldOffset(field);
    52      auto p = data_ + field_offset;
    53      return field_offset ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p))
    54                          : nullptr;
    55    }
    56    template<typename P> P GetPointer(voffset_t field) const {
    57      return const_cast<Table *>(this)->GetPointer<P>(field);
    58    }
    59  
    60    template<typename P> P GetStruct(voffset_t field) const {
    61      auto field_offset = GetOptionalFieldOffset(field);
    62      auto p = const_cast<uint8_t *>(data_ + field_offset);
    63      return field_offset ? reinterpret_cast<P>(p) : nullptr;
    64    }
    65  
    66    template<typename Raw, typename Face>
    67    flatbuffers::Optional<Face> GetOptional(voffset_t field) const {
    68      auto field_offset = GetOptionalFieldOffset(field);
    69      auto p = data_ + field_offset;
    70      return field_offset ? Optional<Face>(static_cast<Face>(ReadScalar<Raw>(p)))
    71                          : Optional<Face>();
    72    }
    73  
    74    template<typename T> bool SetField(voffset_t field, T val, T def) {
    75      auto field_offset = GetOptionalFieldOffset(field);
    76      if (!field_offset) return IsTheSameAs(val, def);
    77      WriteScalar(data_ + field_offset, val);
    78      return true;
    79    }
    80    template<typename T> bool SetField(voffset_t field, T val) {
    81      auto field_offset = GetOptionalFieldOffset(field);
    82      if (!field_offset) return false;
    83      WriteScalar(data_ + field_offset, val);
    84      return true;
    85    }
    86  
    87    bool SetPointer(voffset_t field, const uint8_t *val) {
    88      auto field_offset = GetOptionalFieldOffset(field);
    89      if (!field_offset) return false;
    90      WriteScalar(data_ + field_offset,
    91                  static_cast<uoffset_t>(val - (data_ + field_offset)));
    92      return true;
    93    }
    94  
    95    uint8_t *GetAddressOf(voffset_t field) {
    96      auto field_offset = GetOptionalFieldOffset(field);
    97      return field_offset ? data_ + field_offset : nullptr;
    98    }
    99    const uint8_t *GetAddressOf(voffset_t field) const {
   100      return const_cast<Table *>(this)->GetAddressOf(field);
   101    }
   102  
   103    bool CheckField(voffset_t field) const {
   104      return GetOptionalFieldOffset(field) != 0;
   105    }
   106  
   107    // Verify the vtable of this table.
   108    // Call this once per table, followed by VerifyField once per field.
   109    bool VerifyTableStart(Verifier &verifier) const {
   110      return verifier.VerifyTableStart(data_);
   111    }
   112  
   113    // Verify a particular field.
   114    template<typename T>
   115    bool VerifyField(const Verifier &verifier, voffset_t field,
   116                     size_t align) const {
   117      // Calling GetOptionalFieldOffset should be safe now thanks to
   118      // VerifyTable().
   119      auto field_offset = GetOptionalFieldOffset(field);
   120      // Check the actual field.
   121      return !field_offset || verifier.VerifyField<T>(data_, field_offset, align);
   122    }
   123  
   124    // VerifyField for required fields.
   125    template<typename T>
   126    bool VerifyFieldRequired(const Verifier &verifier, voffset_t field,
   127                             size_t align) const {
   128      auto field_offset = GetOptionalFieldOffset(field);
   129      return verifier.Check(field_offset != 0) &&
   130             verifier.VerifyField<T>(data_, field_offset, align);
   131    }
   132  
   133    // Versions for offsets.
   134    bool VerifyOffset(const Verifier &verifier, voffset_t field) const {
   135      auto field_offset = GetOptionalFieldOffset(field);
   136      return !field_offset || verifier.VerifyOffset(data_, field_offset);
   137    }
   138  
   139    bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const {
   140      auto field_offset = GetOptionalFieldOffset(field);
   141      return verifier.Check(field_offset != 0) &&
   142             verifier.VerifyOffset(data_, field_offset);
   143    }
   144  
   145   private:
   146    // private constructor & copy constructor: you obtain instances of this
   147    // class by pointing to existing data only
   148    Table();
   149    Table(const Table &other);
   150    Table &operator=(const Table &);
   151  
   152    uint8_t data_[1];
   153  };
   154  
   155  // This specialization allows avoiding warnings like:
   156  // MSVC C4800: type: forcing value to bool 'true' or 'false'.
   157  template<>
   158  inline flatbuffers::Optional<bool> Table::GetOptional<uint8_t, bool>(
   159      voffset_t field) const {
   160    auto field_offset = GetOptionalFieldOffset(field);
   161    auto p = data_ + field_offset;
   162    return field_offset ? Optional<bool>(ReadScalar<uint8_t>(p) != 0)
   163                        : Optional<bool>();
   164  }
   165  
   166  }  // namespace flatbuffers
   167  
   168  #endif  // FLATBUFFERS_TABLE_H_