mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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
This commit is contained in:
parent
3af6dda231
commit
04739ba617
7 changed files with 107 additions and 18 deletions
22
ChangeLog
22
ChangeLog
|
@ -1,3 +1,25 @@
|
||||||
|
Fri Jun 20 11:07:56 2008 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
Wed Jun 18 21:52:38 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
|
Wed Jun 18 21:52:38 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
|
||||||
|
|
||||||
* array.c (ary_new, rb_ary_initialize, rb_ary_store,
|
* array.c (ary_new, rb_ary_initialize, rb_ary_store,
|
||||||
|
|
|
@ -475,6 +475,7 @@ VALUE rb_range_beg_len(VALUE, long*, long*, long, int);
|
||||||
/* random.c */
|
/* random.c */
|
||||||
unsigned long rb_genrand_int32(void);
|
unsigned long rb_genrand_int32(void);
|
||||||
double rb_genrand_real(void);
|
double rb_genrand_real(void);
|
||||||
|
void rb_reset_random_seed(void);
|
||||||
/* re.c */
|
/* re.c */
|
||||||
#define rb_memcmp memcmp
|
#define rb_memcmp memcmp
|
||||||
int rb_memcicmp(const void*,const void*,long);
|
int rb_memcicmp(const void*,const void*,long);
|
||||||
|
|
2
inits.c
2
inits.c
|
@ -38,6 +38,7 @@ void Init_Precision(void);
|
||||||
void Init_sym(void);
|
void Init_sym(void);
|
||||||
void Init_id(void);
|
void Init_id(void);
|
||||||
void Init_process(void);
|
void Init_process(void);
|
||||||
|
void Init_RandomSeed(void);
|
||||||
void Init_Random(void);
|
void Init_Random(void);
|
||||||
void Init_Range(void);
|
void Init_Range(void);
|
||||||
void Init_Rational(void);
|
void Init_Rational(void);
|
||||||
|
@ -58,6 +59,7 @@ void Init_Encoding(void);
|
||||||
void
|
void
|
||||||
rb_call_inits()
|
rb_call_inits()
|
||||||
{
|
{
|
||||||
|
Init_RandomSeed();
|
||||||
Init_sym();
|
Init_sym();
|
||||||
Init_id();
|
Init_id();
|
||||||
Init_var_tables();
|
Init_var_tables();
|
||||||
|
|
76
random.c
76
random.c
|
@ -199,6 +199,7 @@ rb_genrand_real(void)
|
||||||
return genrand_real();
|
return genrand_real();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int seed_initialized = 0;
|
||||||
static VALUE saved_seed = INT2FIX(0);
|
static VALUE saved_seed = INT2FIX(0);
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -259,27 +260,21 @@ rand_init(VALUE vseed)
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
#define DEFAULT_SEED_LEN (4 * sizeof(long))
|
||||||
random_seed(void)
|
|
||||||
|
static void
|
||||||
|
fill_random_seed(char *ptr)
|
||||||
{
|
{
|
||||||
static int n = 0;
|
static int n = 0;
|
||||||
|
unsigned long *seed;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
int fd;
|
int fd;
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
char *buf = (char*)ptr;
|
||||||
|
|
||||||
int seed_len;
|
seed = (unsigned long *)buf;
|
||||||
BDIGIT *digits;
|
|
||||||
unsigned long *seed;
|
|
||||||
NEWOBJ(big, struct RBignum);
|
|
||||||
OBJSETUP(big, rb_cBignum, T_BIGNUM);
|
|
||||||
|
|
||||||
seed_len = 4 * sizeof(long);
|
memset(buf, 0, DEFAULT_SEED_LEN);
|
||||||
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);
|
|
||||||
|
|
||||||
#ifdef S_ISCHR
|
#ifdef S_ISCHR
|
||||||
if ((fd = open("/dev/urandom", O_RDONLY
|
if ((fd = open("/dev/urandom", O_RDONLY
|
||||||
|
@ -294,7 +289,7 @@ random_seed(void)
|
||||||
#endif
|
#endif
|
||||||
)) >= 0) {
|
)) >= 0) {
|
||||||
if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) {
|
if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) {
|
||||||
read(fd, seed, seed_len);
|
read(fd, seed, DEFAULT_SEED_LEN);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
@ -305,6 +300,20 @@ random_seed(void)
|
||||||
seed[1] ^= tv.tv_sec;
|
seed[1] ^= tv.tv_sec;
|
||||||
seed[2] ^= getpid() ^ (n++ << 16);
|
seed[2] ^= getpid() ^ (n++ << 16);
|
||||||
seed[3] ^= (unsigned long)&seed;
|
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. */
|
/* set leading-zero-guard if need. */
|
||||||
digits[RBIGNUM_LEN(big)-1] = digits[RBIGNUM_LEN(big)-2] <= 1 ? 1 : 0;
|
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);
|
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:
|
* call-seq:
|
||||||
* srand(number=0) => old_seed
|
* srand(number=0) => old_seed
|
||||||
|
@ -453,6 +470,9 @@ rb_f_rand(int argc, VALUE *argv, VALUE obj)
|
||||||
long val, max;
|
long val, max;
|
||||||
|
|
||||||
rb_scan_args(argc, argv, "01", &vmax);
|
rb_scan_args(argc, argv, "01", &vmax);
|
||||||
|
if (!seed_initialized) {
|
||||||
|
rand_init(random_seed());
|
||||||
|
}
|
||||||
switch (TYPE(vmax)) {
|
switch (TYPE(vmax)) {
|
||||||
case T_FLOAT:
|
case T_FLOAT:
|
||||||
if (RFLOAT_VALUE(vmax) <= LONG_MAX && RFLOAT_VALUE(vmax) >= LONG_MIN) {
|
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);
|
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
|
void
|
||||||
Init_Random(void)
|
Init_Random(void)
|
||||||
{
|
{
|
||||||
rand_init(random_seed());
|
Init_RandomSeed2();
|
||||||
rb_define_global_function("srand", rb_f_srand, -1);
|
rb_define_global_function("srand", rb_f_srand, -1);
|
||||||
rb_define_global_function("rand", rb_f_rand, -1);
|
rb_define_global_function("rand", rb_f_rand, -1);
|
||||||
rb_global_variable(&saved_seed);
|
rb_global_variable(&saved_seed);
|
||||||
|
|
12
string.c
12
string.c
|
@ -1820,13 +1820,21 @@ hash(const unsigned char * data, int len, unsigned int h)
|
||||||
int
|
int
|
||||||
rb_memhash(const void *ptr, long len)
|
rb_memhash(const void *ptr, long len)
|
||||||
{
|
{
|
||||||
return hash(ptr, len, 0);
|
static int hashseed_init = 0;
|
||||||
|
static unsigned int hashseed;
|
||||||
|
|
||||||
|
if (!hashseed_init) {
|
||||||
|
hashseed = rb_genrand_int32();
|
||||||
|
hashseed_init = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash(ptr, len, hashseed);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rb_str_hash(VALUE str)
|
rb_str_hash(VALUE str)
|
||||||
{
|
{
|
||||||
return hash((const void *)RSTRING_PTR(str), RSTRING_LEN(str), 0);
|
return rb_memhash((const void *)RSTRING_PTR(str), RSTRING_LEN(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -683,6 +683,17 @@ class TestString < Test::Unit::TestCase
|
||||||
assert(S("hello").hash != S("helLO").hash)
|
assert(S("hello").hash != S("helLO").hash)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_hash_random
|
||||||
|
str = 'abc'
|
||||||
|
a = [str.hash.to_s]
|
||||||
|
3.times {
|
||||||
|
EnvUtil.rubyexec("-e", "print #{str.dump}.hash") {|i,o,e|
|
||||||
|
a << o.read
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_not_equal([str.hash.to_s], a.uniq)
|
||||||
|
end
|
||||||
|
|
||||||
def test_hex
|
def test_hex
|
||||||
assert_equal(255, S("0xff").hex)
|
assert_equal(255, S("0xff").hex)
|
||||||
assert_equal(-255, S("-0xff").hex)
|
assert_equal(-255, S("-0xff").hex)
|
||||||
|
|
1
thread.c
1
thread.c
|
@ -2124,6 +2124,7 @@ rb_thread_atfork(void)
|
||||||
st_clear(vm->living_threads);
|
st_clear(vm->living_threads);
|
||||||
st_insert(vm->living_threads, thval, (st_data_t) th->thread_id);
|
st_insert(vm->living_threads, thval, (st_data_t) th->thread_id);
|
||||||
vm->sleeper = 0;
|
vm->sleeper = 0;
|
||||||
|
rb_reset_random_seed();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue