From 795c631de64a8f5786431ce50806cb049ebf5839 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 13 Jul 2015 15:20:39 +0200 Subject: [PATCH] Stricter checks on RLP. --- libdevcore/RLP.cpp | 12 +++++++++++- libdevcore/RLP.h | 21 ++++++++++----------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/libdevcore/RLP.cpp b/libdevcore/RLP.cpp index 7e419e42b..fc49796a5 100644 --- a/libdevcore/RLP.cpp +++ b/libdevcore/RLP.cpp @@ -173,8 +173,14 @@ size_t RLP::length() const if (lengthSize > sizeof(ret)) // We did not check, but would most probably not fit in our memory. BOOST_THROW_EXCEPTION(UndersizeRLP()); + // No leading zeroes. + if (!m_data[1]) + BOOST_THROW_EXCEPTION(BadRLP()); for (unsigned i = 0; i < lengthSize; ++i) ret = (ret << 8) | m_data[i + 1]; + // Must be greater than the limit. + if (ret < c_rlpListStart - c_rlpDataImmLenStart - c_rlpMaxLengthBytes) + BOOST_THROW_EXCEPTION(BadRLP()); } else if (n <= c_rlpListIndLenZero) return n - c_rlpListStart; @@ -189,8 +195,12 @@ size_t RLP::length() const if (lengthSize > sizeof(ret)) // We did not check, but would most probably not fit in our memory. BOOST_THROW_EXCEPTION(UndersizeRLP()); + if (!m_data[1]) + BOOST_THROW_EXCEPTION(BadRLP()); for (unsigned i = 0; i < lengthSize; ++i) ret = (ret << 8) | m_data[i + 1]; + if (ret < 0x100 - c_rlpListStart - c_rlpMaxLengthBytes) + BOOST_THROW_EXCEPTION(BadRLP()); } // We have to be able to add payloadOffset to length without overflow. // This rejects roughly 4GB-sized RLPs on some platforms. @@ -203,7 +213,7 @@ size_t RLP::items() const { if (isList()) { - bytesConstRef d = payload().cropped(0, length()); + bytesConstRef d = payload(); size_t i = 0; for (; d.size(); ++i) d = d.cropped(sizeAsEncoded(d)); diff --git a/libdevcore/RLP.h b/libdevcore/RLP.h index 0a4d1b88b..a94c8ba55 100644 --- a/libdevcore/RLP.h +++ b/libdevcore/RLP.h @@ -232,25 +232,22 @@ public: template std::pair toPair() const { + if (itemCountStrict() != 2) + BOOST_THROW_EXCEPTION(BadCast()); std::pair ret; - if (isList()) - { - ret.first = (T)(*this)[0]; - ret.second = (U)(*this)[1]; - } + ret.first = (T)(*this)[0]; + ret.second = (U)(*this)[1]; return ret; } template std::array toArray() const { - if (itemCount() != N || !isList()) + if (itemCountStrict() != N) BOOST_THROW_EXCEPTION(BadCast()); std::array ret; for (size_t i = 0; i < N; ++i) - { ret[i] = (T)operator[](i); - } return ret; } @@ -281,7 +278,9 @@ public: template _N toHash(int _flags = Strict) const { requireGood(); - if (!isData() || (length() > _N::size && (_flags & FailIfTooBig)) || (length() < _N::size && (_flags & FailIfTooSmall))) + auto p = payload(); + auto l = p.size(); + if (!isData() || (l > _N::size && (_flags & FailIfTooBig)) || (l < _N::size && (_flags & FailIfTooSmall))) { if (_flags & ThrowOnFail) BOOST_THROW_EXCEPTION(BadCast()); @@ -290,8 +289,8 @@ public: } _N ret; - size_t s = std::min(_N::size, length()); - memcpy(ret.data() + _N::size - s, payload().data(), s); + size_t s = std::min(_N::size, l); + memcpy(ret.data() + _N::size - s, p.data(), s); return ret; }