Bug #21437
Updated by Stranger6667 (Dmitry Dygalo) 19 days 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.