github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/executor/_include/flatbuffers/buffer.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_BUFFER_H_ 18 #define FLATBUFFERS_BUFFER_H_ 19 20 #include "flatbuffers/base.h" 21 22 namespace flatbuffers { 23 24 // Wrapper for uoffset_t to allow safe template specialization. 25 // Value is allowed to be 0 to indicate a null object (see e.g. AddOffset). 26 template<typename T> struct Offset { 27 uoffset_t o; 28 Offset() : o(0) {} 29 Offset(uoffset_t _o) : o(_o) {} 30 Offset<void> Union() const { return Offset<void>(o); } 31 bool IsNull() const { return !o; } 32 }; 33 34 inline void EndianCheck() { 35 int endiantest = 1; 36 // If this fails, see FLATBUFFERS_LITTLEENDIAN above. 37 FLATBUFFERS_ASSERT(*reinterpret_cast<char *>(&endiantest) == 38 FLATBUFFERS_LITTLEENDIAN); 39 (void)endiantest; 40 } 41 42 template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() { 43 // clang-format off 44 #ifdef _MSC_VER 45 return __alignof(T); 46 #else 47 #ifndef alignof 48 return __alignof__(T); 49 #else 50 return alignof(T); 51 #endif 52 #endif 53 // clang-format on 54 } 55 56 // Lexicographically compare two strings (possibly containing nulls), and 57 // return true if the first is less than the second. 58 static inline bool StringLessThan(const char *a_data, uoffset_t a_size, 59 const char *b_data, uoffset_t b_size) { 60 const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size)); 61 return cmp == 0 ? a_size < b_size : cmp < 0; 62 } 63 64 // When we read serialized data from memory, in the case of most scalars, 65 // we want to just read T, but in the case of Offset, we want to actually 66 // perform the indirection and return a pointer. 67 // The template specialization below does just that. 68 // It is wrapped in a struct since function templates can't overload on the 69 // return type like this. 70 // The typedef is for the convenience of callers of this function 71 // (avoiding the need for a trailing return decltype) 72 template<typename T> struct IndirectHelper { 73 typedef T return_type; 74 typedef T mutable_return_type; 75 static const size_t element_stride = sizeof(T); 76 static return_type Read(const uint8_t *p, uoffset_t i) { 77 return EndianScalar((reinterpret_cast<const T *>(p))[i]); 78 } 79 }; 80 template<typename T> struct IndirectHelper<Offset<T>> { 81 typedef const T *return_type; 82 typedef T *mutable_return_type; 83 static const size_t element_stride = sizeof(uoffset_t); 84 static return_type Read(const uint8_t *p, uoffset_t i) { 85 p += i * sizeof(uoffset_t); 86 return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p)); 87 } 88 }; 89 template<typename T> struct IndirectHelper<const T *> { 90 typedef const T *return_type; 91 typedef T *mutable_return_type; 92 static const size_t element_stride = sizeof(T); 93 static return_type Read(const uint8_t *p, uoffset_t i) { 94 return reinterpret_cast<const T *>(p + i * sizeof(T)); 95 } 96 }; 97 98 /// @brief Get a pointer to the file_identifier section of the buffer. 99 /// @return Returns a const char pointer to the start of the file_identifier 100 /// characters in the buffer. The returned char * has length 101 /// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'. 102 /// This function is UNDEFINED for FlatBuffers whose schema does not include 103 /// a file_identifier (likely points at padding or the start of a the root 104 /// vtable). 105 inline const char *GetBufferIdentifier(const void *buf, 106 bool size_prefixed = false) { 107 return reinterpret_cast<const char *>(buf) + 108 ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t)); 109 } 110 111 // Helper to see if the identifier in a buffer has the expected value. 112 inline bool BufferHasIdentifier(const void *buf, const char *identifier, 113 bool size_prefixed = false) { 114 return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier, 115 flatbuffers::kFileIdentifierLength) == 0; 116 } 117 118 /// @cond FLATBUFFERS_INTERNAL 119 // Helpers to get a typed pointer to the root object contained in the buffer. 120 template<typename T> T *GetMutableRoot(void *buf) { 121 EndianCheck(); 122 return reinterpret_cast<T *>( 123 reinterpret_cast<uint8_t *>(buf) + 124 EndianScalar(*reinterpret_cast<uoffset_t *>(buf))); 125 } 126 127 template<typename T> T *GetMutableSizePrefixedRoot(void *buf) { 128 return GetMutableRoot<T>(reinterpret_cast<uint8_t *>(buf) + 129 sizeof(uoffset_t)); 130 } 131 132 template<typename T> const T *GetRoot(const void *buf) { 133 return GetMutableRoot<T>(const_cast<void *>(buf)); 134 } 135 136 template<typename T> const T *GetSizePrefixedRoot(const void *buf) { 137 return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(uoffset_t)); 138 } 139 140 } // namespace flatbuffers 141 142 #endif // FLATBUFFERS_BUFFER_H_