]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: sample: fix random number upper-bound
authorVincent Bernat <vincent@bernat.im>
Wed, 10 Dec 2014 09:31:37 +0000 (10:31 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 10 Dec 2014 21:45:34 +0000 (22:45 +0100)
random() will generate a number between 0 and RAND_MAX. POSIX mandates
RAND_MAX to be at least 32767. GNU libc uses (1<<31 - 1) as
RAND_MAX.

In smp_fetch_rand(), a reduction is done with a multiply and shift to
avoid skewing the results. However, the shift was always 32 and hence
the numbers were not distributed uniformly in the specified range. We
fix that by dividing by RAND_MAX+1. gcc is smart enough to turn that
into a shift:

    0x000000000046ecc8 <+40>:    shr    $0x1f,%rax

src/sample.c

index 0ffc76daf3a940cfb0c961833bb128ae680ccca1..00345a8940ebacd5120a6087b9ed6e26a5de0c28 100644 (file)
@@ -1824,7 +1824,7 @@ smp_fetch_rand(struct proxy *px, struct session *s, void *l7, unsigned int opt,
 
        /* reduce if needed. Don't do a modulo, use all bits! */
        if (args && args[0].type == ARGT_UINT)
-               smp->data.uint = ((uint64_t)smp->data.uint * args[0].data.uint) >> 32;
+               smp->data.uint = ((uint64_t)smp->data.uint * args[0].data.uint) / ((u64)RAND_MAX+1);
 
        smp->type = SMP_T_UINT;
        smp->flags |= SMP_F_VOL_TEST | SMP_F_MAY_CHANGE;