mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-11 15:19:19 +02:00
serialize: add LimitedVectorFormatter
This commit is contained in:
@@ -494,6 +494,7 @@ static inline Wrapper<Formatter, T&> Using(T&& t) { return Wrapper<Formatter, T&
|
||||
#define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
|
||||
#define COMPACTSIZE(obj) Using<CompactSizeFormatter<true>>(obj)
|
||||
#define LIMITED_STRING(obj,n) Using<LimitedStringFormatter<n>>(obj)
|
||||
#define LIMITED_VECTOR(obj,n) Using<LimitedVectorFormatter<n>>(obj)
|
||||
|
||||
/** Serialization wrapper class for integers in VarInt format. */
|
||||
template<VarIntMode Mode>
|
||||
@@ -790,6 +791,35 @@ struct DefaultFormatter
|
||||
static void Unser(Stream& s, T& t) { Unserialize(s, t); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Limited vector formatter. Throws an error if a vector is oversized.
|
||||
*/
|
||||
|
||||
template<size_t Limit, class Formatter = DefaultFormatter>
|
||||
struct LimitedVectorFormatter
|
||||
{
|
||||
template<typename Stream, typename V>
|
||||
void Unser(Stream& s, V& v)
|
||||
{
|
||||
Formatter formatter;
|
||||
v.clear();
|
||||
size_t size = ReadCompactSize(s);
|
||||
if (size > Limit) {
|
||||
throw std::ios_base::failure("Vector length limit exceeded");
|
||||
}
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back();
|
||||
formatter.Unser(s, v.back());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Stream, typename V>
|
||||
void Ser(Stream& s, const V& v)
|
||||
{
|
||||
VectorFormatter<Formatter>{}.Ser(s, v);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <test/util/setup_common.h>
|
||||
#include <util/strencodings.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
@@ -251,6 +252,30 @@ BOOST_AUTO_TEST_CASE(string_view)
|
||||
BOOST_CHECK_EQUAL(sv, s);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(limited_vector)
|
||||
{
|
||||
const std::vector<int> v = {1,2,3,4,-5,-6,-7,-8,-9,-10,10000,20000,-30000};
|
||||
|
||||
auto check = [&]<size_t N>() {
|
||||
DataStream ss;
|
||||
ss << v;
|
||||
try {
|
||||
std::vector<int> r;
|
||||
ss >> LIMITED_VECTOR(r, N);
|
||||
BOOST_CHECK_LE(r.size(), N);
|
||||
BOOST_CHECK(std::ranges::equal(r, v));
|
||||
} catch (const std::ios_base::failure&) {
|
||||
BOOST_CHECK_GT(v.size(), N);
|
||||
}
|
||||
};
|
||||
check.operator()<0>();
|
||||
check.operator()<10>();
|
||||
check.operator()<12>();
|
||||
check.operator()<13>();
|
||||
check.operator()<14>();
|
||||
check.operator()<100>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(class_methods)
|
||||
{
|
||||
int intval(100);
|
||||
|
||||
Reference in New Issue
Block a user