aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--random.c62
-rw-r--r--test/ruby/test_rand.rb9
3 files changed, 56 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog
index 6733d21786..1279775681 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+Thu Oct 22 06:20:48 2015 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
+
+ * random.c (Init_RandomSeed): move all Random::DEFAULT
+ construction bits to Init_RandomSeed2. Random::DEFAULT
+ and Ruby internal hashes are no longer shared their seed.
+ * random.c (Init_RandomSeed2): ditto. And, kill evil
+ rb_obj_reveal() stuff.
+
+ * random.c (init_hashseed): add MT argument.
+ * random.c: (init_siphash): ditto.
+
+ * test/ruby/test_rand.rb (TestRand#test_default_seed): new
+ test for Random::DEFAULT::seed.
+
Thu Oct 22 05:23:48 2015 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
* random.c (init_hashseed, init_siphash): extract initialize
diff --git a/random.c b/random.c
index 11b7a3febe..8a9ef3a5f5 100644
--- a/random.c
+++ b/random.c
@@ -1452,24 +1452,9 @@ static union {
uint32_t u32[(16 * sizeof(uint8_t) - 1) / sizeof(uint32_t)];
} sipseed;
-static VALUE
-init_randomseed(struct MT *mt)
-{
- uint32_t initial[DEFAULT_SEED_CNT];
- VALUE seed;
-
- fill_random_seed(initial);
- init_by_array(mt, initial, DEFAULT_SEED_CNT);
- seed = make_seed_value(initial);
- explicit_bzero(initial, DEFAULT_SEED_LEN);
- return seed;
-}
-
static void
-init_hashseed(void)
+init_hashseed(struct MT *mt)
{
- struct MT *mt = default_mt();
-
hashseed = genrand_int32(mt);
#if SIZEOF_ST_INDEX_T*CHAR_BIT > 4*8
hashseed <<= 32;
@@ -1486,9 +1471,8 @@ init_hashseed(void)
}
static void
-init_siphash(void)
+init_siphash(struct MT *mt)
{
- struct MT *mt = default_mt();
int i;
for (i = 0; i < numberof(sipseed.u32); ++i)
@@ -1512,28 +1496,48 @@ rb_memhash(const void *ptr, long len)
#endif
}
+/* Initialize Ruby internal seeds */
void
Init_RandomSeed(void)
{
- rb_random_t *r = &default_rand;
- struct MT *mt = &r->mt;
- VALUE seed = init_randomseed(mt);
+ /*
+ Don't reuse this MT for Random::DEFAULT. Random::DEFAULT::seed shouldn't
+ provide a hint that an attacker guess siphash's seed.
+ */
+ struct MT mt;
+ uint32_t initial_seed[DEFAULT_SEED_CNT];
- init_hashseed();
- init_siphash();
+ fill_random_seed(initial_seed);
+ init_by_array(&mt, initial_seed, DEFAULT_SEED_CNT);
- rb_global_variable(&r->seed);
- r->seed = seed;
+ init_hashseed(&mt);
+ init_siphash(&mt);
+
+ explicit_bzero(initial_seed, DEFAULT_SEED_LEN);
+}
+
+static VALUE
+init_randomseed(struct MT *mt)
+{
+ uint32_t initial[DEFAULT_SEED_CNT];
+ VALUE seed;
+
+ fill_random_seed(initial);
+ init_by_array(mt, initial, DEFAULT_SEED_CNT);
+ seed = make_seed_value(initial);
+ explicit_bzero(initial, DEFAULT_SEED_LEN);
+ return seed;
}
+/* construct Random::DEFAULT bits */
static void
Init_RandomSeed2(void)
{
- VALUE seed = default_rand.seed;
+ rb_random_t *r = &default_rand;
+ struct MT *mt = &r->mt;
- if (RB_TYPE_P(seed, T_BIGNUM)) {
- rb_obj_reveal(seed, rb_cBignum);
- }
+ r->seed = init_randomseed(mt);
+ rb_global_variable(&r->seed);
}
void
diff --git a/test/ruby/test_rand.rb b/test/ruby/test_rand.rb
index d2a1244b0b..db2d4578b8 100644
--- a/test/ruby/test_rand.rb
+++ b/test/ruby/test_rand.rb
@@ -524,4 +524,13 @@ END
[1, 2].sample(1, random: gen)
assert_equal(2, gen.limit, bug7935)
end
+
+ def test_default_seed
+ assert_separately([], <<-End)
+ seed = Random::DEFAULT::seed
+ rand1 = Random::DEFAULT::rand
+ rand2 = Random.new(seed).rand
+ assert_equal(rand1, rand2)
+ End
+ end
end