Fix serialization of std::vector (fix issue #3220)

Signed-off-by: Stefan Weil <sw@weilnetz.de>
This commit is contained in:
Stefan Weil 2021-01-12 21:23:14 +01:00
parent 9b15e65900
commit b0e46085f4
2 changed files with 39 additions and 29 deletions

View File

@ -73,6 +73,42 @@ TFile::~TFile() {
delete data_; delete data_;
} }
template <typename T>
bool TFile::DeSerialize(std::vector<T>& data) {
uint32_t size;
if (!DeSerialize(&size)) {
return false;
}
// Arbitrarily limit the number of elements to protect against bad data.
const uint32_t limit = 50000000;
assert(size <= limit);
if (size > limit) {
return false;
} else if (size > 0) {
// TODO: optimize.
data.reserve(size);
return DeSerialize(&data[0], size);
}
data.clear();
return true;
}
template <typename T>
bool TFile::Serialize(const std::vector<T>& data) {
uint32_t size = data.size();
if (!Serialize(&size)) {
return false;
} else if (size > 0) {
return Serialize(&data[0], size);
}
return true;
}
template bool TFile::DeSerialize(std::vector<double>& data);
template bool TFile::DeSerialize(std::vector<int32_t>& data);
template bool TFile::Serialize(const std::vector<double>& data);
template bool TFile::Serialize(const std::vector<int32_t>& data);
bool TFile::DeSerialize(std::vector<char>& data) { bool TFile::DeSerialize(std::vector<char>& data) {
uint32_t size; uint32_t size;
if (!DeSerialize(&size)) { if (!DeSerialize(&size)) {
@ -91,7 +127,7 @@ bool TFile::Serialize(const std::vector<char>& data) {
if (!Serialize(&size)) { if (!Serialize(&size)) {
return false; return false;
} else if (size > 0) { } else if (size > 0) {
return Serialize(&data[0], size); return Serialize(&data[0], size);
} }
return true; return true;
} }

View File

@ -86,6 +86,7 @@ class TESS_API TFile {
// Deserialize data. // Deserialize data.
bool DeSerialize(std::vector<char>& data); bool DeSerialize(std::vector<char>& data);
template <typename T> bool DeSerialize(std::vector<T>& data);
template <typename T> template <typename T>
bool DeSerialize(T *data, size_t count = 1) { bool DeSerialize(T *data, size_t count = 1) {
return FReadEndian(data, sizeof(T), count) == count; return FReadEndian(data, sizeof(T), count) == count;
@ -93,39 +94,12 @@ class TESS_API TFile {
// Serialize data. // Serialize data.
bool Serialize(const std::vector<char>& data); bool Serialize(const std::vector<char>& data);
template <typename T> bool Serialize(const std::vector<T>& data);
template <typename T> template <typename T>
bool Serialize(const T *data, size_t count = 1) { bool Serialize(const T *data, size_t count = 1) {
return FWrite(data, sizeof(T), count) == count; return FWrite(data, sizeof(T), count) == count;
} }
template <typename T>
bool Serialize(const std::vector<T>& data) {
auto size_used_ = data.size();
if (FWrite(&size_used_, sizeof(size_used_), 1) != 1) {
return false;
}
if (FWrite(data.data(), sizeof(T), size_used_) != size_used_) {
return false;
}
return true;
}
template <typename T>
bool DeSerialize(std::vector<T>& data) {
uint32_t reserved;
if (FReadEndian(&reserved, sizeof(reserved), 1) != 1) {
return false;
}
// Arbitrarily limit the number of elements to protect against bad data.
const uint32_t limit = 50000000;
//assert(reserved <= limit);
if (reserved > limit) {
return false;
}
data.reserve(reserved);
return FReadEndian(data.data(), sizeof(T), reserved) == reserved;
}
// Skip data. // Skip data.
bool Skip(size_t count); bool Skip(size_t count);