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_