xref: /aosp_15_r20/external/flatbuffers/include/flatbuffers/verifier.h (revision 890232f25432b36107d06881e0a25aaa6b473652)
1*890232f2SAndroid Build Coastguard Worker /*
2*890232f2SAndroid Build Coastguard Worker  * Copyright 2021 Google Inc. All rights reserved.
3*890232f2SAndroid Build Coastguard Worker  *
4*890232f2SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*890232f2SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*890232f2SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*890232f2SAndroid Build Coastguard Worker  *
8*890232f2SAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
9*890232f2SAndroid Build Coastguard Worker  *
10*890232f2SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*890232f2SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*890232f2SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*890232f2SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*890232f2SAndroid Build Coastguard Worker  * limitations under the License.
15*890232f2SAndroid Build Coastguard Worker  */
16*890232f2SAndroid Build Coastguard Worker 
17*890232f2SAndroid Build Coastguard Worker #ifndef FLATBUFFERS_VERIFIER_H_
18*890232f2SAndroid Build Coastguard Worker #define FLATBUFFERS_VERIFIER_H_
19*890232f2SAndroid Build Coastguard Worker 
20*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/base.h"
21*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/vector.h"
22*890232f2SAndroid Build Coastguard Worker 
23*890232f2SAndroid Build Coastguard Worker namespace flatbuffers {
24*890232f2SAndroid Build Coastguard Worker 
25*890232f2SAndroid Build Coastguard Worker // Helper class to verify the integrity of a FlatBuffer
26*890232f2SAndroid Build Coastguard Worker class Verifier FLATBUFFERS_FINAL_CLASS {
27*890232f2SAndroid Build Coastguard Worker  public:
28*890232f2SAndroid Build Coastguard Worker   Verifier(const uint8_t *const buf, const size_t buf_len,
29*890232f2SAndroid Build Coastguard Worker            const uoffset_t _max_depth = 64,
30*890232f2SAndroid Build Coastguard Worker            const uoffset_t _max_tables = 1000000,
31*890232f2SAndroid Build Coastguard Worker            const bool _check_alignment = true)
buf_(buf)32*890232f2SAndroid Build Coastguard Worker       : buf_(buf),
33*890232f2SAndroid Build Coastguard Worker         size_(buf_len),
34*890232f2SAndroid Build Coastguard Worker         max_depth_(_max_depth),
35*890232f2SAndroid Build Coastguard Worker         max_tables_(_max_tables),
36*890232f2SAndroid Build Coastguard Worker         check_alignment_(_check_alignment),
37*890232f2SAndroid Build Coastguard Worker         upper_bound_(0),
38*890232f2SAndroid Build Coastguard Worker         depth_(0),
39*890232f2SAndroid Build Coastguard Worker         num_tables_(0),
40*890232f2SAndroid Build Coastguard Worker         flex_reuse_tracker_(nullptr) {
41*890232f2SAndroid Build Coastguard Worker     FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
42*890232f2SAndroid Build Coastguard Worker   }
43*890232f2SAndroid Build Coastguard Worker 
44*890232f2SAndroid Build Coastguard Worker   // Central location where any verification failures register.
Check(const bool ok)45*890232f2SAndroid Build Coastguard Worker   bool Check(const bool ok) const {
46*890232f2SAndroid Build Coastguard Worker     // clang-format off
47*890232f2SAndroid Build Coastguard Worker     #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
48*890232f2SAndroid Build Coastguard Worker       FLATBUFFERS_ASSERT(ok);
49*890232f2SAndroid Build Coastguard Worker     #endif
50*890232f2SAndroid Build Coastguard Worker     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
51*890232f2SAndroid Build Coastguard Worker       if (!ok)
52*890232f2SAndroid Build Coastguard Worker         upper_bound_ = 0;
53*890232f2SAndroid Build Coastguard Worker     #endif
54*890232f2SAndroid Build Coastguard Worker     // clang-format on
55*890232f2SAndroid Build Coastguard Worker     return ok;
56*890232f2SAndroid Build Coastguard Worker   }
57*890232f2SAndroid Build Coastguard Worker 
58*890232f2SAndroid Build Coastguard Worker   // Verify any range within the buffer.
Verify(const size_t elem,const size_t elem_len)59*890232f2SAndroid Build Coastguard Worker   bool Verify(const size_t elem, const size_t elem_len) const {
60*890232f2SAndroid Build Coastguard Worker     // clang-format off
61*890232f2SAndroid Build Coastguard Worker     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
62*890232f2SAndroid Build Coastguard Worker       auto upper_bound = elem + elem_len;
63*890232f2SAndroid Build Coastguard Worker       if (upper_bound_ < upper_bound)
64*890232f2SAndroid Build Coastguard Worker         upper_bound_ =  upper_bound;
65*890232f2SAndroid Build Coastguard Worker     #endif
66*890232f2SAndroid Build Coastguard Worker     // clang-format on
67*890232f2SAndroid Build Coastguard Worker     return Check(elem_len < size_ && elem <= size_ - elem_len);
68*890232f2SAndroid Build Coastguard Worker   }
69*890232f2SAndroid Build Coastguard Worker 
VerifyAlignment(const size_t elem,const size_t align)70*890232f2SAndroid Build Coastguard Worker   bool VerifyAlignment(const size_t elem, const size_t align) const {
71*890232f2SAndroid Build Coastguard Worker     return Check((elem & (align - 1)) == 0 || !check_alignment_);
72*890232f2SAndroid Build Coastguard Worker   }
73*890232f2SAndroid Build Coastguard Worker 
74*890232f2SAndroid Build Coastguard Worker   // Verify a range indicated by sizeof(T).
Verify(const size_t elem)75*890232f2SAndroid Build Coastguard Worker   template<typename T> bool Verify(const size_t elem) const {
76*890232f2SAndroid Build Coastguard Worker     return VerifyAlignment(elem, sizeof(T)) && Verify(elem, sizeof(T));
77*890232f2SAndroid Build Coastguard Worker   }
78*890232f2SAndroid Build Coastguard Worker 
VerifyFromPointer(const uint8_t * const p,const size_t len)79*890232f2SAndroid Build Coastguard Worker   bool VerifyFromPointer(const uint8_t *const p, const size_t len) {
80*890232f2SAndroid Build Coastguard Worker     return Verify(static_cast<size_t>(p - buf_), len);
81*890232f2SAndroid Build Coastguard Worker   }
82*890232f2SAndroid Build Coastguard Worker 
83*890232f2SAndroid Build Coastguard Worker   // Verify relative to a known-good base pointer.
VerifyFieldStruct(const uint8_t * const base,const voffset_t elem_off,const size_t elem_len,const size_t align)84*890232f2SAndroid Build Coastguard Worker   bool VerifyFieldStruct(const uint8_t *const base, const voffset_t elem_off,
85*890232f2SAndroid Build Coastguard Worker                          const size_t elem_len, const size_t align) const {
86*890232f2SAndroid Build Coastguard Worker     const auto f = static_cast<size_t>(base - buf_) + elem_off;
87*890232f2SAndroid Build Coastguard Worker     return VerifyAlignment(f, align) && Verify(f, elem_len);
88*890232f2SAndroid Build Coastguard Worker   }
89*890232f2SAndroid Build Coastguard Worker 
90*890232f2SAndroid Build Coastguard Worker   template<typename T>
VerifyField(const uint8_t * const base,const voffset_t elem_off,const size_t align)91*890232f2SAndroid Build Coastguard Worker   bool VerifyField(const uint8_t *const base, const voffset_t elem_off,
92*890232f2SAndroid Build Coastguard Worker                    const size_t align) const {
93*890232f2SAndroid Build Coastguard Worker     const auto f = static_cast<size_t>(base - buf_) + elem_off;
94*890232f2SAndroid Build Coastguard Worker     return VerifyAlignment(f, align) && Verify(f, sizeof(T));
95*890232f2SAndroid Build Coastguard Worker   }
96*890232f2SAndroid Build Coastguard Worker 
97*890232f2SAndroid Build Coastguard Worker   // Verify a pointer (may be NULL) of a table type.
VerifyTable(const T * const table)98*890232f2SAndroid Build Coastguard Worker   template<typename T> bool VerifyTable(const T *const table) {
99*890232f2SAndroid Build Coastguard Worker     return !table || table->Verify(*this);
100*890232f2SAndroid Build Coastguard Worker   }
101*890232f2SAndroid Build Coastguard Worker 
102*890232f2SAndroid Build Coastguard Worker   // Verify a pointer (may be NULL) of any vector type.
VerifyVector(const Vector<T> * const vec)103*890232f2SAndroid Build Coastguard Worker   template<typename T> bool VerifyVector(const Vector<T> *const vec) const {
104*890232f2SAndroid Build Coastguard Worker     return !vec || VerifyVectorOrString(reinterpret_cast<const uint8_t *>(vec),
105*890232f2SAndroid Build Coastguard Worker                                         sizeof(T));
106*890232f2SAndroid Build Coastguard Worker   }
107*890232f2SAndroid Build Coastguard Worker 
108*890232f2SAndroid Build Coastguard Worker   // Verify a pointer (may be NULL) of a vector to struct.
109*890232f2SAndroid Build Coastguard Worker   template<typename T>
VerifyVector(const Vector<const T * > * const vec)110*890232f2SAndroid Build Coastguard Worker   bool VerifyVector(const Vector<const T *> *const vec) const {
111*890232f2SAndroid Build Coastguard Worker     return VerifyVector(reinterpret_cast<const Vector<T> *>(vec));
112*890232f2SAndroid Build Coastguard Worker   }
113*890232f2SAndroid Build Coastguard Worker 
114*890232f2SAndroid Build Coastguard Worker   // Verify a pointer (may be NULL) to string.
VerifyString(const String * const str)115*890232f2SAndroid Build Coastguard Worker   bool VerifyString(const String *const str) const {
116*890232f2SAndroid Build Coastguard Worker     size_t end;
117*890232f2SAndroid Build Coastguard Worker     return !str || (VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str),
118*890232f2SAndroid Build Coastguard Worker                                          1, &end) &&
119*890232f2SAndroid Build Coastguard Worker                     Verify(end, 1) &&           // Must have terminator
120*890232f2SAndroid Build Coastguard Worker                     Check(buf_[end] == '\0'));  // Terminating byte must be 0.
121*890232f2SAndroid Build Coastguard Worker   }
122*890232f2SAndroid Build Coastguard Worker 
123*890232f2SAndroid Build Coastguard Worker   // Common code between vectors and strings.
124*890232f2SAndroid Build Coastguard Worker   bool VerifyVectorOrString(const uint8_t *const vec, const size_t elem_size,
125*890232f2SAndroid Build Coastguard Worker                             size_t *const end = nullptr) const {
126*890232f2SAndroid Build Coastguard Worker     const auto veco = static_cast<size_t>(vec - buf_);
127*890232f2SAndroid Build Coastguard Worker     // Check we can read the size field.
128*890232f2SAndroid Build Coastguard Worker     if (!Verify<uoffset_t>(veco)) return false;
129*890232f2SAndroid Build Coastguard Worker     // Check the whole array. If this is a string, the byte past the array
130*890232f2SAndroid Build Coastguard Worker     // must be 0.
131*890232f2SAndroid Build Coastguard Worker     const auto size = ReadScalar<uoffset_t>(vec);
132*890232f2SAndroid Build Coastguard Worker     const auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
133*890232f2SAndroid Build Coastguard Worker     if (!Check(size < max_elems))
134*890232f2SAndroid Build Coastguard Worker       return false;  // Protect against byte_size overflowing.
135*890232f2SAndroid Build Coastguard Worker     const auto byte_size = sizeof(size) + elem_size * size;
136*890232f2SAndroid Build Coastguard Worker     if (end) *end = veco + byte_size;
137*890232f2SAndroid Build Coastguard Worker     return Verify(veco, byte_size);
138*890232f2SAndroid Build Coastguard Worker   }
139*890232f2SAndroid Build Coastguard Worker 
140*890232f2SAndroid Build Coastguard Worker   // Special case for string contents, after the above has been called.
VerifyVectorOfStrings(const Vector<Offset<String>> * const vec)141*890232f2SAndroid Build Coastguard Worker   bool VerifyVectorOfStrings(const Vector<Offset<String>> *const vec) const {
142*890232f2SAndroid Build Coastguard Worker     if (vec) {
143*890232f2SAndroid Build Coastguard Worker       for (uoffset_t i = 0; i < vec->size(); i++) {
144*890232f2SAndroid Build Coastguard Worker         if (!VerifyString(vec->Get(i))) return false;
145*890232f2SAndroid Build Coastguard Worker       }
146*890232f2SAndroid Build Coastguard Worker     }
147*890232f2SAndroid Build Coastguard Worker     return true;
148*890232f2SAndroid Build Coastguard Worker   }
149*890232f2SAndroid Build Coastguard Worker 
150*890232f2SAndroid Build Coastguard Worker   // Special case for table contents, after the above has been called.
151*890232f2SAndroid Build Coastguard Worker   template<typename T>
VerifyVectorOfTables(const Vector<Offset<T>> * const vec)152*890232f2SAndroid Build Coastguard Worker   bool VerifyVectorOfTables(const Vector<Offset<T>> *const vec) {
153*890232f2SAndroid Build Coastguard Worker     if (vec) {
154*890232f2SAndroid Build Coastguard Worker       for (uoffset_t i = 0; i < vec->size(); i++) {
155*890232f2SAndroid Build Coastguard Worker         if (!vec->Get(i)->Verify(*this)) return false;
156*890232f2SAndroid Build Coastguard Worker       }
157*890232f2SAndroid Build Coastguard Worker     }
158*890232f2SAndroid Build Coastguard Worker     return true;
159*890232f2SAndroid Build Coastguard Worker   }
160*890232f2SAndroid Build Coastguard Worker 
VerifyTableStart(const uint8_t * const table)161*890232f2SAndroid Build Coastguard Worker   __supress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart(
162*890232f2SAndroid Build Coastguard Worker       const uint8_t *const table) {
163*890232f2SAndroid Build Coastguard Worker     // Check the vtable offset.
164*890232f2SAndroid Build Coastguard Worker     const auto tableo = static_cast<size_t>(table - buf_);
165*890232f2SAndroid Build Coastguard Worker     if (!Verify<soffset_t>(tableo)) return false;
166*890232f2SAndroid Build Coastguard Worker     // This offset may be signed, but doing the subtraction unsigned always
167*890232f2SAndroid Build Coastguard Worker     // gives the result we want.
168*890232f2SAndroid Build Coastguard Worker     const auto vtableo =
169*890232f2SAndroid Build Coastguard Worker         tableo - static_cast<size_t>(ReadScalar<soffset_t>(table));
170*890232f2SAndroid Build Coastguard Worker     // Check the vtable size field, then check vtable fits in its entirety.
171*890232f2SAndroid Build Coastguard Worker     if (!(VerifyComplexity() && Verify<voffset_t>(vtableo) &&
172*890232f2SAndroid Build Coastguard Worker           VerifyAlignment(ReadScalar<voffset_t>(buf_ + vtableo),
173*890232f2SAndroid Build Coastguard Worker                           sizeof(voffset_t))))
174*890232f2SAndroid Build Coastguard Worker       return false;
175*890232f2SAndroid Build Coastguard Worker     const auto vsize = ReadScalar<voffset_t>(buf_ + vtableo);
176*890232f2SAndroid Build Coastguard Worker     return Check((vsize & 1) == 0) && Verify(vtableo, vsize);
177*890232f2SAndroid Build Coastguard Worker   }
178*890232f2SAndroid Build Coastguard Worker 
179*890232f2SAndroid Build Coastguard Worker   template<typename T>
VerifyBufferFromStart(const char * const identifier,const size_t start)180*890232f2SAndroid Build Coastguard Worker   bool VerifyBufferFromStart(const char *const identifier, const size_t start) {
181*890232f2SAndroid Build Coastguard Worker     // Buffers have to be of some size to be valid. The reason it is a runtime
182*890232f2SAndroid Build Coastguard Worker     // check instead of static_assert, is that nested flatbuffers go through
183*890232f2SAndroid Build Coastguard Worker     // this call and their size is determined at runtime.
184*890232f2SAndroid Build Coastguard Worker     if (!Check(size_ >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false;
185*890232f2SAndroid Build Coastguard Worker 
186*890232f2SAndroid Build Coastguard Worker     // If an identifier is provided, check that we have a buffer
187*890232f2SAndroid Build Coastguard Worker     if (identifier && !Check((size_ >= 2 * sizeof(flatbuffers::uoffset_t) &&
188*890232f2SAndroid Build Coastguard Worker                               BufferHasIdentifier(buf_ + start, identifier)))) {
189*890232f2SAndroid Build Coastguard Worker       return false;
190*890232f2SAndroid Build Coastguard Worker     }
191*890232f2SAndroid Build Coastguard Worker 
192*890232f2SAndroid Build Coastguard Worker     // Call T::Verify, which must be in the generated code for this type.
193*890232f2SAndroid Build Coastguard Worker     const auto o = VerifyOffset(start);
194*890232f2SAndroid Build Coastguard Worker     return Check(o != 0) &&
195*890232f2SAndroid Build Coastguard Worker            reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this)
196*890232f2SAndroid Build Coastguard Worker     // clang-format off
197*890232f2SAndroid Build Coastguard Worker     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
198*890232f2SAndroid Build Coastguard Worker            && GetComputedSize()
199*890232f2SAndroid Build Coastguard Worker     #endif
200*890232f2SAndroid Build Coastguard Worker         ;
201*890232f2SAndroid Build Coastguard Worker     // clang-format on
202*890232f2SAndroid Build Coastguard Worker   }
203*890232f2SAndroid Build Coastguard Worker 
204*890232f2SAndroid Build Coastguard Worker   template<typename T>
VerifyNestedFlatBuffer(const Vector<uint8_t> * const buf,const char * const identifier)205*890232f2SAndroid Build Coastguard Worker   bool VerifyNestedFlatBuffer(const Vector<uint8_t> *const buf,
206*890232f2SAndroid Build Coastguard Worker                               const char *const identifier) {
207*890232f2SAndroid Build Coastguard Worker     // An empty buffer is OK as it indicates not present.
208*890232f2SAndroid Build Coastguard Worker     if (!buf) return true;
209*890232f2SAndroid Build Coastguard Worker 
210*890232f2SAndroid Build Coastguard Worker     // If there is a nested buffer, it must be greater than the min size.
211*890232f2SAndroid Build Coastguard Worker     if(!Check(buf->size() >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false;
212*890232f2SAndroid Build Coastguard Worker 
213*890232f2SAndroid Build Coastguard Worker     Verifier nested_verifier(buf->data(), buf->size());
214*890232f2SAndroid Build Coastguard Worker     return nested_verifier.VerifyBuffer<T>(identifier);
215*890232f2SAndroid Build Coastguard Worker   }
216*890232f2SAndroid Build Coastguard Worker 
217*890232f2SAndroid Build Coastguard Worker   // Verify this whole buffer, starting with root type T.
VerifyBuffer()218*890232f2SAndroid Build Coastguard Worker   template<typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); }
219*890232f2SAndroid Build Coastguard Worker 
VerifyBuffer(const char * const identifier)220*890232f2SAndroid Build Coastguard Worker   template<typename T> bool VerifyBuffer(const char *const identifier) {
221*890232f2SAndroid Build Coastguard Worker     return VerifyBufferFromStart<T>(identifier, 0);
222*890232f2SAndroid Build Coastguard Worker   }
223*890232f2SAndroid Build Coastguard Worker 
224*890232f2SAndroid Build Coastguard Worker   template<typename T>
VerifySizePrefixedBuffer(const char * const identifier)225*890232f2SAndroid Build Coastguard Worker   bool VerifySizePrefixedBuffer(const char *const identifier) {
226*890232f2SAndroid Build Coastguard Worker     return Verify<uoffset_t>(0U) &&
227*890232f2SAndroid Build Coastguard Worker            Check(ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t)) &&
228*890232f2SAndroid Build Coastguard Worker            VerifyBufferFromStart<T>(identifier, sizeof(uoffset_t));
229*890232f2SAndroid Build Coastguard Worker   }
230*890232f2SAndroid Build Coastguard Worker 
VerifyOffset(const size_t start)231*890232f2SAndroid Build Coastguard Worker   uoffset_t VerifyOffset(const size_t start) const {
232*890232f2SAndroid Build Coastguard Worker     if (!Verify<uoffset_t>(start)) return 0;
233*890232f2SAndroid Build Coastguard Worker     const auto o = ReadScalar<uoffset_t>(buf_ + start);
234*890232f2SAndroid Build Coastguard Worker     // May not point to itself.
235*890232f2SAndroid Build Coastguard Worker     if (!Check(o != 0)) return 0;
236*890232f2SAndroid Build Coastguard Worker     // Can't wrap around / buffers are max 2GB.
237*890232f2SAndroid Build Coastguard Worker     if (!Check(static_cast<soffset_t>(o) >= 0)) return 0;
238*890232f2SAndroid Build Coastguard Worker     // Must be inside the buffer to create a pointer from it (pointer outside
239*890232f2SAndroid Build Coastguard Worker     // buffer is UB).
240*890232f2SAndroid Build Coastguard Worker     if (!Verify(start + o, 1)) return 0;
241*890232f2SAndroid Build Coastguard Worker     return o;
242*890232f2SAndroid Build Coastguard Worker   }
243*890232f2SAndroid Build Coastguard Worker 
VerifyOffset(const uint8_t * const base,const voffset_t start)244*890232f2SAndroid Build Coastguard Worker   uoffset_t VerifyOffset(const uint8_t *const base,
245*890232f2SAndroid Build Coastguard Worker                          const voffset_t start) const {
246*890232f2SAndroid Build Coastguard Worker     return VerifyOffset(static_cast<size_t>(base - buf_) + start);
247*890232f2SAndroid Build Coastguard Worker   }
248*890232f2SAndroid Build Coastguard Worker 
249*890232f2SAndroid Build Coastguard Worker   // Called at the start of a table to increase counters measuring data
250*890232f2SAndroid Build Coastguard Worker   // structure depth and amount, and possibly bails out with false if
251*890232f2SAndroid Build Coastguard Worker   // limits set by the constructor have been hit. Needs to be balanced
252*890232f2SAndroid Build Coastguard Worker   // with EndTable().
VerifyComplexity()253*890232f2SAndroid Build Coastguard Worker   bool VerifyComplexity() {
254*890232f2SAndroid Build Coastguard Worker     depth_++;
255*890232f2SAndroid Build Coastguard Worker     num_tables_++;
256*890232f2SAndroid Build Coastguard Worker     return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
257*890232f2SAndroid Build Coastguard Worker   }
258*890232f2SAndroid Build Coastguard Worker 
259*890232f2SAndroid Build Coastguard Worker   // Called at the end of a table to pop the depth count.
EndTable()260*890232f2SAndroid Build Coastguard Worker   bool EndTable() {
261*890232f2SAndroid Build Coastguard Worker     depth_--;
262*890232f2SAndroid Build Coastguard Worker     return true;
263*890232f2SAndroid Build Coastguard Worker   }
264*890232f2SAndroid Build Coastguard Worker 
265*890232f2SAndroid Build Coastguard Worker   // Returns the message size in bytes
GetComputedSize()266*890232f2SAndroid Build Coastguard Worker   size_t GetComputedSize() const {
267*890232f2SAndroid Build Coastguard Worker     // clang-format off
268*890232f2SAndroid Build Coastguard Worker     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
269*890232f2SAndroid Build Coastguard Worker       uintptr_t size = upper_bound_;
270*890232f2SAndroid Build Coastguard Worker       // Align the size to uoffset_t
271*890232f2SAndroid Build Coastguard Worker       size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
272*890232f2SAndroid Build Coastguard Worker       return (size > size_) ?  0 : size;
273*890232f2SAndroid Build Coastguard Worker     #else
274*890232f2SAndroid Build Coastguard Worker       // Must turn on FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE for this to work.
275*890232f2SAndroid Build Coastguard Worker       (void)upper_bound_;
276*890232f2SAndroid Build Coastguard Worker       FLATBUFFERS_ASSERT(false);
277*890232f2SAndroid Build Coastguard Worker       return 0;
278*890232f2SAndroid Build Coastguard Worker     #endif
279*890232f2SAndroid Build Coastguard Worker     // clang-format on
280*890232f2SAndroid Build Coastguard Worker   }
281*890232f2SAndroid Build Coastguard Worker 
GetFlexReuseTracker()282*890232f2SAndroid Build Coastguard Worker   std::vector<uint8_t> *GetFlexReuseTracker() { return flex_reuse_tracker_; }
283*890232f2SAndroid Build Coastguard Worker 
SetFlexReuseTracker(std::vector<uint8_t> * const rt)284*890232f2SAndroid Build Coastguard Worker   void SetFlexReuseTracker(std::vector<uint8_t> *const rt) {
285*890232f2SAndroid Build Coastguard Worker     flex_reuse_tracker_ = rt;
286*890232f2SAndroid Build Coastguard Worker   }
287*890232f2SAndroid Build Coastguard Worker 
288*890232f2SAndroid Build Coastguard Worker  private:
289*890232f2SAndroid Build Coastguard Worker   const uint8_t *buf_;
290*890232f2SAndroid Build Coastguard Worker   const size_t size_;
291*890232f2SAndroid Build Coastguard Worker   const uoffset_t max_depth_;
292*890232f2SAndroid Build Coastguard Worker   const uoffset_t max_tables_;
293*890232f2SAndroid Build Coastguard Worker   const bool check_alignment_;
294*890232f2SAndroid Build Coastguard Worker 
295*890232f2SAndroid Build Coastguard Worker   mutable size_t upper_bound_;
296*890232f2SAndroid Build Coastguard Worker 
297*890232f2SAndroid Build Coastguard Worker   uoffset_t depth_;
298*890232f2SAndroid Build Coastguard Worker   uoffset_t num_tables_;
299*890232f2SAndroid Build Coastguard Worker   std::vector<uint8_t> *flex_reuse_tracker_;
300*890232f2SAndroid Build Coastguard Worker };
301*890232f2SAndroid Build Coastguard Worker 
302*890232f2SAndroid Build Coastguard Worker }  // namespace flatbuffers
303*890232f2SAndroid Build Coastguard Worker 
304*890232f2SAndroid Build Coastguard Worker #endif  // FLATBUFFERS_VERIFIER_H_
305