wazoox has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks, I'm puzzled. I was trying to find out the answer to the following question : does a copy of a hash comes in the same order as the original ? ( I know that the same hash should come in a random order between executions). So I wrote this tiny script :

#!/usr/bin/perl use strict; use warnings; use Data::Dumper; my %t=qw( a A b B c C d D e E f F ); print Dumper \%t; print "***************\n"

Then I found something really weird : on a machine (Linux Mandrake 9.2), the order of %t is different each time you run the script. BUT on two other machine running RedHat 8.0 and RedHat ES 4, the hash is exactly the same every time!

Then I modified slightly the script :

#!/usr/bin/perl use strict; use warnings; use Data::Dumper; my %t=qw( a A b B c C d D e E f F ); my %l=%t; print Dumper \%t; print Dumper \%l; print "***************\n"

There it goes worse : ont the Mandrake machine, the two hashes %t and %l come sometimes in the same order, but not always :

$VAR1 = { 'c' => 'C', 'e' => 'E', 'd' => 'D', 'a' => 'A', 'f' => 'F', 'b' => 'B' }; $VAR1 = { 'c' => 'C', 'e' => 'E', 'd' => 'D', 'a' => 'A', 'f' => 'F', 'b' => 'B' }; *************** $VAR1 = { 'd' => 'D', 'a' => 'A', 'f' => 'F', 'c' => 'C', 'b' => 'B', 'e' => 'E' }; $VAR1 = { 'a' => 'A', 'd' => 'D', 'f' => 'F', 'b' => 'B', 'c' => 'C', 'e' => 'E' };

On the RedHat systems, they come ALWAYS the same! The perl versions are all different : MDK 9.2 has Perl 5.8.3, RH 8.0 perl 5.8.0, and RHES 5.8.5.

I've also tested the scripts on a Fedora Core 4 machine : the two copies of a hash comes in a different order, but always the same from a run to another....

I'd like to understand : how does RH obtains such a weird result ? Isn't this supposed to be a bug, apparently introduced deliberately by RedHat in their perl binaries ? Isn't it supposed to be a security hole ? What is the correct behaviour ?

update: I've tried on several machines, running Slackware, Debian, Ubuntu and Mac OS X, running the following snippet :

perl -e 'my %t=qw(a A b B c C d D e E); print join("", %t) . "\n"'

The 2 slackware, the 2 debian Sarge and the Ubuntu machine show the same behaviour : they always give the same result :

eEcCaAbBdD
The Mac OS X gives a different result each run. So now, it looks like the usual way isn't what I thought it to be... Is the Perl documentation out of sync, or is there something fishy in most Linux distros out there?

Replies are listed 'Best First'.
Re: Weird hash order behaviour on several RedHat releases.
by pboin (Deacon) on Mar 16, 2006 at 15:59 UTC

    The only thing you're guaranteed is consistency between keys() and values(). Basically, don't ever count on keys being in order and you'll be OK.

    From perldoc -f keys:

    The keys are returned in an apparently random order. The actual random order is subject to change in future versions of perl, but it is guaranteed to be the same order as either the "values" or "each" function produces (given that the hash has not been modified). Since Perl 5.8.1 the ordering is different even between different runs of Perl for security reasons (see "Algorithmic Complexity Attacks" in perlsec).
      I know that but
      Since Perl 5.8.1 the ordering is different even between different runs of Perl for security reasons (see "Algorithmic Complexity Attacks" in perlsec)."
      And I have the same order for every run, on 3 different machines running different RedHat flavours and perl releases. I've also played with PERL_HASH_SEED, no luck, it has absolutely no effect at all. Why do RedHat do that ?

        I just wonder if Red Hat didn't turn the randomization off on purpose in the name of compatibility to make sure that older applications didn't break when keys started to come back randomly. I have no doc that says that's the case, that just seems reasonable to me. Here's the option to do it:

        From perlrun:

        The default behaviour is to randomise unless the PERL_HASH_SEED is set. If Perl has been compiled with -DUSE_HASH_SEED_EXPLICIT, the default behaviour is not to randomise unless the PERL_HASH_SEED is set.
Re: Weird hash order behaviour on several RedHat releases.
by spiritway (Vicar) on Mar 17, 2006 at 03:53 UTC

    I get a similar result using Windows XP Home, and ActivePerl 5.8.7 Build 813.:

    $VAR1 = { 'e' => 'E', 'c' => 'C', 'a' => 'A', 'b' => 'B', 'd' => 'D', 'f' => 'F' }; ***************

    My reading of the docs would suggest that this order should change for different runs of perl. I'm not clear why it's doing this.