From 04586f50b17317ef257f6d3f81190021c93ad5ea Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 16 Dec 2012 17:26:01 +0900 Subject: [PATCH] Fixed BitfieldMan::getOffsetCompletedLength overflow on 32-bit systems --- src/BitfieldMan.cc | 4 ++-- test/BitfieldManTest.cc | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/BitfieldMan.cc b/src/BitfieldMan.cc index b0f202d4..e3c033f9 100644 --- a/src/BitfieldMan.cc +++ b/src/BitfieldMan.cc @@ -863,7 +863,7 @@ int64_t BitfieldMan::getOffsetCompletedLength } } else { if(isBitSet(start)) { - res += (start+1)*blockLength_-offset; + res += static_cast(start+1)*blockLength_-offset; } for(size_t i = start+1; i <= end-1; ++i) { if(isBitSet(i)) { @@ -871,7 +871,7 @@ int64_t BitfieldMan::getOffsetCompletedLength } } if(isBitSet(end)) { - res += offset+length-end*blockLength_; + res += offset+length-static_cast(end)*blockLength_; } } return res; diff --git a/test/BitfieldManTest.cc b/test/BitfieldManTest.cc index de1fce4b..709a028a 100644 --- a/test/BitfieldManTest.cc +++ b/test/BitfieldManTest.cc @@ -28,6 +28,7 @@ class BitfieldManTest:public CppUnit::TestFixture { CPPUNIT_TEST(testGetSparseMissingUnusedIndex_withMinSplitSize); CPPUNIT_TEST(testIsBitSetOffsetRange); CPPUNIT_TEST(testGetOffsetCompletedLength); + CPPUNIT_TEST(testGetOffsetCompletedLength_largeFile); CPPUNIT_TEST(testGetMissingUnusedLength); CPPUNIT_TEST(testSetBitRange); CPPUNIT_TEST(testGetAllMissingIndexes); @@ -62,6 +63,7 @@ public: void testGetSparseMissingUnusedIndex_withMinSplitSize(); void testIsBitSetOffsetRange(); void testGetOffsetCompletedLength(); + void testGetOffsetCompletedLength_largeFile(); void testGetMissingUnusedLength(); void testSetBitRange(); void testCountFilteredBlock(); @@ -484,6 +486,26 @@ void BitfieldManTest::testGetOffsetCompletedLength() 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() { int64_t totalLength = 1024*10+10;