diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-06-20 02:46:17 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-06-20 02:46:17 +0000 |
commit | 04739ba61744046ac145b384aa9053429c80142f (patch) | |
tree | 848a727b1a400b56d7906f33ad564d8073aaf693 /random.c | |
parent | 3af6dda231c26524b65a02f8212d91ce37618aa9 (diff) |
* string.c (rb_memhash): randomize hash to avoid algorithmic
complexity attacks.
(rb_str_hash): use rb_memhash.
* include/ruby/intern.h (rb_reset_random_seed): declared.
* thread.c (rb_thread_atfork): call rb_reset_random_seed.
* inits.c (rb_call_inits): call Init_RandomSeed at first.
* random.c (seed_initialized): defined.
(fill_random_seed): extracted from random_seed.
(make_seed_value): extracted from random_seed.
(rb_f_rand): initialize random seed at first.
(initial_seed): defined.
(Init_RandomSeed): defined.
(Init_RandomSeed2): defined.
(rb_reset_random_seed): defined.
(Init_Random): call Init_RandomSeed2.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17465 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'random.c')
-rw-r--r-- | random.c | 76 |
1 files changed, 60 insertions, 16 deletions
@@ -199,6 +199,7 @@ rb_genrand_real(void) return genrand_real(); } +static int seed_initialized = 0; static VALUE saved_seed = INT2FIX(0); static VALUE @@ -259,27 +260,21 @@ rand_init(VALUE vseed) return old; } -static VALUE -random_seed(void) +#define DEFAULT_SEED_LEN (4 * sizeof(long)) + +static void +fill_random_seed(char *ptr) { static int n = 0; + unsigned long *seed; struct timeval tv; int fd; struct stat statbuf; + char *buf = (char*)ptr; - int seed_len; - BDIGIT *digits; - unsigned long *seed; - NEWOBJ(big, struct RBignum); - OBJSETUP(big, rb_cBignum, T_BIGNUM); + seed = (unsigned long *)buf; - seed_len = 4 * sizeof(long); - RBIGNUM_SET_SIGN(big, 1); - rb_big_resize((VALUE)big, seed_len / SIZEOF_BDIGITS + 1); - digits = RBIGNUM_DIGITS(big); - seed = (unsigned long *)RBIGNUM_DIGITS(big); - - memset(digits, 0, RBIGNUM_LEN(big) * SIZEOF_BDIGITS); + memset(buf, 0, DEFAULT_SEED_LEN); #ifdef S_ISCHR if ((fd = open("/dev/urandom", O_RDONLY @@ -294,7 +289,7 @@ random_seed(void) #endif )) >= 0) { if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) { - read(fd, seed, seed_len); + read(fd, seed, DEFAULT_SEED_LEN); } close(fd); } @@ -305,6 +300,20 @@ random_seed(void) seed[1] ^= tv.tv_sec; seed[2] ^= getpid() ^ (n++ << 16); seed[3] ^= (unsigned long)&seed; +} + +static VALUE +make_seed_value(char *ptr) +{ + BDIGIT *digits; + NEWOBJ(big, struct RBignum); + OBJSETUP(big, rb_cBignum, T_BIGNUM); + + RBIGNUM_SET_SIGN(big, 1); + rb_big_resize((VALUE)big, DEFAULT_SEED_LEN / SIZEOF_BDIGITS + 1); + digits = RBIGNUM_DIGITS(big); + + MEMCPY((char *)RBIGNUM_DIGITS(big), ptr, char, DEFAULT_SEED_LEN); /* set leading-zero-guard if need. */ digits[RBIGNUM_LEN(big)-1] = digits[RBIGNUM_LEN(big)-2] <= 1 ? 1 : 0; @@ -312,6 +321,14 @@ random_seed(void) return rb_big_norm((VALUE)big); } +static VALUE +random_seed(void) +{ + char buf[DEFAULT_SEED_LEN]; + fill_random_seed(buf); + return make_seed_value(buf); +} + /* * call-seq: * srand(number=0) => old_seed @@ -453,6 +470,9 @@ rb_f_rand(int argc, VALUE *argv, VALUE obj) long val, max; rb_scan_args(argc, argv, "01", &vmax); + if (!seed_initialized) { + rand_init(random_seed()); + } switch (TYPE(vmax)) { case T_FLOAT: if (RFLOAT_VALUE(vmax) <= LONG_MAX && RFLOAT_VALUE(vmax) >= LONG_MIN) { @@ -499,10 +519,34 @@ rb_f_rand(int argc, VALUE *argv, VALUE obj) return LONG2NUM(val); } +static char initial_seed[DEFAULT_SEED_LEN]; + +void +Init_RandomSeed(void) +{ + fill_random_seed(initial_seed); + init_by_array((unsigned long*)initial_seed, DEFAULT_SEED_LEN/sizeof(unsigned long)); + seed_initialized = 1; +} + +static VALUE +Init_RandomSeed2(void) +{ + saved_seed = make_seed_value(initial_seed); + memset(initial_seed, 0, DEFAULT_SEED_LEN); +} + +void +rb_reset_random_seed(void) +{ + seed_initialized = 0; + saved_seed = INT2FIX(0); +} + void Init_Random(void) { - rand_init(random_seed()); + Init_RandomSeed2(); rb_define_global_function("srand", rb_f_srand, -1); rb_define_global_function("rand", rb_f_rand, -1); rb_global_variable(&saved_seed); |