Skip to content

Commit

Permalink
Fix overflow exception in BitArray
Browse files Browse the repository at this point in the history
  • Loading branch information
jimbowhales committed Nov 20, 2019
1 parent f31f5f0 commit 91d36e6
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 4 deletions.
13 changes: 13 additions & 0 deletions spec/std/bit_array_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,19 @@ describe "BitArray" do

ba[28..40].should eq(from_int(13, 0b1111111111111))
end

it "gets 32-bit boundaries" do
{32, 64, 128}.each do |ba_size|
ba = BitArray.new(ba_size, true)
{0, 31, 32}.each do |start|
{0, 31, 32}.each do |len|
size = {ba_size - start, len}.min
ba[start, len].size.should eq(size)
ba[start, len].should eq(BitArray.new(size, true))
end
end
end
end
end

it "toggles a bit" do
Expand Down
8 changes: 4 additions & 4 deletions src/bit_array.cr
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,18 @@ struct BitArray
bits = @bits[0]

bits >>= start
bits &= (1 << count) - 1
bits &= (1 << count) &- 1

BitArray.new(count).tap { |ba| ba.@bits[0] = bits }
elsif size <= 64
# Original fits in int64, we can use bitshifts
bits = @bits.as(UInt64*)[0]

bits >>= start
bits &= (1 << count) - 1
bits &= (1 << count) &- 1

if count <= 32
BitArray.new(count).tap { |ba| ba.@bits[0] = bits.to_u32 }
BitArray.new(count).tap { |ba| ba.@bits[0] = bits.to_u32! }
else
BitArray.new(count).tap { |ba| ba.@bits.as(UInt64*)[0] = bits }
end
Expand All @@ -169,7 +169,7 @@ struct BitArray
bits = @bits[start_bit_index + i + 1]

high_bits = bits
high_bits &= (1 << start_sub_index) - 1
high_bits &= (1 << start_sub_index) &- 1
high_bits <<= 32 - start_sub_index

ba.@bits[i] = low_bits | high_bits
Expand Down

0 comments on commit 91d36e6

Please sign in to comment.