aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2013-10-19 23:03:04 -0700
committerGavin Andresen <gavinandresen@gmail.com>2013-10-19 23:03:04 -0700
commitf90b690a0d5fb147080da4ecdab1a99ce0b72042 (patch)
tree4a2cf254e83d5a26e343a41b5160e06944699dc5 /src
parentd3b0fa1d82d0883f2e18e95b91125dd19659a17a (diff)
parent8dc206a1e2715be83912e039465a049b708b94c1 (diff)
Merge pull request #2884 from gavinandresen/canonicalsizes2
Reject non-canonically-encoded CompactSize
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp1
-rw-r--r--src/serialize.h6
-rw-r--r--src/test/serialize_tests.cpp60
3 files changed, 66 insertions, 1 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 6c2898cff5..ba2e83ce76 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -3677,7 +3677,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
vector<uint256> vWorkQueue;
vector<uint256> vEraseQueue;
- CDataStream vMsg(vRecv);
CTransaction tx;
vRecv >> tx;
diff --git a/src/serialize.h b/src/serialize.h
index e3d9939bcc..ca3c962240 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -216,18 +216,24 @@ uint64 ReadCompactSize(Stream& is)
unsigned short xSize;
READDATA(is, xSize);
nSizeRet = xSize;
+ if (nSizeRet < 253)
+ throw std::ios_base::failure("non-canonical ReadCompactSize()");
}
else if (chSize == 254)
{
unsigned int xSize;
READDATA(is, xSize);
nSizeRet = xSize;
+ if (nSizeRet < 0x10000u)
+ throw std::ios_base::failure("non-canonical ReadCompactSize()");
}
else
{
uint64 xSize;
READDATA(is, xSize);
nSizeRet = xSize;
+ if (nSizeRet < 0x100000000LLu)
+ throw std::ios_base::failure("non-canonical ReadCompactSize()");
}
if (nSizeRet > (uint64)MAX_SIZE)
throw std::ios_base::failure("ReadCompactSize() : size too large");
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index 19ffdcab66..50139df09e 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -39,7 +39,67 @@ BOOST_AUTO_TEST_CASE(varints)
ss >> VARINT(j);
BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
}
+}
+
+BOOST_AUTO_TEST_CASE(compactsize)
+{
+ CDataStream ss(SER_DISK, 0);
+ vector<char>::size_type i, j;
+
+ for (i = 1; i <= MAX_SIZE; i *= 2)
+ {
+ WriteCompactSize(ss, i-1);
+ WriteCompactSize(ss, i);
+ }
+ for (i = 1; i <= MAX_SIZE; i *= 2)
+ {
+ j = ReadCompactSize(ss);
+ BOOST_CHECK_MESSAGE((i-1) == j, "decoded:" << j << " expected:" << (i-1));
+ j = ReadCompactSize(ss);
+ BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
+ }
+}
+
+static bool isCanonicalException(const std::ios_base::failure& ex)
+{
+ return std::string("non-canonical ReadCompactSize()") == ex.what();
+}
+
+BOOST_AUTO_TEST_CASE(noncanonical)
+{
+ // Write some non-canonical CompactSize encodings, and
+ // make sure an exception is thrown when read back.
+ CDataStream ss(SER_DISK, 0);
+ vector<char>::size_type n;
+
+ // zero encoded with three bytes:
+ ss.write("\xfd\x00\x00", 3);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+
+ // 0xfc encoded with three bytes:
+ ss.write("\xfd\xfc\x00", 3);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+
+ // 0xfd encoded with three bytes is OK:
+ ss.write("\xfd\xfd\x00", 3);
+ n = ReadCompactSize(ss);
+ BOOST_CHECK(n == 0xfd);
+
+ // zero encoded with five bytes:
+ ss.write("\xfe\x00\x00\x00\x00", 5);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+
+ // 0xffff encoded with five bytes:
+ ss.write("\xfe\xff\xff\x00\x00", 5);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+
+ // zero encoded with nine bytes:
+ ss.write("\xff\x00\x00\x00\x00\x00\x00\x00\x00", 9);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+ // 0x01ffffff encoded with nine bytes:
+ ss.write("\xff\xff\xff\xff\x01\x00\x00\x00\x00", 9);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
}
BOOST_AUTO_TEST_SUITE_END()