Fixed BitfieldMan::getOffsetCompletedLength overflow on 32-bit systems

pull/38/head
Tatsuhiro Tsujikawa 2012-12-16 17:26:01 +09:00
parent de1ca6d6b8
commit 04586f50b1
2 changed files with 24 additions and 2 deletions

View File

@ -863,7 +863,7 @@ int64_t BitfieldMan::getOffsetCompletedLength
} }
} else { } else {
if(isBitSet(start)) { if(isBitSet(start)) {
res += (start+1)*blockLength_-offset; res += static_cast<int64_t>(start+1)*blockLength_-offset;
} }
for(size_t i = start+1; i <= end-1; ++i) { for(size_t i = start+1; i <= end-1; ++i) {
if(isBitSet(i)) { if(isBitSet(i)) {
@ -871,7 +871,7 @@ int64_t BitfieldMan::getOffsetCompletedLength
} }
} }
if(isBitSet(end)) { if(isBitSet(end)) {
res += offset+length-end*blockLength_; res += offset+length-static_cast<int64_t>(end)*blockLength_;
} }
} }
return res; return res;

View File

@ -28,6 +28,7 @@ class BitfieldManTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testGetSparseMissingUnusedIndex_withMinSplitSize); CPPUNIT_TEST(testGetSparseMissingUnusedIndex_withMinSplitSize);
CPPUNIT_TEST(testIsBitSetOffsetRange); CPPUNIT_TEST(testIsBitSetOffsetRange);
CPPUNIT_TEST(testGetOffsetCompletedLength); CPPUNIT_TEST(testGetOffsetCompletedLength);
CPPUNIT_TEST(testGetOffsetCompletedLength_largeFile);
CPPUNIT_TEST(testGetMissingUnusedLength); CPPUNIT_TEST(testGetMissingUnusedLength);
CPPUNIT_TEST(testSetBitRange); CPPUNIT_TEST(testSetBitRange);
CPPUNIT_TEST(testGetAllMissingIndexes); CPPUNIT_TEST(testGetAllMissingIndexes);
@ -62,6 +63,7 @@ public:
void testGetSparseMissingUnusedIndex_withMinSplitSize(); void testGetSparseMissingUnusedIndex_withMinSplitSize();
void testIsBitSetOffsetRange(); void testIsBitSetOffsetRange();
void testGetOffsetCompletedLength(); void testGetOffsetCompletedLength();
void testGetOffsetCompletedLength_largeFile();
void testGetMissingUnusedLength(); void testGetMissingUnusedLength();
void testSetBitRange(); void testSetBitRange();
void testCountFilteredBlock(); void testCountFilteredBlock();
@ -484,6 +486,26 @@ void BitfieldManTest::testGetOffsetCompletedLength()
CPPUNIT_ASSERT_EQUAL((int64_t)0, bt.getOffsetCompletedLength(1024*20, 1)); CPPUNIT_ASSERT_EQUAL((int64_t)0, bt.getOffsetCompletedLength(1024*20, 1));
} }
void BitfieldManTest::testGetOffsetCompletedLength_largeFile()
{
// Test for overflow on 32-bit systems.
// Total 4TiB, 4MiB block
BitfieldMan bt(1 << 22, 1LL << 40);
bt.setBit(1 << 11);
bt.setBit((1 << 11)+1);
bt.setBit((1 << 11)+2);
// The last piece is missing:
CPPUNIT_ASSERT_EQUAL((int64_t)bt.getBlockLength()*3,
bt.getOffsetCompletedLength(1LL << 33, 1 << 24));
// The first piece is missing:
CPPUNIT_ASSERT_EQUAL((int64_t)bt.getBlockLength()*3,
bt.getOffsetCompletedLength
((1LL << 33) - bt.getBlockLength(), 1 << 24));
}
void BitfieldManTest::testGetMissingUnusedLength() void BitfieldManTest::testGetMissingUnusedLength()
{ {
int64_t totalLength = 1024*10+10; int64_t totalLength = 1024*10+10;