Project

General

Profile

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.

Back