From 051faf7e9d4e32142f95f7adb31d2f53f656cb66 Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Wed, 7 Nov 2018 12:36:23 -0800 Subject: add a test demonstrating an overflow in a deserialization edge case Also add a test that the highest legal index is accepted. --- src/test/blockencodings_tests.cpp | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index 5131fe8235..309b8d2d06 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -344,4 +344,49 @@ BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) { BOOST_CHECK_EQUAL(req1.indexes[3], req2.indexes[3]); } +BOOST_AUTO_TEST_CASE(TransactionsRequestDeserializationMaxTest) { + // Check that the highest legal index is decoded correctly + BlockTransactionsRequest req0; + req0.blockhash = InsecureRand256(); + req0.indexes.resize(1); + req0.indexes[0] = 0xffff; + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << req0; + + BlockTransactionsRequest req1; + stream >> req1; + BOOST_CHECK_EQUAL(req0.indexes.size(), req1.indexes.size()); + BOOST_CHECK_EQUAL(req0.indexes[0], req1.indexes[0]); +} + +BOOST_AUTO_TEST_CASE(TransactionsRequestDeserializationOverflowTest) { + // Any set of index deltas that starts with N values that sum to (0x10000 - N) + // causes the edge-case overflow that was originally not checked for. Such + // a request cannot be created by serializing a real BlockTransactionsRequest + // due to the overflow, so here we'll serialize from raw deltas. + BlockTransactionsRequest req0; + req0.blockhash = InsecureRand256(); + req0.indexes.resize(3); + req0.indexes[0] = 0x7000; + req0.indexes[1] = 0x10000 - 0x7000 - 2; + req0.indexes[2] = 0; + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << req0.blockhash; + WriteCompactSize(stream, req0.indexes.size()); + WriteCompactSize(stream, req0.indexes[0]); + WriteCompactSize(stream, req0.indexes[1]); + WriteCompactSize(stream, req0.indexes[2]); + + BlockTransactionsRequest req1; + try { + stream >> req1; + // before patch: deserialize above succeeds and this check fails, demonstrating the overflow + BOOST_CHECK(req1.indexes[1] < req1.indexes[2]); + // this shouldn't be reachable before or after patch + BOOST_CHECK(0); + } catch(std::ios_base::failure &) { + // deserialize should fail + } +} + BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.3 From 6bed4b374daf26233e96fa7863d4324a5bfa99c2 Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Wed, 7 Nov 2018 12:39:44 -0800 Subject: fix a deserialization overflow edge case A specially-constructed BlockTransactionsRequest can overflow in deserialization in a way that is currently harmless. --- src/blockencodings.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/blockencodings.h b/src/blockencodings.h index fad1f56f54..4bfe538250 100644 --- a/src/blockencodings.h +++ b/src/blockencodings.h @@ -52,12 +52,12 @@ public: } } - uint16_t offset = 0; + int32_t offset = 0; for (size_t j = 0; j < indexes.size(); j++) { - if (uint64_t(indexes[j]) + uint64_t(offset) > std::numeric_limits::max()) + if (int32_t(indexes[j]) + offset > std::numeric_limits::max()) throw std::ios_base::failure("indexes overflowed 16 bits"); indexes[j] = indexes[j] + offset; - offset = indexes[j] + 1; + offset = int32_t(indexes[j]) + 1; } } else { for (size_t i = 0; i < indexes.size(); i++) { -- cgit v1.2.3 From b08af10fb299dc3fdcd1f022619fb112c72e5d8e Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Tue, 13 Nov 2018 12:40:22 -0800 Subject: disallow oversized CBlockHeaderAndShortTxIDs Otherwise we'd reply with a bogus BlockTransactionsRequest trying to request indexes with overflowed deltas. --- src/blockencodings.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/blockencodings.h b/src/blockencodings.h index 4bfe538250..0c2b83ebcf 100644 --- a/src/blockencodings.h +++ b/src/blockencodings.h @@ -186,6 +186,9 @@ public: READWRITE(prefilledtxn); + if (BlockTxCount() > std::numeric_limits::max()) + throw std::ios_base::failure("indexes overflowed 16 bits"); + if (ser_action.ForRead()) FillShortTxIDSelector(); } -- cgit v1.2.3