Skip to content

Commit 04586f5

Browse files
committed
Fixed BitfieldMan::getOffsetCompletedLength overflow on 32-bit systems
1 parent de1ca6d commit 04586f5

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

src/BitfieldMan.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -863,15 +863,15 @@ int64_t BitfieldMan::getOffsetCompletedLength
863863
}
864864
} else {
865865
if(isBitSet(start)) {
866-
res += (start+1)*blockLength_-offset;
866+
res += static_cast<int64_t>(start+1)*blockLength_-offset;
867867
}
868868
for(size_t i = start+1; i <= end-1; ++i) {
869869
if(isBitSet(i)) {
870870
res += blockLength_;
871871
}
872872
}
873873
if(isBitSet(end)) {
874-
res += offset+length-end*blockLength_;
874+
res += offset+length-static_cast<int64_t>(end)*blockLength_;
875875
}
876876
}
877877
return res;

test/BitfieldManTest.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class BitfieldManTest:public CppUnit::TestFixture {
2828
CPPUNIT_TEST(testGetSparseMissingUnusedIndex_withMinSplitSize);
2929
CPPUNIT_TEST(testIsBitSetOffsetRange);
3030
CPPUNIT_TEST(testGetOffsetCompletedLength);
31+
CPPUNIT_TEST(testGetOffsetCompletedLength_largeFile);
3132
CPPUNIT_TEST(testGetMissingUnusedLength);
3233
CPPUNIT_TEST(testSetBitRange);
3334
CPPUNIT_TEST(testGetAllMissingIndexes);
@@ -62,6 +63,7 @@ class BitfieldManTest:public CppUnit::TestFixture {
6263
void testGetSparseMissingUnusedIndex_withMinSplitSize();
6364
void testIsBitSetOffsetRange();
6465
void testGetOffsetCompletedLength();
66+
void testGetOffsetCompletedLength_largeFile();
6567
void testGetMissingUnusedLength();
6668
void testSetBitRange();
6769
void testCountFilteredBlock();
@@ -484,6 +486,26 @@ void BitfieldManTest::testGetOffsetCompletedLength()
484486
CPPUNIT_ASSERT_EQUAL((int64_t)0, bt.getOffsetCompletedLength(1024*20, 1));
485487
}
486488

489+
void BitfieldManTest::testGetOffsetCompletedLength_largeFile()
490+
{
491+
// Test for overflow on 32-bit systems.
492+
493+
// Total 4TiB, 4MiB block
494+
BitfieldMan bt(1 << 22, 1LL << 40);
495+
bt.setBit(1 << 11);
496+
bt.setBit((1 << 11)+1);
497+
bt.setBit((1 << 11)+2);
498+
499+
// The last piece is missing:
500+
CPPUNIT_ASSERT_EQUAL((int64_t)bt.getBlockLength()*3,
501+
bt.getOffsetCompletedLength(1LL << 33, 1 << 24));
502+
503+
// The first piece is missing:
504+
CPPUNIT_ASSERT_EQUAL((int64_t)bt.getBlockLength()*3,
505+
bt.getOffsetCompletedLength
506+
((1LL << 33) - bt.getBlockLength(), 1 << 24));
507+
}
508+
487509
void BitfieldManTest::testGetMissingUnusedLength()
488510
{
489511
int64_t totalLength = 1024*10+10;

0 commit comments

Comments
 (0)