Bug #21437
Updated by Stranger6667 (Dmitry Dygalo) about 1 month ago
Parsing the same date string allocates new large integer objects with different pointer addresses, which then affects the hash value due to `d_lite_hash` behavior.
```ruby
require 'date'
# Small year - consistent hashes
Date.strptime('2024-5-9', '%Y-%m-%d').hash
#=> 3287407234087466140
Date.strptime('2024-5-9', '%Y-%m-%d').hash
#=> 3287407234087466140
# BUG - Large year - different hashes for identical date strings
Date.strptime('3171505571716611468830131104691-5-9', '%Y-%m-%d').hash
#=> 3525034678868094350
Date.strptime('3171505571716611468830131104691-5-9', '%Y-%m-%d').hash
#=> 2502076152602341316 # Different hash for same date!
```
In [ext/date/date_core.c](https://github.com/ruby/ruby/blob/v3_4_4/ext/date/date_core.c#L6936):
```c
static VALUE
d_lite_hash(VALUE self)
{
st_index_t v, h[4];
get_d1(self);
h[0] = m_nth(dat); // Could be different for equal large integers
// ...
v = rb_memhash(h, sizeof(h));
return ST2FIX(v);
}
```
Each call to `Date.strptime` with a large year allocates a new large integer for `m_nth(dat)`. The hash function uses this pointer address directly in `rb_memhash`, so equal dates parsed separately get different hashes.
This breaks the hash contract that equal objects must have equal hashes.