mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-09 14:46:26 +00:00
Fix for FlexBuffers FBT_VECTOR_STRING size bit-width.
For details, test.cpp/FlexBuffersDeprecatedTest(), and also https://github.com/google/flatbuffers/issues/5627 Change-Id: I6e86e1138a5777e31055cfa2f79276d44732efbc
This commit is contained in:
@@ -65,7 +65,9 @@ enum Type {
|
||||
FBT_VECTOR_UINT = 12,
|
||||
FBT_VECTOR_FLOAT = 13,
|
||||
FBT_VECTOR_KEY = 14,
|
||||
FBT_VECTOR_STRING = 15,
|
||||
// DEPRECATED, use FBT_VECTOR or FBT_VECTOR_KEY instead.
|
||||
// Read test.cpp/FlexBuffersDeprecatedTest() for details on why.
|
||||
FBT_VECTOR_STRING_DEPRECATED = 15,
|
||||
FBT_VECTOR_INT2 = 16, // Typed tuple (no type table, no size field).
|
||||
FBT_VECTOR_UINT2 = 17,
|
||||
FBT_VECTOR_FLOAT2 = 18,
|
||||
@@ -88,7 +90,7 @@ inline bool IsTypedVectorElementType(Type t) {
|
||||
}
|
||||
|
||||
inline bool IsTypedVector(Type t) {
|
||||
return (t >= FBT_VECTOR_INT && t <= FBT_VECTOR_STRING) ||
|
||||
return (t >= FBT_VECTOR_INT && t <= FBT_VECTOR_STRING_DEPRECATED) ||
|
||||
t == FBT_VECTOR_BOOL;
|
||||
}
|
||||
|
||||
@@ -212,26 +214,40 @@ class Object {
|
||||
uint8_t byte_width_;
|
||||
};
|
||||
|
||||
// Stores size in `byte_width_` bytes before data_ pointer.
|
||||
// Object that has a size, obtained either from size prefix, or elsewhere.
|
||||
class Sized : public Object {
|
||||
public:
|
||||
Sized(const uint8_t *data, uint8_t byte_width) : Object(data, byte_width) {}
|
||||
size_t size() const {
|
||||
// Size prefix.
|
||||
Sized(const uint8_t *data, uint8_t byte_width) :
|
||||
Object(data, byte_width), size_(read_size()) {}
|
||||
// Manual size.
|
||||
Sized(const uint8_t *data, uint8_t byte_width, size_t sz) :
|
||||
Object(data, byte_width), size_(sz) {}
|
||||
size_t size() const { return size_; }
|
||||
// Access size stored in `byte_width_` bytes before data_ pointer.
|
||||
size_t read_size() const {
|
||||
return static_cast<size_t>(ReadUInt64(data_ - byte_width_, byte_width_));
|
||||
}
|
||||
protected:
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
class String : public Sized {
|
||||
public:
|
||||
String(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {}
|
||||
// Size prefix.
|
||||
String(const uint8_t *data, uint8_t byte_width)
|
||||
: Sized(data, byte_width) {}
|
||||
// Manual size.
|
||||
String(const uint8_t *data, uint8_t byte_width, size_t sz)
|
||||
: Sized(data, byte_width, sz) {}
|
||||
|
||||
size_t length() const { return size(); }
|
||||
const char *c_str() const { return reinterpret_cast<const char *>(data_); }
|
||||
std::string str() const { return std::string(c_str(), length()); }
|
||||
std::string str() const { return std::string(c_str(), size()); }
|
||||
|
||||
static String EmptyString() {
|
||||
static const uint8_t empty_string[] = { 0 /*len*/, 0 /*terminator*/ };
|
||||
return String(empty_string + 1, 1);
|
||||
static const char *empty_string = "";
|
||||
return String(reinterpret_cast<const uint8_t *>(empty_string), 1, 0);
|
||||
}
|
||||
bool IsTheEmptyString() const { return data_ == EmptyString().data_; }
|
||||
};
|
||||
@@ -279,6 +295,7 @@ class TypedVector : public Sized {
|
||||
|
||||
Type ElementType() { return type_; }
|
||||
|
||||
friend Reference;
|
||||
private:
|
||||
Type type_;
|
||||
|
||||
@@ -487,17 +504,22 @@ class Reference {
|
||||
float AsFloat() const { return static_cast<float>(AsDouble()); }
|
||||
|
||||
const char *AsKey() const {
|
||||
if (type_ == FBT_KEY) {
|
||||
if (type_ == FBT_KEY || type_ == FBT_STRING) {
|
||||
return reinterpret_cast<const char *>(Indirect());
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// This function returns the empty string if you try to read a not-string.
|
||||
// This function returns the empty string if you try to read something that
|
||||
// is not a string or key.
|
||||
String AsString() const {
|
||||
if (type_ == FBT_STRING) {
|
||||
return String(Indirect(), byte_width_);
|
||||
} else if (type_ == FBT_KEY) {
|
||||
auto key = Indirect();
|
||||
return String(key, byte_width_,
|
||||
strlen(reinterpret_cast<const char *>(key)));
|
||||
} else {
|
||||
return String::EmptyString();
|
||||
}
|
||||
@@ -588,8 +610,18 @@ class Reference {
|
||||
|
||||
TypedVector AsTypedVector() const {
|
||||
if (IsTypedVector()) {
|
||||
return TypedVector(Indirect(), byte_width_,
|
||||
ToTypedVectorElementType(type_));
|
||||
auto tv = TypedVector(Indirect(), byte_width_,
|
||||
ToTypedVectorElementType(type_));
|
||||
if (tv.type_ == FBT_STRING) {
|
||||
// These can't be accessed as strings, since we don't know the bit-width
|
||||
// of the size field, see the declaration of
|
||||
// FBT_VECTOR_STRING_DEPRECATED above for details.
|
||||
// We change the type here to be keys, which are a subtype of strings,
|
||||
// and will ignore the size field. This will truncate strings with
|
||||
// embedded nulls.
|
||||
tv.type_ = FBT_KEY;
|
||||
}
|
||||
return tv;
|
||||
} else {
|
||||
return TypedVector::EmptyTypedVector();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user