• E
    random: don't mix RAND_MAX with random_r · dd3688e4
    Eric Blake 提交于
    FreeBSD 10 recently changed their definition of RAND_MAX, to try
    and cover the fact that their evenly distributed results of rand()
    really are a smaller range than a full power of 2.  As a result,
    I did some investigation, and learned:
    
    1. POSIX requires random() to be evenly distributed across exactly
    31 bits.  glibc also guarantees this for rand(), but the two are
    unrelated, and POSIX only associates RAND_MAX with rand().
    Avoiding RAND_MAX altogether thus avoids a build failure on
    FreeBSD 10.
    
    2. Concatenating random bits from a PRNG will NOT provide uniform
    coverage over the larger value UNLESS the period of the original
    PRNG is at least as large as the number of bits being concatenated.
    Simple example: suppose that RAND_MAX were 1 with a period of 2**1
    (which means that the PRNG merely alternates between 0 and 1).
    Concatenating two successive rand() calls would then invariably
    result in 01 or 10, which is a rather non-uniform distribution
    (00 and 11 are impossible) and an even worse period (2**0, since
    our second attempt will get the same number as our first attempt).
    But a RAND_MAX of 1 with a period of 2**2 (alternating between
    0, 1, 1, 0) provides sane coverage of all four values, if properly
    tempered.  (Back-to-back calls would still only see half the values
    if we don't do some tempering).  We therefore want to guarantee a
    period of at least 2**64, preferably larger (as a tempering factor);
    POSIX only makes this guarantee for random() with 256 bytes of info.
    
    * src/util/virrandom.c (virRandomBits): Use constants that are
    accurate for the PRNG we are using, not an unrelated PRNG.
    (randomState): Ensure the period of our PRNG exceeds our usage.
    Signed-off-by: NEric Blake <eblake@redhat.com>
    dd3688e4
virrandom.c 5.1 KB