Merge pull request #2884 from gavinandresen/canonicalsizes2
Reject non-canonically-encoded CompactSize
This commit is contained in:
commit
f90b690a0d
@ -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;
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user