@@ -101,10 +101,85 @@ static struct { Class isa; } allocFailedException; uint32_t of_hash_seed; + +#ifndef HAVE_ARC4RANDOM +static void +initRandom(void) +{ + struct timeval tv; + +# ifdef HAVE_RANDOM + gettimeofday(&tv, NULL); + srandom((unsigned)(tv.tv_sec ^ tv.tv_usec)); +# else + gettimeofday(&tv, NULL); + srand((unsigned)(tv.tv_sec ^ tv.tv_usec)); +# endif +} +#endif + +uint16_t +of_random16(void) +{ +#if defined(HAVE_ARC4RANDOM) + return arc4random(); +#elif defined(HAVE_GETRANDOM) + uint16_t buffer; + + OF_ENSURE(getrandom(&buffer, sizeof(buffer), 0) == sizeof(buffer)); + + return buffer; +#else + static of_once_t onceControl = OF_ONCE_INIT; + + of_once(&onceControl, initRandom); +# ifdef HAVE_RANDOM + return random() & 0xFFFF; +# else + return rand() & 0xFFFF; +# endif +#endif +} + +uint32_t +of_random32(void) +{ +#if defined(HAVE_ARC4RANDOM) + return arc4random(); +#elif defined(HAVE_GETRANDOM) + uint32_t buffer; + + OF_ENSURE(getrandom(&buffer, sizeof(buffer), 0) == sizeof(buffer)); + + return buffer; +#else + return ((uint32_t)of_random16() << 16) | of_random16(); +#endif +} + +uint64_t +of_random64(void) +{ +#if defined(HAVE_ARC4RANDOM) + uint64_t buffer; + + arc4random_buf(&buffer, sizeof(buffer)); + + return buffer; +#elif defined(HAVE_GETRANDOM) + uint64_t buffer; + + OF_ENSURE(getrandom(&buffer, sizeof(buffer), 0) == sizeof(buffer)); + + return buffer; +#else + return ((uint64_t)of_random32() << 32) | of_random32(); +#endif +} static const char * typeEncodingForSelector(Class class, SEL selector) { Method method; @@ -250,11 +325,11 @@ #endif objc_setEnumerationMutationHandler(enumerationMutationHandler); do { - of_hash_seed = of_random(); + of_hash_seed = of_random32(); } while (of_hash_seed == 0); } + (void)unload {