From b31074cc6b2456306fe309d0a383b30b42691b92 Mon Sep 17 00:00:00 2001 From: Akos Kiss Date: Tue, 1 Nov 2016 15:43:16 +0100 Subject: [PATCH] Ensure that `Math.random()` really covers `[0,1)` interval (#1417) Legacy implementation made incorrect assumptions on how many bits of useful information is returned by libc's `rand()`. If `RAND_MAX` had more than 16 useful bits, it assumed that `rand()` could return 32 useful random bits. However, e.g., jerry-libc's `RAND_MAX` is `0x7fffffff`, which denotes 31 useful bits only. The consequence was that `Math.random()` covered only the lower half of the standard-mandated `[0,1)` interval. This path fixes the error and always uses the exact value of `RAND_MAX` to compute the random value, which will thus fully cover `[0,1)`. Fixes #1414 JerryScript-DCO-1.0-Signed-off-by: Akos Kiss akiss@inf.u-szeged.hu --- .../ecma/builtin-objects/ecma-builtin-math.c | 23 +++---------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-math.c b/jerry-core/ecma/builtin-objects/ecma-builtin-math.c index 07d4608af..30c3ac588 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-math.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-math.c @@ -507,28 +507,11 @@ static ecma_value_t ecma_builtin_math_object_random (ecma_value_t this_arg) /**< 'this' argument */ { JERRY_UNUSED (this_arg); - uint32_t rnd = 1; - uint32_t reps_count; -#if RAND_MAX < 0x100 - reps_count = 4; -#elif RAND_MAX < 0x10000 - reps_count = 2; -#else /* RAND_MAX >= 0x10000 */ - reps_count = 1; -#endif /* RAND_MAX < 0x100 */ - for (uint32_t i = 0; i < reps_count; i++) - { - uint32_t next_rand = (uint32_t) rand (); - rnd *= next_rand; - } + const ecma_number_t rand_max = (ecma_number_t) RAND_MAX; + const ecma_number_t rand_max_min_1 = (ecma_number_t) (RAND_MAX - 1); - const uint32_t max_uint32 = (uint32_t) -1; - ecma_number_t rand = (ecma_number_t) rnd; - rand /= (ecma_number_t) max_uint32; - rand *= (ecma_number_t) (max_uint32 - 1) / (ecma_number_t) max_uint32; - - return ecma_make_number_value (rand); + return ecma_make_number_value (((ecma_number_t) rand ()) / rand_max * rand_max_min_1 / rand_max); } /* ecma_builtin_math_object_random */ /**