Skip to content

The random number generation for srand() is weak #22968

Open
@scottchiefbaker

Description

Description

As part of my exploration into the guts of how Perl handles random numbers I've come across some interesting things. When rand() is called without calling srand() first, a "random" seed is chosen to kick off the drand48 PRNG.

On Linux (or any system with /dev/urandom) the seed is chosen by taking four bytes from urandom and generating a U32 from it. For 90% of use cases this is probably find for a general seed. This is good, well thought out, and the correct way to seed a PRNG.

On non-Linux systems, or when /dev/urandom fails to read, Perl fails back to very simple hash of: unixtime, Perl PID, Pointer address, and a hash of a pointer address. On it's face this should be a semi-decent random seed. It would be pretty difficult to guess or repeat a given seed.

However after doing some testing I'm finding that repeated calls to seed() return very similar values. Usually the values only vary between 2 to 4 bits.

Steps to Reproduce

Call the seed() function repeatedly

3106881140, 3106881131, 3106881119, 3106881110
662064185, 662064176, 662064164, 662064155
2315860893, 2315860881, 2315860869, 2315860857

I used the following code:

PerlIO_printf(Perl_debug_log, "SEED: %u/%u/%u/%u\n", seed(), seed(), seed(), seed());

at the end of the Perl_drand48_init_r() and then called rand() from the CLI and saw the very similar values.

Expected behavior

Whatever seed() function we employ, that has the sole purpose of seeding a PRNG, should return better, more spaced out, more randomish values. This is very easily solved by simply employing a better hash of the u value at the end of Perl_seed(pTHX). To be clear, this only affects systems where we do not read from /dev/urandom. Windows I'm looking at you.

This should be a pretty simple fix, and I'd like to take a run at it. Before I go too much farther I need to figure out the status of #22962 so I can move forward appropriately.

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions