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 committed 2025-10-30 17:51:53 +01:00
1 parent fad0c8680e
commit fa6c0bedd3
1 file changed
+11 -10
+11 -10
View File
@@ -1051,31 +1051,32 @@ struct ActionUnserialize {
class SizeComputer class SizeComputer
{ {
protected: protected:
size_t nSize{0}; uint64_t m_size{0};
public: public:
SizeComputer() = default; SizeComputer() = default;
void write(std::span<const std::byte> src) void write(std::span<const std::byte> src)
{ {
this->nSize += src.size(); m_size += src.size();
} }
/** Pretend _nSize bytes are written, without specifying them. */ /** Pretend this many bytes are written, without specifying them. */
void seek(size_t _nSize) void seek(uint64_t num)
{ {
this->nSize += _nSize; m_size += num;
} }
template<typename T> template <typename T>
SizeComputer& operator<<(const T& obj) SizeComputer& operator<<(const T& obj)
{ {
::Serialize(*this, obj); ::Serialize(*this, obj);
return (*this); return *this;
} }
size_t size() const { uint64_t size() const
return nSize; {
return m_size;
} }
}; };
@@ -1091,7 +1092,7 @@ inline void WriteCompactSize(SizeComputer &s, uint64_t nSize)
} }
template <typename T> template <typename T>
size_t GetSerializeSize(const T& t) uint64_t GetSerializeSize(const T& t)
{ {
return (SizeComputer() << t).size(); return (SizeComputer() << t).size();
} }