Project

General

Profile

Actions

Bug #21437

closed

Date#hash may return different values for equal dates with large years

Added by Stranger6667 (Dmitry Dygalo) 6 days ago. Updated 1 day ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
3.2.8 - 3.4.4 (and older versions too)
[ruby-core:122516]

Description

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.

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:

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);
}

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.

Actions #1

Updated by Stranger6667 (Dmitry Dygalo) 5 days ago

  • Description updated (diff)
Actions #2

Updated by byroot (Jean Boussier) 5 days ago

  • Backport changed from 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN to 3.2: WONTFIX, 3.3: REQUIRED, 3.4: REQUIRED
Actions #3

Updated by Anonymous 1 day ago

  • Status changed from Open to Closed
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0