diff options
| author | Graydon Hoare <graydon@mozilla.com> | 2013-02-19 07:06:20 -0800 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2013-02-19 07:06:36 -0800 |
| commit | 968ab03026d716f1e648aadebe8f199bdacbe4ad (patch) | |
| tree | 4a27364dcfcab05c01198462ab343e0a968ce5da | |
| parent | a8efa2133392cc846d4ea3cae14f0eb4eccb5f1e (diff) | |
| download | rust-968ab03026d716f1e648aadebe8f199bdacbe4ad.tar.gz rust-968ab03026d716f1e648aadebe8f199bdacbe4ad.zip | |
rt: fix memory-unsafe random seed logic, r=valgrindclean
| -rw-r--r-- | src/libcore/rand.rs | 44 | ||||
| -rw-r--r-- | src/rt/rust_builtin.cpp | 35 | ||||
| -rw-r--r-- | src/rt/rust_rng.cpp | 37 | ||||
| -rw-r--r-- | src/rt/rust_rng.h | 8 | ||||
| -rw-r--r-- | src/rt/rust_sched_loop.cpp | 2 | ||||
| -rw-r--r-- | src/rt/rustrt.def.in | 4 |
6 files changed, 64 insertions, 66 deletions
diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs index 97812602ce7..79dd29604e4 100644 --- a/src/libcore/rand.rs +++ b/src/libcore/rand.rs @@ -18,6 +18,7 @@ use u32; use uint; use util; use vec; +use libc::size_t; /// A type that can be randomly generated using an RNG pub trait Rand { @@ -120,9 +121,9 @@ enum rust_rng {} #[abi = "cdecl"] extern mod rustrt { - unsafe fn rand_seed() -> ~[u8]; - unsafe fn rand_new() -> *rust_rng; - unsafe fn rand_new_seeded2(&&seed: ~[u8]) -> *rust_rng; + unsafe fn rand_seed_size() -> size_t; + unsafe fn rand_gen_seed(buf: *mut u8, sz: size_t); + unsafe fn rand_new_seeded(buf: *u8, sz: size_t) -> *rust_rng; unsafe fn rand_next(rng: *rust_rng) -> u32; unsafe fn rand_free(rng: *rust_rng); } @@ -388,15 +389,18 @@ impl Rng for @RandRes { /// Create a new random seed for seeded_rng pub fn seed() -> ~[u8] { unsafe { - rustrt::rand_seed() + let n = rustrt::rand_seed_size() as uint; + let mut s = vec::from_elem(n, 0_u8); + do vec::as_mut_buf(s) |p, sz| { + rustrt::rand_gen_seed(p, sz as size_t) + } + s } } /// Create a random number generator with a system specified seed pub fn Rng() -> Rng { - unsafe { - @RandRes(rustrt::rand_new()) as Rng - } + seeded_rng(seed()) } /** @@ -405,9 +409,15 @@ pub fn Rng() -> Rng { * all other generators constructed with the same seed. The seed may be any * length. */ -pub fn seeded_rng(seed: &~[u8]) -> Rng { +pub fn seeded_rng(seed: &[u8]) -> Rng { + seeded_randres(seed) as Rng +} + +fn seeded_randres(seed: &[u8]) -> @RandRes { unsafe { - @RandRes(rustrt::rand_new_seeded2(*seed)) as Rng + do vec::as_imm_buf(seed) |p, sz| { + @RandRes(rustrt::rand_new_seeded(p, sz as size_t)) + } } } @@ -457,7 +467,7 @@ pub fn task_rng() -> Rng { match r { None => { unsafe { - let rng = @RandRes(rustrt::rand_new()); + let rng = seeded_randres(seed()); task::local_data::local_data_set(tls_rng_state, rng); rng as Rng } @@ -483,24 +493,24 @@ pub mod tests { #[test] pub fn rng_seeded() { let seed = rand::seed(); - let ra = rand::seeded_rng(&seed); - let rb = rand::seeded_rng(&seed); + let ra = rand::seeded_rng(seed); + let rb = rand::seeded_rng(seed); assert ra.gen_str(100u) == rb.gen_str(100u); } #[test] pub fn rng_seeded_custom_seed() { // much shorter than generated seeds which are 1024 bytes - let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8]; - let ra = rand::seeded_rng(&seed); - let rb = rand::seeded_rng(&seed); + let seed = [2u8, 32u8, 4u8, 32u8, 51u8]; + let ra = rand::seeded_rng(seed); + let rb = rand::seeded_rng(seed); assert ra.gen_str(100u) == rb.gen_str(100u); } #[test] pub fn rng_seeded_custom_seed2() { - let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8]; - let ra = rand::seeded_rng(&seed); + let seed = [2u8, 32u8, 4u8, 32u8, 51u8]; + let ra = rand::seeded_rng(seed); // Regression test that isaac is actually using the above vector let r = ra.next(); error!("%?", r); diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 85caf7b2e53..2c5b56f3fa4 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -128,49 +128,30 @@ vec_reserve_shared(type_desc* ty, rust_vec_box** vp, reserve_vec_exact(task, vp, n_elts * ty->size); } -extern "C" CDECL rust_vec* -rand_seed() { - size_t size = sizeof(ub4) * RANDSIZ; - rust_task *task = rust_get_current_task(); - rust_vec *v = (rust_vec *) task->kernel->malloc(vec_size<uint8_t>(size), - "rand_seed"); - v->fill = v->alloc = size; - rng_gen_seed(task->kernel, (uint8_t*) &v->data, size); - return v; +extern "C" CDECL size_t +rand_seed_size() { + return rng_seed_size(); } -extern "C" CDECL void * -rand_new() { +extern "C" CDECL void +rand_gen_seed(uint8_t* dest, size_t size) { rust_task *task = rust_get_current_task(); - rust_sched_loop *thread = task->sched_loop; - rust_rng *rng = (rust_rng *) task->malloc(sizeof(rust_rng), "rand_new"); - if (!rng) { - task->fail(); - return NULL; - } - rng_init(thread->kernel, rng, NULL); - return rng; + rng_gen_seed(task->kernel, dest, size); } extern "C" CDECL void * -rand_new_seeded(rust_vec_box* seed) { +rand_new_seeded(uint8_t* seed, size_t seed_size) { rust_task *task = rust_get_current_task(); - rust_sched_loop *thread = task->sched_loop; rust_rng *rng = (rust_rng *) task->malloc(sizeof(rust_rng), "rand_new_seeded"); if (!rng) { task->fail(); return NULL; } - rng_init(thread->kernel, rng, seed); + rng_init(task->kernel, rng, seed, seed_size); return rng; } -extern "C" CDECL void * -rand_new_seeded2(rust_vec_box** seed) { - return rand_new_seeded(*seed); -} - extern "C" CDECL uint32_t rand_next(rust_rng *rng) { rust_task *task = rust_get_current_task(); diff --git a/src/rt/rust_rng.cpp b/src/rt/rust_rng.cpp index 3d6bfdf7dbb..2c11691bf86 100644 --- a/src/rt/rust_rng.cpp +++ b/src/rt/rust_rng.cpp @@ -12,6 +12,12 @@ #include "rust_rng.h" #include "rust_util.h" +size_t +rng_seed_size() { + randctx rctx; + return sizeof(rctx.randrsl); +} + // Initialization helpers for ISAAC RNG void @@ -48,15 +54,17 @@ rng_gen_seed(rust_kernel* kernel, uint8_t* dest, size_t size) { } static void -isaac_init(rust_kernel *kernel, randctx *rctx, rust_vec_box* user_seed) { +isaac_init(rust_kernel *kernel, randctx *rctx, + uint8_t* user_seed, size_t seed_len) { memset(rctx, 0, sizeof(randctx)); char *env_seed = kernel->env->rust_seed; if (user_seed != NULL) { // ignore bytes after the required length - size_t seed_len = user_seed->body.fill < sizeof(rctx->randrsl) - ? user_seed->body.fill : sizeof(rctx->randrsl); - memcpy(&rctx->randrsl, user_seed->body.data, seed_len); + if (seed_len > sizeof(rctx->randrsl)) { + seed_len = sizeof(rctx->randrsl); + } + memcpy(&rctx->randrsl, user_seed, seed_len); } else if (env_seed != NULL) { ub4 seed = (ub4) atoi(env_seed); for (size_t i = 0; i < RANDSIZ; i ++) { @@ -64,15 +72,18 @@ isaac_init(rust_kernel *kernel, randctx *rctx, rust_vec_box* user_seed) { seed = (seed + 0x7ed55d16) + (seed << 12); } } else { - rng_gen_seed(kernel, (uint8_t*)&rctx->randrsl, sizeof(rctx->randrsl)); + rng_gen_seed(kernel, + (uint8_t*)&rctx->randrsl, + sizeof(rctx->randrsl)); } randinit(rctx, 1); } void -rng_init(rust_kernel* kernel, rust_rng* rng, rust_vec_box* user_seed) { - isaac_init(kernel, &rng->rctx, user_seed); +rng_init(rust_kernel* kernel, rust_rng* rng, + uint8_t *user_seed, size_t seed_len) { + isaac_init(kernel, &rng->rctx, user_seed, seed_len); rng->reseedable = !user_seed && !kernel->env->rust_seed; } @@ -85,15 +96,9 @@ rng_maybe_reseed(rust_kernel* kernel, rust_rng* rng) { if (bytes_generated < RESEED_THRESHOLD || !rng->reseedable) { return; } - - uint32_t new_seed[RANDSIZ]; - rng_gen_seed(kernel, (uint8_t*) new_seed, RANDSIZ * sizeof(uint32_t)); - - // Stir new seed into PRNG's entropy pool. - for (size_t i = 0; i < RANDSIZ; i++) { - rng->rctx.randrsl[i] ^= new_seed[i]; - } - + rng_gen_seed(kernel, + (uint8_t*)rng->rctx.randrsl, + sizeof(rng->rctx.randrsl)); randinit(&rng->rctx, 1); } diff --git a/src/rt/rust_rng.h b/src/rt/rust_rng.h index 2f1e680623f..3879b1138fa 100644 --- a/src/rt/rust_rng.h +++ b/src/rt/rust_rng.h @@ -14,7 +14,6 @@ #include "rand.h" class rust_kernel; -struct rust_vec_box; // Initialization helpers for ISAAC RNG @@ -23,8 +22,11 @@ struct rust_rng { bool reseedable; }; -void rng_gen_seed(rust_kernel* kernel, uint8_t* dest, size_t size); -void rng_init(rust_kernel *kernel, rust_rng *rng, rust_vec_box* user_seed); +size_t rng_seed_size(); +void rng_gen_seed(rust_kernel* kernel, + uint8_t* dest, size_t size); +void rng_init(rust_kernel *kernel, rust_rng *rng, + uint8_t *user_seed, size_t seed_len); uint32_t rng_gen_u32(rust_kernel *kernel, rust_rng *rng); // diff --git a/src/rt/rust_sched_loop.cpp b/src/rt/rust_sched_loop.cpp index 7143bf88d46..c215752d8dd 100644 --- a/src/rt/rust_sched_loop.cpp +++ b/src/rt/rust_sched_loop.cpp @@ -41,7 +41,7 @@ rust_sched_loop::rust_sched_loop(rust_scheduler *sched, int id, bool killed) : name("main") { LOGPTR(this, "new dom", (uintptr_t)this); - rng_init(kernel, &rng, NULL); + rng_init(kernel, &rng, NULL, 0); if (!tls_initialized) init_tls(); diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index a19f9053cbe..8fc8fceff86 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -17,9 +17,9 @@ rust_mktime new_task precise_time_ns rand_free -rand_new rand_new_seeded -rand_new_seeded2 +rand_seed_size +rand_gen_seed rand_next rand_seed rust_get_sched_id |
