2323namespace flatbuffers {
2424
2525// Helper class to verify the integrity of a FlatBuffer
26- class Verifier FLATBUFFERS_FINAL_CLASS {
26+ template <bool TrackVerifierBufferSize>
27+ class VerifierTemplate FLATBUFFERS_FINAL_CLASS {
2728 public:
2829 struct Options {
2930 // The maximum nesting of tables and vectors before we call it invalid.
@@ -40,17 +41,18 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
4041 bool assert = false ;
4142 };
4243
43- explicit Verifier (const uint8_t *const buf, const size_t buf_len,
44- const Options &opts)
44+ explicit VerifierTemplate (const uint8_t *const buf, const size_t buf_len,
45+ const Options &opts)
4546 : buf_(buf), size_(buf_len), opts_(opts) {
4647 FLATBUFFERS_ASSERT (size_ < opts.max_size );
4748 }
4849
49- // Deprecated API, please construct with Verifier::Options.
50- Verifier (const uint8_t *const buf, const size_t buf_len,
51- const uoffset_t max_depth = 64 , const uoffset_t max_tables = 1000000 ,
52- const bool check_alignment = true )
53- : Verifier(buf, buf_len, [&] {
50+ // Deprecated API, please construct with VerifierTemplate::Options.
51+ VerifierTemplate (const uint8_t *const buf, const size_t buf_len,
52+ const uoffset_t max_depth = 64 ,
53+ const uoffset_t max_tables = 1000000 ,
54+ const bool check_alignment = true )
55+ : VerifierTemplate(buf, buf_len, [&] {
5456 Options opts;
5557 opts.max_depth = max_depth;
5658 opts.max_tables = max_tables;
@@ -62,25 +64,25 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
6264 bool Check (const bool ok) const {
6365 // clang-format off
6466 #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
65- if (opts_.assert ) { FLATBUFFERS_ASSERT (ok); }
66- #endif
67- #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
68- if (!ok)
69- upper_bound_ = 0 ;
67+ if (opts_.assert ) { FLATBUFFERS_ASSERT (ok); }
7068 #endif
7169 // clang-format on
70+ if (TrackVerifierBufferSize) {
71+ if (!ok) {
72+ upper_bound_ = 0 ;
73+ }
74+ }
7275 return ok;
7376 }
7477
7578 // Verify any range within the buffer.
7679 bool Verify (const size_t elem, const size_t elem_len) const {
77- // clang-format off
78- #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
80+ if (TrackVerifierBufferSize) {
7981 auto upper_bound = elem + elem_len;
80- if (upper_bound_ < upper_bound)
82+ if (upper_bound_ < upper_bound) {
8183 upper_bound_ = upper_bound;
82- # endif
83- // clang-format on
84+ }
85+ }
8486 return Check (elem_len < size_ && elem <= size_ - elem_len);
8587 }
8688
@@ -210,14 +212,14 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
210212
211213 // Call T::Verify, which must be in the generated code for this type.
212214 const auto o = VerifyOffset<uoffset_t >(start);
213- return Check (o != 0 ) &&
214- reinterpret_cast <const T *>(buf_ + start + o)->Verify (*this )
215- // clang-format off
216- # ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
217- && GetComputedSize ()
218- # endif
219- ;
220- // clang-format on
215+ if (! Check (o != 0 )) return false ;
216+ if (!( reinterpret_cast <const T *>(buf_ + start + o)->Verify (*this ))) {
217+ return false ;
218+ }
219+ if (TrackVerifierBufferSize) {
220+ if ( GetComputedSize () == 0 ) return false ;
221+ }
222+ return true ;
221223 }
222224
223225 template <typename T, int &..., typename SizeT>
@@ -232,7 +234,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
232234 // If there is a nested buffer, it must be greater than the min size.
233235 if (!Check (buf->size () >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false ;
234236
235- Verifier nested_verifier (buf->data (), buf->size (), opts_);
237+ VerifierTemplate<TrackVerifierBufferSize> nested_verifier (
238+ buf->data (), buf->size (), opts_);
236239 return nested_verifier.VerifyBuffer <T>(identifier);
237240 }
238241
@@ -286,21 +289,27 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
286289 return true ;
287290 }
288291
289- // Returns the message size in bytes
292+ // Returns the message size in bytes.
293+ //
294+ // This should only be called after first calling VerifyBuffer or
295+ // VerifySizePrefixedBuffer.
296+ //
297+ // This method should only be called for VerifierTemplate instances
298+ // where the TrackVerifierBufferSize template parameter is true,
299+ // i.e. for SizeVerifier. For instances where TrackVerifierBufferSize
300+ // is false, this fails at runtime or returns zero.
290301 size_t GetComputedSize () const {
291- // clang-format off
292- #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
302+ if (TrackVerifierBufferSize) {
293303 uintptr_t size = upper_bound_;
294304 // Align the size to uoffset_t
295305 size = (size - 1 + sizeof (uoffset_t )) & ~(sizeof (uoffset_t ) - 1 );
296306 return (size > size_) ? 0 : size;
297- #else
298- // Must turn on FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE for this to work.
299- (void )upper_bound_;
300- FLATBUFFERS_ASSERT (false );
301- return 0 ;
302- #endif
303- // clang-format on
307+ }
308+ // Must use SizeVerifier, or (deprecated) turn on
309+ // FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE, for this to work.
310+ (void )upper_bound_;
311+ FLATBUFFERS_ASSERT (false );
312+ return 0 ;
304313 }
305314
306315 std::vector<uint8_t > *GetFlexReuseTracker () { return flex_reuse_tracker_; }
@@ -323,10 +332,33 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
323332
324333// Specialization for 64-bit offsets.
325334template <>
326- inline size_t Verifier::VerifyOffset<uoffset64_t >(const size_t start) const {
335+ template <>
336+ inline size_t VerifierTemplate<false >::VerifyOffset<uoffset64_t >(
337+ const size_t start) const {
338+ return VerifyOffset<uoffset64_t , soffset64_t >(start);
339+ }
340+ template <>
341+ template <>
342+ inline size_t VerifierTemplate<true >::VerifyOffset<uoffset64_t >(
343+ const size_t start) const {
327344 return VerifyOffset<uoffset64_t , soffset64_t >(start);
328345}
329346
347+ // Instance of VerifierTemplate that supports GetComputedSize().
348+ using SizeVerifier = VerifierTemplate</* TrackVerifierBufferSize = */ true >;
349+
350+ // The FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE build configuration macro is
351+ // deprecated, and should not be defined, since it is easy to misuse in ways
352+ // that result in ODR violations. Rather than using Verifier and defining
353+ // FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE, please use SizeVerifier instead.
354+ #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE // Deprecated, see above.
355+ using Verifier = SizeVerifier;
356+ #else
357+ // Instance of VerifierTemplate that is slightly faster, but does not
358+ // support GetComputedSize().
359+ using Verifier = VerifierTemplate</* TrackVerifierBufferSize = */ false >;
360+ #endif
361+
330362} // namespace flatbuffers
331363
332364#endif // FLATBUFFERS_VERIFIER_H_
0 commit comments