refactor: Return uint64_t from GetSerializeSize

Normally, the values are small enough to fit in size_t, but the risk
that it may not fit sometimes is a reason to use uint64_t consistently
for all architectures.

On 64-bit systems, this refactor is a no-op. On 32-bit systems, it could
avoid bugs in the theoretical and unexpected case where a 32-bit size_t
is too small and overflows.

For example, 32-bit Bitcoin Core versions with CVE-2025-46597 unfixed
may overflow while checking for the bad-blk-length violation when
receiving a malformed and bloated compact block.
This commit is contained in:
MarcoFalke
2025-10-28 16:05:50 +01:00
parent fad0c8680e
commit fa6c0bedd3

View File

@@ -1051,31 +1051,32 @@ struct ActionUnserialize {
class SizeComputer
{
protected:
size_t nSize{0};
uint64_t m_size{0};
public:
SizeComputer() = default;
void write(std::span<const std::byte> src)
{
this->nSize += src.size();
m_size += src.size();
}
/** Pretend _nSize bytes are written, without specifying them. */
void seek(size_t _nSize)
/** Pretend this many bytes are written, without specifying them. */
void seek(uint64_t num)
{
this->nSize += _nSize;
m_size += num;
}
template<typename T>
template <typename T>
SizeComputer& operator<<(const T& obj)
{
::Serialize(*this, obj);
return (*this);
return *this;
}
size_t size() const {
return nSize;
uint64_t size() const
{
return m_size;
}
};
@@ -1091,7 +1092,7 @@ inline void WriteCompactSize(SizeComputer &s, uint64_t nSize)
}
template <typename T>
size_t GetSerializeSize(const T& t)
uint64_t GetSerializeSize(const T& t)
{
return (SizeComputer() << t).size();
}