Merge pull request #2884 from gavinandresen/canonicalsizes2
Reject non-canonically-encoded CompactSize
This commit is contained in:
commit
f90b690a0d
3 changed files with 66 additions and 1 deletions
|
@ -3677,7 +3677,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||||
{
|
{
|
||||||
vector<uint256> vWorkQueue;
|
vector<uint256> vWorkQueue;
|
||||||
vector<uint256> vEraseQueue;
|
vector<uint256> vEraseQueue;
|
||||||
CDataStream vMsg(vRecv);
|
|
||||||
CTransaction tx;
|
CTransaction tx;
|
||||||
vRecv >> tx;
|
vRecv >> tx;
|
||||||
|
|
||||||
|
|
|
@ -216,18 +216,24 @@ uint64 ReadCompactSize(Stream& is)
|
||||||
unsigned short xSize;
|
unsigned short xSize;
|
||||||
READDATA(is, xSize);
|
READDATA(is, xSize);
|
||||||
nSizeRet = xSize;
|
nSizeRet = xSize;
|
||||||
|
if (nSizeRet < 253)
|
||||||
|
throw std::ios_base::failure("non-canonical ReadCompactSize()");
|
||||||
}
|
}
|
||||||
else if (chSize == 254)
|
else if (chSize == 254)
|
||||||
{
|
{
|
||||||
unsigned int xSize;
|
unsigned int xSize;
|
||||||
READDATA(is, xSize);
|
READDATA(is, xSize);
|
||||||
nSizeRet = xSize;
|
nSizeRet = xSize;
|
||||||
|
if (nSizeRet < 0x10000u)
|
||||||
|
throw std::ios_base::failure("non-canonical ReadCompactSize()");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint64 xSize;
|
uint64 xSize;
|
||||||
READDATA(is, xSize);
|
READDATA(is, xSize);
|
||||||
nSizeRet = xSize;
|
nSizeRet = xSize;
|
||||||
|
if (nSizeRet < 0x100000000LLu)
|
||||||
|
throw std::ios_base::failure("non-canonical ReadCompactSize()");
|
||||||
}
|
}
|
||||||
if (nSizeRet > (uint64)MAX_SIZE)
|
if (nSizeRet > (uint64)MAX_SIZE)
|
||||||
throw std::ios_base::failure("ReadCompactSize() : size too large");
|
throw std::ios_base::failure("ReadCompactSize() : size too large");
|
||||||
|
|
|
@ -39,7 +39,67 @@ BOOST_AUTO_TEST_CASE(varints)
|
||||||
ss >> VARINT(j);
|
ss >> VARINT(j);
|
||||||
BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
|
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()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
Loading…
Reference in a new issue