Skip to content

Commit 20df591

Browse files
committed
🐛 Fix SequenceSet#merge with another SequenceSet
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!
1 parent a01a59f commit 20df591

File tree

2 files changed

+7
-2
lines changed

2 files changed

+7
-2
lines changed

lib/net/imap/sequence_set.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,8 +1341,8 @@ def tuple_add(tuple)
13411341
modifying!
13421342
min, max = tuple
13431343
lower, lower_idx = tuple_gte_with_index(min - 1)
1344-
if lower.nil? then tuples << tuple
1345-
elsif (max + 1) < lower.first then tuples.insert(lower_idx, tuple)
1344+
if lower.nil? then tuples << [min, max]
1345+
elsif (max + 1) < lower.first then tuples.insert(lower_idx, [min, max])
13461346
else tuple_coalesce(lower, lower_idx, min, max)
13471347
end
13481348
end

test/net/imap/test_sequence_set.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,11 @@ def obj.to_sequence_set; 192_168.001_255 end
362362
assert_equal seqset["1:3,5,7:9"], seqset["1,3,5,7:8"].merge(seqset["2,8:9"])
363363
assert_equal seqset["1:*"], seqset["5:*"].merge(1..4)
364364
assert_equal seqset["1:5"], seqset["1,3,5"].merge(seqset["2,4"])
365+
# when merging frozen SequenceSet
366+
set = SequenceSet.new
367+
set.merge SequenceSet[1, 3, 5]
368+
set.merge SequenceSet[2..33]
369+
assert_equal seqset[1..33], set
365370
end
366371

367372
test "set - other" do

0 commit comments

Comments
 (0)