streams: Fix read-past-the-end and integer overflows

This commit is contained in:
MarcoFalke 2022-01-28 15:29:44 +01:00
parent 5e8e0b3d7f
commit fab02f7991
No known key found for this signature in database
GPG key ID: CE2B75697E69A548
2 changed files with 12 additions and 14 deletions

View file

@ -9,6 +9,7 @@
#include <serialize.h>
#include <span.h>
#include <support/allocators/zeroafterfree.h>
#include <util/overflow.h>
#include <algorithm>
#include <assert.h>
@ -281,36 +282,32 @@ public:
if (dst.size() == 0) return;
// Read from the beginning of the buffer
unsigned int nReadPosNext = nReadPos + dst.size();
if (nReadPosNext > vch.size()) {
auto next_read_pos{CheckedAdd<uint32_t>(nReadPos, dst.size())};
if (!next_read_pos.has_value() || next_read_pos.value() > vch.size()) {
throw std::ios_base::failure("CDataStream::read(): end of data");
}
memcpy(dst.data(), &vch[nReadPos], dst.size());
if (nReadPosNext == vch.size())
{
if (next_read_pos.value() == vch.size()) {
nReadPos = 0;
vch.clear();
return;
}
nReadPos = nReadPosNext;
nReadPos = next_read_pos.value();
}
void ignore(int nSize)
void ignore(size_t num_ignore)
{
// Ignore from the beginning of the buffer
if (nSize < 0) {
throw std::ios_base::failure("CDataStream::ignore(): nSize negative");
auto next_read_pos{CheckedAdd<uint32_t>(nReadPos, num_ignore)};
if (!next_read_pos.has_value() || next_read_pos.value() > vch.size()) {
throw std::ios_base::failure("CDataStream::ignore(): end of data");
}
unsigned int nReadPosNext = nReadPos + nSize;
if (nReadPosNext >= vch.size())
{
if (nReadPosNext > vch.size())
throw std::ios_base::failure("CDataStream::ignore(): end of data");
if (next_read_pos.value() == vch.size()) {
nReadPos = 0;
vch.clear();
return;
}
nReadPos = nReadPosNext;
nReadPos = next_read_pos.value();
}
void write(Span<const value_type> src)

View file

@ -6,6 +6,7 @@
#define BITCOIN_UTIL_OVERFLOW_H
#include <limits>
#include <optional>
#include <type_traits>
template <class T>