Project

General

Profile

Actions

Bug #6008

closed

{a: 1}.hash not consistent over VM restarts

Added by jensb (Jens Berlips) about 12 years ago. Updated about 12 years ago.

Status:
Rejected
Assignee:
-
Target version:
ruby -v:
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-darwin11.0.0]
Backport:
[ruby-core:42523]

Description

$ ruby -e 'puts ({a: 1}.hash)'
-2419336229553239378
$ ruby -e 'puts ({a: 1}.hash)'
-4506930541181251952
$ ruby -e 'puts ({a: 1}.hash)'
2108665473238231010
$ ruby -e 'puts ({a: 1}.hash)'
-3675793335936991568

But if you go to rvm 1.8.7

ruby -e 'puts ({:a => 1}.hash)'
425023
ruby -e 'puts ({:a => 1}.hash)'
425023
ruby -e 'puts ({:a => 1}.hash)'
425023

The documentation read:

Generates a Fixnum hash value for this object. This function must have the property that a.eql?(b) implies a.hash == b.hash. The hash value is used by class Hash. Any hash value that exceeds the capacity of a Fixnum will be truncated before > being used.

Which implies that you should get the behaviour in 1.8.7.

Regards,
Jens

Updated by shyouhei (Shyouhei Urabe) about 12 years ago

  • Status changed from Open to Feedback

Jens Berlips wrote:

Which implies that you should get the behaviour in 1.8.7.

Why? I can't get it. I was wondering if you could describe it in detail.

Updated by mame (Yusuke Endoh) about 12 years ago

  • Status changed from Feedback to Rejected

When objects a and b are in different VM, a.eql?(b) does not
make sense. If you pass the either object from one VM to the
other in some way (such as using Marshal), a.eql?(b) will be
satisfied, and then a.hash == b.hash will be also satisfied
in the VM.

Theory aside, the behavior (changing the value in each run)
is intended for security reason. So we will not change the
behavior.

--
Yusuke Endoh

Updated by Anonymous about 12 years ago

Just to clarify some topics.

hashDoS vulnerability Eric pointed is the problem of String(-ish)#hash.
The fix for 1.8.7-p357 is for String(-ishes) so Fixnum#hash is still
stable (3). The most confusing part for the original poster is
Symbol#hash (== Kernel#object_id) looks stable for each process invocation.

Can you imagine what's happening inside?

% ruby187 -v
ruby 1.8.7 (2012-02-08 patchlevel 358) [x86_64-linux]
% ruby187 -e 'puts({:omg! => 1}.hash)'
437103
% ruby187 -e 'puts({:ZOMG! => 1}.hash)'
437103
% ruby187 -e 'puts({:omg! => 1}.hash == {:ZOMG! => 1}.hash)'
false #### ZOMG!!!!

So for an answer to Jens: In 1.8.7, "ruby -e 'puts ({:a => 1}.hash)'"
shows the same hash value by accident. But in Ruby, both on 1.8 and
1.9, you cannot expect the same hash value across processes.

Best regards,
// NaHi

Updated by jensb (Jens Berlips) about 12 years ago

Alright. Make sense.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0