Skip to content

Commit

Permalink
🐛 Fix SequenceSet#merge with another SequenceSet
Browse files Browse the repository at this point in the history
Most methods convert their inputs into an array of range tuples.  For
efficiency, SequenceSet inputs just use the internal `@tuples` array
directly.  Unfortunately, the internal tuples arrays were also reused,
which could cause a variety of bugs.  Fortunately, the only bug I
experienced was that adding a frozen SequenceSet would result in frozen
tuples being added to a mutable set.  But this could also result in
modifications to one SequenceSet affecting another SequenceSet!
  • Loading branch information
nevans committed Jan 17, 2025
1 parent ced3f04 commit d89ae43
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 2 deletions.
4 changes: 2 additions & 2 deletions lib/net/imap/sequence_set.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1342,8 +1342,8 @@ def tuple_add(tuple)
modifying!
min, max = tuple
lower, lower_idx = tuple_gte_with_index(min - 1)
if lower.nil? then tuples << tuple
elsif (max + 1) < lower.first then tuples.insert(lower_idx, tuple)
if lower.nil? then tuples << [min, max]
elsif (max + 1) < lower.first then tuples.insert(lower_idx, [min, max])
else tuple_coalesce(lower, lower_idx, min, max)
end
end
Expand Down
5 changes: 5 additions & 0 deletions test/net/imap/test_sequence_set.rb
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,11 @@ def obj.to_sequence_set; 192_168.001_255 end
assert_equal seqset["1:3,5,7:9"], seqset["1,3,5,7:8"].merge(seqset["2,8:9"])
assert_equal seqset["1:*"], seqset["5:*"].merge(1..4)
assert_equal seqset["1:5"], seqset["1,3,5"].merge(seqset["2,4"])
# when merging frozen SequenceSet
set = SequenceSet.new
set.merge SequenceSet[1, 3, 5]
set.merge SequenceSet[2..33]
assert_equal seqset[1..33], set
end

test "set - other" do
Expand Down

0 comments on commit d89ae43

Please sign in to comment.