From 5ed02dc04a7b5ea8995ad044ae9b04c55e613119 Mon Sep 17 00:00:00 2001 From: are-you-tilted-already <165279732+are-you-tilted-already@users.noreply.github.com> Date: Wed, 5 Nov 2025 00:47:44 +0300 Subject: [PATCH] Prevent `make_span` from working with vectors and arrays of pointers (#8735) * Prevent `make_span` from working with vectors and arrays of pointers * support `make_structs_span` for little-endian * fix build: add the required parentheses --------- Co-authored-by: Wouter van Oortmerssen --- include/flatbuffers/array.h | 7 ++++--- include/flatbuffers/vector.h | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/include/flatbuffers/array.h b/include/flatbuffers/array.h index 914f479aa..a903139e6 100644 --- a/include/flatbuffers/array.h +++ b/include/flatbuffers/array.h @@ -39,10 +39,11 @@ class Array { typedef VectorConstIterator const_iterator; typedef VectorReverseIterator const_reverse_iterator; - // If T is a LE-scalar or a struct (!scalar_tag::value). + // If T is a non-pointer and a LE-scalar or a struct (!scalar_tag::value). static FLATBUFFERS_CONSTEXPR bool is_span_observable = - (scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1)) || - !scalar_tag::value; + !std::is_pointer::value && + ((scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1)) || + !scalar_tag::value); FLATBUFFERS_CONSTEXPR uint16_t size() const { return length; } diff --git a/include/flatbuffers/vector.h b/include/flatbuffers/vector.h index e967e5344..7d20d189f 100644 --- a/include/flatbuffers/vector.h +++ b/include/flatbuffers/vector.h @@ -172,7 +172,8 @@ class Vector { scalar_tag; static FLATBUFFERS_CONSTEXPR bool is_span_observable = - scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1); + scalar_tag::value && !std::is_pointer::value && + (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1); SizeT size() const { return EndianScalar(length_); } @@ -359,6 +360,22 @@ FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_bytes_span( return span(vec.Data(), vec.size() * sizeof(U)); } +#if FLATBUFFERS_LITTLEENDIAN + +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_structs_span( + Vector& vec) FLATBUFFERS_NOEXCEPT { + return span(reinterpret_cast(vec.data()), vec.size()); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_structs_span( + const Vector& vec) FLATBUFFERS_NOEXCEPT { + return span(reinterpret_cast(vec.data()), vec.size()); +} + +#endif + // Convenient helper functions to get a span of any vector, regardless // of whether it is null or not (the field is not set). template @@ -377,6 +394,23 @@ FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_span( return ptr ? make_span(*ptr) : span(); } +#if FLATBUFFERS_LITTLEENDIAN + +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_structs_span( + Vector* ptr) FLATBUFFERS_NOEXCEPT { + return ptr ? make_span(*ptr) : span(); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_structs_span( + const Vector* ptr) FLATBUFFERS_NOEXCEPT { + return ptr ? make_span(*ptr) : span(); +} + +#endif + + // Represent a vector much like the template above, but in this case we // don't know what the element types are (used with reflection.h). class VectorOfAny {