Actions
Bug #21170
closedCorrupted Hash (bad VALUE and missing entry) when -1 returned from .hash
Description
class MyObj
attr_reader :hash
def initialize(val) = @hash = val
end
values = 0.downto(-16).to_a
hash = {}
values.each do |val|
hash[MyObj.new(val)] = val
end
p hash.values
# => [0, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, false, -16]
st_table reserves -1 as a special hash value to indicate that an entry has been deleted. So that that's a valid value to be returned from the hash function, do_hash replaces -1 with 0 so that it is not mistaken for the sentinel.
Previously, when upgrading an AR table to an ST table, rb_st_add_direct_with_hash was used which did not perform the same conversion, this could lead to a hash in a broken state where one if its entries which was supposed to exist being marked as a tombstone.
The hash could then become further corrupted when the ST table required resizing as the falsely tombstoned entry would be skipped but it would be counted in num entries, leading to an uninitialized entry at index 15.
Actions
Like1
Like1Like0Like0Like0Like0