Skip to content

Commit b2659d0

Browse files
committed
Fix undefined behaviour and problems with large vectors
When the vector was very large (multiple words) the function was miscalculating. The partial difference also had an error
1 parent 1f078b8 commit b2659d0

File tree

1 file changed

+20
-21
lines changed

1 file changed

+20
-21
lines changed

include/boost/dynamic_bitset/dynamic_bitset.hpp

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ class dynamic_bitset
475475
inline static Block difference_partial(Block lhs, Block rhs,
476476
size_type first, size_type last) BOOST_NOEXCEPT
477477
{
478-
return (lhs & (~rhs)) & bit_mask(first, last);
478+
return (lhs & ~(rhs & bit_mask(first, last)));
479479
}
480480
inline static Block difference_full(Block lhs, Block rhs) BOOST_NOEXCEPT
481481
{
@@ -2329,15 +2329,15 @@ dynamic_bitset<Block, Allocator>& dynamic_bitset<Block, Allocator>::range_operat
23292329
if ( a_first_block == a_last_block ) {
23302330
// Filling only a sub-block of a block
23312331

2332-
Block assembled_b = b.m_bits[b_first_block] & bit_mask(b_first_bit_index, std::max(b_first_bit_index + len, bits_per_block - 1));
2332+
Block assembled_b = b.m_bits[b_first_block] & bit_mask(b_first_bit_index, std::min(b_first_bit_index + len, bits_per_block - 1));
23332333
if (b_first_bit_index >= a_first_bit_index) {
23342334
assembled_b >>= (b_first_bit_index - a_first_bit_index);
23352335
}else{
23362336
assembled_b <<= (a_first_bit_index - b_first_bit_index);
23372337
}
2338-
if (b_first_bit_index + len > bits_per_block - 1) {
2338+
if (b_first_bit_index + len > bits_per_block) {
23392339
assert(b_first_block + 1 <= b_last_block);
2340-
assembled_b = (b.m_bits[b_first_block + 1] & bit_mask(0, len - b_first_bit_index - bits_per_block + 1)) << (std::min(bits_per_block, len));
2340+
assembled_b = (b.m_bits[b_first_block + 1] & bit_mask(0, len + b_first_bit_index + 1 - bits_per_block)) << (bits_per_block + a_first_bit_index - b_first_bit_index);
23412341
}
23422342
m_bits[a_first_block] = partial_block_operation(m_bits[a_first_block],
23432343
assembled_b,
@@ -2347,13 +2347,12 @@ dynamic_bitset<Block, Allocator>& dynamic_bitset<Block, Allocator>::range_operat
23472347
const size_type a_first_full_block = a_first_block + a_first_block_shift;
23482348
const size_type a_last_full_block = a_last_block - a_last_block_shift;
23492349

2350-
size_type b_start_index_first_block = b_pos;
2350+
size_type b_start_index_first_block = b_pos % bits_per_block;
23512351
if (a_first_block_shift) {
23522352
//b_start_index_first_block += (bits_per_block - 1) - a_first_bit_index;
23532353
b_start_index_first_block = (bits_per_block + b_pos - a_pos) % bits_per_block;
23542354
}
23552355
const size_type b_last_index_first_block = bits_per_block - 1;
2356-
const size_type b_last_index_second_block = bits_per_block - 1 - b_start_index_first_block;
23572356

23582357
for (size_type i = a_first_full_block; i <= a_last_full_block; ++i) {
23592358
//blocks from a are the main iterator. b is adjusted to compute a
@@ -2366,7 +2365,7 @@ dynamic_bitset<Block, Allocator>& dynamic_bitset<Block, Allocator>::range_operat
23662365
Block assembled_b = (b.m_bits[b_block] & bit_mask(b_start_index_first_block, b_last_index_first_block)) >> b_start_index_first_block;
23672366
if (b_start_index_first_block != 0 && b_block + 1 <= b_last_block) {
23682367
assert(b_block + 1 <= b_last_block);
2369-
assembled_b |= (b.m_bits[b_block + 1] & bit_mask(0, b_last_index_second_block)) << b_last_index_first_block;
2368+
assembled_b |= (b.m_bits[b_block + 1] & bit_mask(0, b_start_index_first_block - 1)) << (b_last_index_first_block + 1 - b_start_index_first_block);
23702369
}
23712370

23722371
m_bits[i] = full_block_operation(m_bits[i], assembled_b);
@@ -2456,45 +2455,45 @@ bool dynamic_bitset<Block, Allocator>::boolean_range_operation_pair(
24562455
if ( a_first_block == a_last_block ) {
24572456
// Filling only a sub-block of a block
24582457

2459-
Block assembled_b = b.m_bits[b_first_block] & bit_mask(b_first_bit_index, std::max(b_first_bit_index + len, bits_per_block - 1));
2458+
Block assembled_b = b.m_bits[b_first_block] & bit_mask(b_first_bit_index, std::min(b_first_bit_index + len - 1, bits_per_block - 1));
24602459
if (b_first_bit_index >= a_first_bit_index) {
24612460
assembled_b >>= (b_first_bit_index - a_first_bit_index);
24622461
}else{
24632462
assembled_b <<= (a_first_bit_index - b_first_bit_index);
24642463
}
2465-
if (b_first_bit_index + len > bits_per_block - 1) {
2464+
if (b_first_bit_index + len > bits_per_block) {
24662465
assert(b_first_block + 1 <= b_last_block);
2467-
assembled_b = (b.m_bits[b_first_block + 1] & bit_mask(0, len - b_first_bit_index - bits_per_block + 1)) << (std::min(bits_per_block, len));
2466+
assembled_b = (b.m_bits[b_first_block + 1] & bit_mask(0, len + b_first_bit_index + 1 - bits_per_block)) << (bits_per_block + a_first_bit_index - b_first_bit_index);
24682467
}
24692468
if ( partial_block_operation(m_bits[a_first_block],
24702469
assembled_b,
24712470
a_first_bit_index, a_last_bit_index)){
2472-
return true;
2471+
return true;
24732472
}
24742473
}else{
24752474
// Regular blocks that will be broken similarly
24762475
const size_type a_first_full_block = a_first_block + a_first_block_shift;
24772476
const size_type a_last_full_block = a_last_block - a_last_block_shift;
24782477

2479-
size_type b_start_index_first_block = b_pos;
2478+
size_type b_start_index_first_block = b_pos % bits_per_block;
24802479
if (a_first_block_shift) {
2481-
//b_start_index_first_block += (bits_per_block - 1) - a_first_bit_index;
2482-
b_start_index_first_block = (bits_per_block + b_pos - a_pos) % bits_per_block;
2480+
b_start_index_first_block = (bits_per_block + b_first_bit_index - a_first_bit_index) % bits_per_block;
24832481
}
24842482
const size_type b_last_index_first_block = bits_per_block - 1;
2485-
const size_type b_last_index_second_block = bits_per_block - 1 - b_start_index_first_block;
2483+
2484+
size_type b_block = block_index( (a_first_full_block * bits_per_block) - a_pos + b_pos );
2485+
if(a_last_full_block >= a_first_full_block){
2486+
assert(block_index( (a_last_full_block * bits_per_block) - a_pos + b_pos ) <= b_last_block);
2487+
}
24862488

2487-
for (size_type i = a_first_full_block; i <= a_last_full_block; ++i) {
2489+
for (size_type i = a_first_full_block; i <= a_last_full_block; ++i, ++b_block) {
24882490
//blocks from a are the main iterator. b is adjusted to compute a
24892491
//full block operation
2490-
2491-
size_type b_block = block_index( (i * bits_per_block) - a_pos + b_pos );
2492-
//size_type b_start_index_first_block = bit_index(((i - a_first_full_block) * bits_per_block) - a_first_bit_index + b_pos);
2493-
assert(b_block <= b_last_block);
2492+
24942493
Block assembled_b = (b.m_bits[b_block] & bit_mask(b_start_index_first_block, b_last_index_first_block)) >> b_start_index_first_block;
24952494
if (b_start_index_first_block != 0 && b_block + 1 <= b_last_block) {
24962495
assert(b_block + 1 <= b_last_block);
2497-
assembled_b |= (b.m_bits[b_block + 1] & bit_mask(0, b_last_index_second_block)) << b_last_index_first_block;
2496+
assembled_b |= (b.m_bits[b_block + 1] & bit_mask(0, b_start_index_first_block - 1)) << (b_last_index_first_block + 1 - b_start_index_first_block);
24982497
}
24992498

25002499
if ( full_block_operation(m_bits[i], assembled_b)){

0 commit comments

Comments
 (0)