Bläddra i källkod

Merge remote branch 'public/rand_double2'

Nick Mathewson 14 år sedan
förälder
incheckning
485cab869d
4 ändrade filer med 29 tillägg och 2 borttagningar
  1. 20 0
      src/common/crypto.c
  2. 1 0
      src/common/crypto.h
  3. 4 2
      src/or/circuitbuild.c
  4. 4 0
      src/test/test_crypto.c

+ 20 - 0
src/common/crypto.c

@@ -2067,6 +2067,26 @@ crypto_rand_uint64(uint64_t max)
   }
 }
 
+/** Return a pseudorandom double d, chosen uniformly from the range
+ * 0.0 <= d < 1.0.
+ */
+double
+crypto_rand_double(void)
+{
+  /* We just use an unsigned int here; we don't really care about getting
+   * more than 32 bits of resolution */
+  unsigned int uint;
+  crypto_rand((char*)&uint, sizeof(uint));
+#if SIZEOF_INT == 4
+#define UINT_MAX_AS_DOUBLE 4294967296.0
+#elif SIZEOF_INT == 8
+#define UINT_MAX_AS_DOUBLE 1.8446744073709552e+19
+#else
+#error SIZEOF_INT is neither 4 nor 8
+#endif
+  return ((double)uint) / UINT_MAX_AS_DOUBLE;
+}
+
 /** Generate and return a new random hostname starting with <b>prefix</b>,
  * ending with <b>suffix</b>, and containing no less than
  * <b>min_rand_len</b> and no more than <b>max_rand_len</b> random base32

+ 1 - 0
src/common/crypto.h

@@ -210,6 +210,7 @@ int crypto_seed_rng(int startup);
 int crypto_rand(char *to, size_t n);
 int crypto_rand_int(unsigned int max);
 uint64_t crypto_rand_uint64(uint64_t max);
+double crypto_rand_double(void);
 
 char *crypto_random_hostname(int min_rand_len, int max_rand_len,
                              const char *prefix, const char *suffix);

+ 4 - 2
src/or/circuitbuild.c

@@ -815,18 +815,20 @@ build_time_t
 circuit_build_times_generate_sample(circuit_build_times_t *cbt,
                                     double q_lo, double q_hi)
 {
-  uint64_t r = crypto_rand_uint64(UINT64_MAX-1);
+  double randval = crypto_rand_double();
   build_time_t ret;
   double u;
 
   /* Generate between [q_lo, q_hi) */
+  /*XXXX This is what nextafter is supposed to be for; we should use it on the
+   * platforms that support it. */
   q_hi -= 1.0/(INT32_MAX);
 
   tor_assert(q_lo >= 0);
   tor_assert(q_hi < 1);
   tor_assert(q_lo < q_hi);
 
-  u = q_lo + ((q_hi-q_lo)*r)/(1.0*UINT64_MAX);
+  u = q_lo + (q_hi-q_lo)*randval;
 
   tor_assert(0 <= u && u < 1.0);
   /* circuit_build_times_calculate_timeout returns <= INT32_MAX */

+ 4 - 0
src/test/test_crypto.c

@@ -57,6 +57,7 @@ test_crypto_rng(void)
 {
   int i, j, allok;
   char data1[100], data2[100];
+  double d;
 
   /* Try out RNG. */
   test_assert(! crypto_seed_rng(0));
@@ -76,6 +77,9 @@ test_crypto_rng(void)
     big = crypto_rand_uint64(U64_LITERAL(5));
     if (big >= 5)
       allok = 0;
+    d = crypto_rand_double();
+    test_assert(d >= 0);
+    test_assert(d < 1.0);
     host = crypto_random_hostname(3,8,"www.",".onion");
     if (strcmpstart(host,"www.") ||
         strcmpend(host,".onion") ||