Project

General

Profile

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.

Back